]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/HandlerTest.php
Merge in Phergie changes
[quix0rs-gnu-social.git] / plugins / Irc / extlib / phergie / Tests / Phergie / Plugin / HandlerTest.php
1 <?php
2 /**
3  * Phergie
4  *
5  * PHP version 5
6  *
7  * LICENSE
8  *
9  * This source file is subject to the new BSD license that is bundled
10  * with this package in the file LICENSE.
11  * It is also available through the world-wide-web at this URL:
12  * http://phergie.org/license
13  *
14  * @category  Phergie
15  * @package   Phergie_Tests
16  * @author    Phergie Development Team <team@phergie.org>
17  * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
18  * @license   http://phergie.org/license New BSD License
19  * @link      http://pear.phergie.org/package/Phergie_Tests
20  */
21
22 /**
23  * Unit test suite for Pherge_Plugin_Handler.
24  *
25  * @category Phergie
26  * @package  Phergie_Tests
27  * @author   Phergie Development Team <team@phergie.org>
28  * @license  http://phergie.org/license New BSD License
29  * @link     http://pear.phergie.org/package/Phergie_Tests
30  */
31 class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase
32 {
33     /**
34      * Plugin handler instance being tested
35      *
36      * @var Phergie_Plugin_Handler
37      */
38     protected $handler;
39
40     /**
41      * Mock Phergie_Config instance passed to the plugin handler constructor
42      *
43      * @var Phergie_Config
44      */
45     protected $config;
46
47     /**
48      * Mock Phergie_Event_Handler instance passed to the plugin handler
49      * constructor
50      *
51      * @var Phergie_Event_Handler
52      */
53     protected $events;
54
55     /**
56      * Returns a mock plugin instance.
57      *
58      * @param string $name    Optional short name for the mock plugin, defaults
59      *        to 'TestPlugin'
60      * @param array  $methods Optional list of methods to override
61      *
62      * @return Phergie_Plugin_Abstract
63      */
64     protected function getMockPlugin($name = 'TestPlugin', array $methods = array())
65     {
66         $methods[] = 'getName';
67         $plugin = $this->getMock('Phergie_Plugin_Abstract', $methods);
68         $plugin
69             ->expects($this->any())
70             ->method('getName')
71             ->will($this->returnValue($name));
72         return $plugin;
73     }
74
75     /**
76      * Sets up a new handler instance before each test.
77      *
78      * @return void
79      */
80     public function setUp()
81     {
82         $this->config = $this->getMock('Phergie_Config');
83         $this->events = $this->getMock('Phergie_Event_Handler');
84         $this->handler = new Phergie_Plugin_Handler(
85             $this->config,
86             $this->events
87         );
88     }
89
90     /**
91      * Tests iterability of the plugin handler.
92      *
93      * @return void
94      */
95     public function testImplementsIteratorAggregate()
96     {
97         $reflection = new ReflectionObject($this->handler);
98
99         $this->assertTrue(
100             $reflection->implementsInterface('IteratorAggregate'),
101             'Handler does not implement IteratorAggregate'
102         );
103
104         $this->assertType(
105             'Iterator',
106             $this->handler->getIterator(),
107             'getIterator() must return an iterator'
108         );
109     }
110
111     /**
112      * Tests countability of the plugin handler.
113      *
114      * @return void
115      */
116     public function testImplementsCountable()
117     {
118         $reflection = new ReflectionObject($this->handler);
119
120         $this->assertTrue(
121             $reflection->implementsInterface('Countable'),
122             'Handler does not implement Countable'
123         );
124
125         $this->assertType(
126             'int',
127             count($this->handler),
128             'count() must return an integer'
129         );
130     }
131
132     /**
133      * Tests the plugin handler exposing added plugins as instance
134      * properties of the handler via isset().
135      *
136      * @return void
137      */
138     public function testImplementsIsset()
139     {
140         $pluginName = 'TestPlugin';
141         $this->assertFalse(isset($this->handler->{$pluginName}));
142         $plugin = $this->getMockPlugin($pluginName);
143         $this->handler->addPlugin($plugin);
144         $this->assertTrue(isset($this->handler->{$pluginName}));
145     }
146
147     /**
148      * Tests the plugin handler exposing added plugins as instance
149      * properties of the handler.
150      *
151      * @depends testImplementsIsset
152      * @return void
153      */
154     public function testImplementsGet()
155     {
156         $plugin = $this->getMockPlugin();
157         $this->handler->addPlugin($plugin);
158         $name = $plugin->getName();
159         $getPlugin = $this->handler->getPlugin($name);
160         $this->assertTrue(isset($this->handler->$name));
161         $get = $this->handler->$name;
162         $this->assertSame($getPlugin, $get);
163     }
164
165     /**
166      * Tests the plugin handler allowing for plugin removal via unset().
167      *
168      * @depends testImplementsGet
169      * @return void
170      */
171     public function testImplementsUnset()
172     {
173         $plugin = $this->getMockPlugin();
174         $this->handler->addPlugin($plugin);
175         unset($this->handler->{$plugin->getName()});
176         $this->assertFalse($this->handler->hasPlugin($plugin->getName()));
177     }
178
179     /**
180      * Tests the plugin handler executing a callback on all contained
181      * plugins.
182      *
183      * @return void
184      */
185     public function testImplementsCall()
186     {
187         foreach (range(1, 2) as $index) {
188             $plugin = $this->getMockPlugin('TestPlugin' . $index, array('callback'));
189             $plugin
190                 ->expects($this->once())
191                 ->method('callback');
192             $this->handler->addPlugin($plugin);
193         }
194
195         $this->assertTrue($this->handler->callback());
196     }
197
198     /**
199      * Tests a newly instantiated handler not having plugins associated with
200      * it.
201      *
202      * @depends testImplementsCountable
203      * @return void
204      */
205     public function testEmptyHandlerHasNoPlugins()
206     {
207         $this->assertEquals(0, count($this->handler));
208     }
209
210     /**
211      * Tests a newly instantiated handler not having autoloading enabled by
212      * default.
213      *
214      * @return void
215      */
216     public function testGetAutoloadDefaultsToNotAutoload()
217     {
218         $this->assertFalse($this->handler->getAutoload());
219     }
220
221     /**
222      * Tests setAutoload().
223      *
224      * @depends testGetAutoloadDefaultsToNotAutoload
225      * @return void
226      */
227     public function testSetAutoload()
228     {
229         $this->assertSame(
230             $this->handler->setAutoload(true),
231             $this->handler,
232             'setAutoload() does not provide a fluent interface'
233         );
234
235         $this->assertTrue(
236             $this->handler->getAutoload(),
237             'setAutoload() had no effect on getAutoload()'
238         );
239     }
240
241     /**
242      * Tests addPath() providing a fluent interface.
243      *
244      * @return void
245      */
246     public function testAddPathProvidesFluentInterface()
247     {
248         $handler = $this->handler->addPath(dirname(__FILE__));
249         $this->assertSame($this->handler, $handler);
250     }
251
252     /**
253      * Tests addPath() throwing an exception when it cannot read the
254      * directory.
255      *
256      * @return void
257      */
258     public function testAddPathThrowsExceptionOnUnreadableDirectory()
259     {
260         try {
261             $this->handler->addPath('/an/unreadable/directory/path');
262         } catch(Phergie_Plugin_Exception $e) {
263             $this->assertEquals(
264                 Phergie_Plugin_Exception::ERR_DIRECTORY_NOT_READABLE,
265                 $e->getCode()
266             );
267             return;
268         }
269
270         $this->fail('An expected exception has not been raised');
271     }
272
273     /**
274      * Tests adding a path to the plugin handler.
275      *
276      * @return void
277      */
278     public function testAddPath()
279     {
280         $pluginName = 'Mock';
281
282         try {
283             $this->handler->addPlugin($pluginName);
284         } catch(Phergie_Plugin_Exception $e) {
285             $this->assertEquals(
286                 Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
287                 $e->getCode()
288             );
289         }
290
291         if (!isset($e)) {
292             $this->fail('Plugin loaded, path was already present');
293         }
294
295         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
296
297         try {
298             $this->handler->addPlugin($pluginName);
299         } catch(Phergie_Plugin_Exception $e) {
300             $this->fail('Added path, plugin still not found');
301         }
302     }
303
304     /**
305      * Tests addPlugin() returning an added plugin instance.
306      *
307      * @return void
308      */
309     public function testAddPluginByInstanceReturnsPluginInstance()
310     {
311         $plugin = $this->getMockPlugin();
312         $returnedPlugin = $this->handler->addPlugin($plugin);
313         $this->assertSame(
314             $returnedPlugin,
315             $plugin,
316             'addPlugin() does not return the instance passed to it'
317         );
318     }
319
320     /**
321      * Tests adding a plugin to the handler using the plugin's short name.
322      *
323      * @return void
324      */
325     public function testAddPluginByShortName()
326     {
327         $pluginName = 'Mock';
328         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
329
330         $returnedPlugin = $this->handler->addPlugin($pluginName);
331         $this->assertTrue($this->handler->hasPlugin($pluginName));
332
333         $this->assertType(
334             'Phergie_Plugin_Mock',
335             $this->handler->getPlugin($pluginName)
336         );
337
338         $this->assertSame(
339             $this->handler->getPlugin($pluginName),
340             $returnedPlugin,
341             'Handler does not contain added plugin'
342         );
343     }
344
345
346     /**
347      * Tests adding a plugin instance to the handler.
348      *
349      * @return void
350      */
351     public function testAddPluginByInstance()
352     {
353         $plugin = $this->getMockPlugin();
354         $returnedPlugin = $this->handler->addPlugin($plugin);
355         $this->assertTrue($this->handler->hasPlugin('TestPlugin'));
356
357         $this->assertSame(
358             $plugin,
359             $returnedPlugin,
360             'addPlugin() does not return added plugin instance'
361         );
362
363         $this->assertSame(
364             $plugin,
365             $this->handler->getPlugin('TestPlugin'),
366             'getPlugin() does not return added plugin instance'
367         );
368     }
369
370     /**
371      * Tests addPlugin() throwing an exception when the plugin class file
372      * can't be found.
373      *
374      * @return void
375      */
376     public function testAddPluginThrowsExceptionWhenPluginFileNotFound()
377     {
378         try {
379             $this->handler->addPlugin('TestPlugin');
380         } catch(Phergie_Plugin_Exception $e) {
381             $this->assertEquals(
382                 Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
383                 $e->getCode()
384             );
385             return;
386         }
387
388         $this->fail('An expected exception has not been raised');
389     }
390
391     /**
392      * Recursively removes all files and subdirectories in a directory.
393      *
394      * @param string $path Directory path
395      * @return void
396      */
397     private function removeDirectory($path)
398     {
399         if (file_exists($path)) {
400             $it = new RecursiveIteratorIterator(
401                 new RecursiveDirectoryIterator($path),
402                 RecursiveIteratorIterator::CHILD_FIRST
403             );
404             foreach ($it as $entry) {
405                 if ($it->isDot()) {
406                     continue;
407                 }
408                 if ($entry->isDir()) {
409                     rmdir($entry->getPathname());
410                 } else {
411                     unlink($entry->getPathname());
412                 }
413             }
414         }
415     }
416
417     /**
418      * Tests addPlugin() throwing an exception when the plugin class file is
419      * found, but does not contain the plugin class as expected.
420      *
421      * @return void
422      */
423     public function testAddPluginThrowsExceptionWhenPluginClassNotFound()
424     {
425         $path = sys_get_temp_dir() . '/Phergie/Plugin';
426         $this->removeDirectory(dirname($path));
427         mkdir($path, 0777, true);
428         touch($path . '/TestPlugin.php');
429         $this->handler->addPath($path, 'Phergie_Plugin_');
430
431         try {
432             $this->handler->addPlugin('TestPlugin');
433         } catch(Phergie_Plugin_Exception $e) { }
434
435         if (isset($e)) {
436             $this->assertEquals(
437                 Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
438                 $e->getCode()
439             );
440         } else {
441             $this->fail('An expected exception has not been raised');
442         }
443
444         $this->removeDirectory(dirname($path));
445     }
446
447     /**
448      * Tests addPlugin() throwing an exception when trying to instantiate a
449      * class that doesn't extend Phergie_Plugin_Abstract.
450      *
451      * @return void
452      */
453     public function testAddPluginThrowsExceptionIfRequestingNonPlugin()
454     {
455         try {
456             $this->handler->addPlugin('Handler');
457         } catch(Phergie_Plugin_Exception $e) {
458             $this->assertEquals(
459                 Phergie_Plugin_Exception::ERR_INCORRECT_BASE_CLASS,
460                 $e->getCode()
461             );
462             return;
463         }
464
465         $this->fail('An expected exception has not been raised');
466     }
467
468     /**
469      * Tests addPlugin() throwing an exception when trying to instantiate a
470      * class that can't be instantiated.
471      *
472      * @return void
473      */
474     public function testAddPluginThrowsExceptionIfPluginNotInstantiable()
475     {
476         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
477         try {
478             $this->handler->addPlugin('TestNonInstantiablePluginFromFile');
479         } catch(Phergie_Plugin_Exception $e) {
480             $this->assertEquals(
481                 Phergie_Plugin_Exception::ERR_CLASS_NOT_INSTANTIABLE,
482                 $e->getCode()
483             );
484             return;
485         }
486
487         $this->fail('An expected exception has not been raised');
488     }
489
490     /**
491      * Tests adding a plugin by its short name with arguments passed to the
492      * plugin constructor.
493      *
494      * @return void
495      */
496     public function testAddPluginShortNamePassesArgsToConstructor()
497     {
498         $pluginName = 'Mock';
499         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
500
501         $arguments = array('a', 'b', 'c');
502         $plugin = $this->handler->addPlugin($pluginName, $arguments);
503
504         $this->assertAttributeSame(
505             $arguments,
506             'arguments',
507             $plugin,
508             'Arguments do not match'
509         );
510     }
511
512     /**
513      * Tests addPlugin() passing Phergie_Config to an instantiated plugin.
514      *
515      * @return void
516      */
517     public function testAddPluginPassesConstructorArguments()
518     {
519         $pluginName = 'Mock';
520         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
521         $plugin = $this->handler->addPlugin($pluginName);
522
523         $this->assertSame(
524             $this->config,
525             $plugin->getConfig(),
526             'Phergie_Config instances do not match'
527         );
528
529         $this->assertSame(
530             $this->events,
531             $plugin->getEventHandler(),
532             'Phergie_Event_Handler instances do not match'
533         );
534     }
535
536     /**
537      * Tests addPlugin() calling onLoad() on an instantiated plugin.
538      *
539      * @return void
540      */
541     public function testAddPluginCallsOnLoadOnInstantiatedPlugin()
542     {
543         $plugin = $this->getMockPlugin(null, array('onLoad'));
544         $plugin
545             ->expects($this->once())
546             ->method('onLoad');
547         $this->handler->addPlugin($plugin);
548     }
549
550     /**
551      * Tests addPlugin() returning the same plugin when called twice.
552      *
553      * @return void
554      */
555     public function testAddPluginReturnsSamePluginWhenAskedTwice()
556     {
557         $pluginName = 'Mock';
558         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
559         $plugin1 = $this->handler->addPlugin($pluginName);
560         $plugin2 = $this->handler->addPlugin($pluginName);
561         $this->assertSame($plugin1, $plugin2);
562     }
563
564     /**
565      * Tests getPlugin() throwing an exception when trying to get an
566      * unloaded plugin with autoload disabled.
567      *
568      * @depends testGetAutoloadDefaultsToNotAutoload
569      * @return void
570      */
571     public function testExceptionThrownWhenLoadingPluginWithoutAutoload()
572     {
573         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
574
575         try {
576             $this->handler->getPlugin('Mock');
577         } catch (Phergie_Plugin_Exception $expected) {
578             $this->assertEquals(
579                 Phergie_Plugin_Exception::ERR_PLUGIN_NOT_LOADED,
580                 $expected->getCode()
581             );
582             return;
583         }
584
585         $this->fail('An expected exception has not been raised');
586     }
587
588     /**
589      * Tests addPlugins() with a plugin short name and no plugin constructor
590      * arguments.
591      *
592      * @depends testAddPluginByShortName
593      * @depends testAddPluginByInstance
594      * @return void
595      */
596     public function testAddPluginsWithoutArguments()
597     {
598         $prefix = 'Phergie_Plugin_';
599         $this->handler->addPath(dirname(__FILE__), $prefix);
600
601         $plugin = 'Mock';
602         $this->handler->addPlugins(array($plugin));
603         $returnedPlugin = $this->handler->getPlugin($plugin);
604         $this->assertContains(
605             get_class($returnedPlugin),
606             $prefix . $plugin,
607             'Short name plugin not of expected class'
608         );
609     }
610
611     /**
612      * Tests addPlugins() with a plugin short name and plugin constructor
613      * arguments.
614      *
615      * @depends testAddPluginByShortName
616      * @depends testAddPluginByInstance
617      * @return void
618      */
619     public function testAddPluginsWithArguments()
620     {
621         $prefix = 'Phergie_Plugin_';
622         $this->handler->addPath(dirname(__FILE__), $prefix);
623
624         $arguments = array(1, 2, 3);
625         $plugin = array('Mock', $arguments);
626         $this->handler->addPlugins(array($plugin));
627         $returnedPlugin = $this->handler->getPlugin('Mock');
628         $this->assertEquals(
629             $arguments,
630             $returnedPlugin->getArguments(),
631             'Constructor arguments for instance plugin do not match'
632         );
633     }
634
635     /**
636      * Tests removePlugin() with a plugin instance.
637      *
638      * @depends testAddPluginByInstance
639      * @return void
640      */
641     public function testRemovePluginByInstance()
642     {
643         $plugin = $this->getMockPlugin();
644         $this->handler->addPlugin($plugin);
645         $this->handler->removePlugin($plugin);
646         $this->assertFalse(
647             $this->handler->hasPlugin($plugin->getName()),
648             'Plugin was not removed'
649         );
650     }
651
652     /**
653      * Tests removePlugin() with a plugin short name.
654      *
655      * @depends testAddPluginByShortName
656      * @return void
657      */
658     public function testRemovePluginByShortName()
659     {
660         $plugin = 'Mock';
661         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
662
663         $this->handler->addPlugin($plugin);
664         $this->handler->removePlugin($plugin);
665         $this->assertFalse(
666             $this->handler->hasPlugin($plugin),
667             'Plugin was not removed'
668         );
669     }
670
671     /**
672      * Tests getPlugin() when the plugin is not already loaded and
673      * autoloading is disabled.
674      *
675      * @depends testSetAutoload
676      * @return void
677      */
678     public function testGetPluginWithAutoloadEnabled()
679     {
680         $this->handler->setAutoload(true);
681         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
682         $plugin = $this->handler->getPlugin('Mock');
683         $this->assertType(
684             'Phergie_Plugin_Mock',
685             $plugin,
686             'Retrieved plugin not of expected class'
687         );
688     }
689
690     /**
691      * Tests getPlugins().
692      *
693      * @depends testGetPluginWithAutoloadEnabled
694      * @return void
695      */
696     public function testGetPlugins()
697     {
698         $plugin1 = $this->getMockPlugin('TestPlugin1');
699         $this->handler->addPlugin($plugin1);
700
701         $plugin2 = $this->getMockPlugin('TestPlugin2');
702         $this->handler->addPlugin($plugin2);
703
704         $expected = array(
705             'testplugin1' => $plugin1,
706             'testplugin2' => $plugin2,
707         );
708
709         $actual = $this->handler->getPlugins();
710         $this->assertEquals($expected, $actual);
711
712         $actual = $this->handler->getPlugins(array('testplugin1', 'testplugin2'));
713         $this->assertEquals($expected, $actual);
714     }
715
716     /**
717      * Tests the plugin receiving and using a predefined iterator instance.
718      *
719      * @depends testGetPlugins
720      * @return void
721      */
722     public function testSetIterator()
723     {
724         $plugin = $this->getMockPlugin('TestPlugin');
725         $this->handler->addPlugin($plugin);
726         $plugins = $this->handler->getPlugins();
727         $iterator = new ArrayIterator($plugins);
728         $this->handler->setIterator($iterator);
729         $this->assertSame($this->handler->getIterator(), $iterator);
730         $iterated = array();
731         foreach ($this->handler as $plugin) {
732             $iterated[strtolower($plugin->getName())] = $plugin;
733         }
734         $this->assertEquals($iterated, $plugins);
735     }
736 }