]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/HandlerTest.php
Merge remote branch 'statusnet/1.0.x' into irc-plugin
[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 where one plugin short-circuits the process.
182      *
183      * @return void
184      */
185     public function testImplementsCallWithShortCircuit()
186     {
187         $plugin1 = $this->getMockPlugin('TestPlugin1', array('callback'));
188         $plugin1
189             ->expects($this->once())
190             ->method('callback')
191             ->will($this->returnValue(false));
192         $this->handler->addPlugin($plugin1);
193
194         $plugin2 = $this->getMockPlugin('TestPlugin2', array('callback'));
195         $plugin2
196             ->expects($this->exactly(0))
197             ->method('callback');
198         $this->handler->addPlugin($plugin2);
199
200         $this->assertFalse($this->handler->callback());
201     }
202
203     /**
204      * Tests the plugin handler executing a callback on all contained
205      * plugins where no plugins short-circuit the process.
206      *
207      * @return void
208      */
209     public function testImplementsCallWithoutShortCircuit()
210     {
211         foreach (range(1, 2) as $index) {
212             $plugin = $this->getMockPlugin('TestPlugin' . $index, array('callback'));
213             $plugin
214                 ->expects($this->once())
215                 ->method('callback');
216             $this->handler->addPlugin($plugin);
217         }
218
219         $this->assertTrue($this->handler->callback());
220     }
221
222     /**
223      * Tests a newly instantiated handler not having plugins associated with
224      * it.
225      *
226      * @depends testImplementsCountable
227      * @return void
228      */
229     public function testEmptyHandlerHasNoPlugins()
230     {
231         $this->assertEquals(0, count($this->handler));
232     }
233
234     /**
235      * Tests a newly instantiated handler not having autoloading enabled by
236      * default.
237      *
238      * @return void
239      */
240     public function testGetAutoloadDefaultsToNotAutoload()
241     {
242         $this->assertFalse($this->handler->getAutoload());
243     }
244
245     /**
246      * Tests setAutoload().
247      *
248      * @depends testGetAutoloadDefaultsToNotAutoload
249      * @return void
250      */
251     public function testSetAutoload()
252     {
253         $this->assertSame(
254             $this->handler->setAutoload(true),
255             $this->handler,
256             'setAutoload() does not provide a fluent interface'
257         );
258
259         $this->assertTrue(
260             $this->handler->getAutoload(),
261             'setAutoload() had no effect on getAutoload()'
262         );
263     }
264
265     /**
266      * Tests addPath() providing a fluent interface.
267      *
268      * @return void
269      */
270     public function testAddPathProvidesFluentInterface()
271     {
272         $handler = $this->handler->addPath(dirname(__FILE__));
273         $this->assertSame($this->handler, $handler);
274     }
275
276     /**
277      * Tests addPath() throwing an exception when it cannot read the
278      * directory.
279      *
280      * @return void
281      */
282     public function testAddPathThrowsExceptionOnUnreadableDirectory()
283     {
284         try {
285             $this->handler->addPath('/an/unreadable/directory/path');
286         } catch(Phergie_Plugin_Exception $e) {
287             $this->assertEquals(
288                 Phergie_Plugin_Exception::ERR_DIRECTORY_NOT_READABLE,
289                 $e->getCode()
290             );
291             return;
292         }
293
294         $this->fail('An expected exception has not been raised');
295     }
296
297     /**
298      * Tests adding a path to the plugin handler.
299      *
300      * @return void
301      */
302     public function testAddPath()
303     {
304         $pluginName = 'Mock';
305
306         try {
307             $this->handler->addPlugin($pluginName);
308         } catch(Phergie_Plugin_Exception $e) {
309             $this->assertEquals(
310                 Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
311                 $e->getCode()
312             );
313         }
314
315         if (!isset($e)) {
316             $this->fail('Plugin loaded, path was already present');
317         }
318
319         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
320
321         try {
322             $this->handler->addPlugin($pluginName);
323         } catch(Phergie_Plugin_Exception $e) {
324             $this->fail('Added path, plugin still not found');
325         }
326     }
327
328     /**
329      * Tests addPlugin() returning an added plugin instance.
330      *
331      * @return void
332      */
333     public function testAddPluginByInstanceReturnsPluginInstance()
334     {
335         $plugin = $this->getMockPlugin();
336         $returnedPlugin = $this->handler->addPlugin($plugin);
337         $this->assertSame(
338             $returnedPlugin,
339             $plugin,
340             'addPlugin() does not return the instance passed to it'
341         );
342     }
343
344     /**
345      * Tests adding a plugin to the handler using the plugin's short name.
346      *
347      * @return void
348      */
349     public function testAddPluginByShortName()
350     {
351         $pluginName = 'Mock';
352         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
353
354         $returnedPlugin = $this->handler->addPlugin($pluginName);
355         $this->assertTrue($this->handler->hasPlugin($pluginName));
356
357         $this->assertType(
358             'Phergie_Plugin_Mock',
359             $this->handler->getPlugin($pluginName)
360         );
361
362         $this->assertSame(
363             $this->handler->getPlugin($pluginName),
364             $returnedPlugin,
365             'Handler does not contain added plugin'
366         );
367     }
368
369
370     /**
371      * Tests adding a plugin instance to the handler.
372      *
373      * @return void
374      */
375     public function testAddPluginByInstance()
376     {
377         $plugin = $this->getMockPlugin();
378         $returnedPlugin = $this->handler->addPlugin($plugin);
379         $this->assertTrue($this->handler->hasPlugin('TestPlugin'));
380
381         $this->assertSame(
382             $plugin,
383             $returnedPlugin,
384             'addPlugin() does not return added plugin instance'
385         );
386
387         $this->assertSame(
388             $plugin,
389             $this->handler->getPlugin('TestPlugin'),
390             'getPlugin() does not return added plugin instance'
391         );
392     }
393
394     /**
395      * Tests addPlugin() throwing an exception when the plugin class file
396      * can't be found.
397      *
398      * @return void
399      */
400     public function testAddPluginThrowsExceptionWhenPluginFileNotFound()
401     {
402         try {
403             $this->handler->addPlugin('TestPlugin');
404         } catch(Phergie_Plugin_Exception $e) {
405             $this->assertEquals(
406                 Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
407                 $e->getCode()
408             );
409             return;
410         }
411
412         $this->fail('An expected exception has not been raised');
413     }
414
415     /**
416      * Recursively removes all files and subdirectories in a directory.
417      *
418      * @param string $path Directory path
419      * @return void
420      */
421     private function removeDirectory($path)
422     {
423         if (file_exists($path)) {
424             $it = new RecursiveIteratorIterator(
425                 new RecursiveDirectoryIterator($path),
426                 RecursiveIteratorIterator::CHILD_FIRST
427             );
428             foreach ($it as $entry) {
429                 if ($it->isDot()) {
430                     continue;
431                 }
432                 if ($entry->isDir()) {
433                     rmdir($entry->getPathname());
434                 } else {
435                     unlink($entry->getPathname());
436                 }
437             }
438         }
439     }
440
441     /**
442      * Tests addPlugin() throwing an exception when the plugin class file is
443      * found, but does not contain the plugin class as expected.
444      *
445      * @return void
446      */
447     public function testAddPluginThrowsExceptionWhenPluginClassNotFound()
448     {
449         $path = sys_get_temp_dir() . '/Phergie/Plugin';
450         $this->removeDirectory(dirname($path));
451         mkdir($path, 0777, true);
452         touch($path . '/TestPlugin.php');
453         $this->handler->addPath($path, 'Phergie_Plugin_');
454
455         try {
456             $this->handler->addPlugin('TestPlugin');
457         } catch(Phergie_Plugin_Exception $e) { }
458
459         if (isset($e)) {
460             $this->assertEquals(
461                 Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
462                 $e->getCode()
463             );
464         } else {
465             $this->fail('An expected exception has not been raised');
466         }
467
468         $this->removeDirectory(dirname($path));
469     }
470
471     /**
472      * Tests addPlugin() throwing an exception when trying to instantiate a
473      * class that doesn't extend Phergie_Plugin_Abstract.
474      *
475      * @return void
476      */
477     public function testAddPluginThrowsExceptionIfRequestingNonPlugin()
478     {
479         try {
480             $this->handler->addPlugin('Handler');
481         } catch(Phergie_Plugin_Exception $e) {
482             $this->assertEquals(
483                 Phergie_Plugin_Exception::ERR_INCORRECT_BASE_CLASS,
484                 $e->getCode()
485             );
486             return;
487         }
488
489         $this->fail('An expected exception has not been raised');
490     }
491
492     /**
493      * Tests addPlugin() throwing an exception when trying to instantiate a
494      * class that can't be instantiated.
495      *
496      * @return void
497      */
498     public function testAddPluginThrowsExceptionIfPluginNotInstantiable()
499     {
500         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
501         try {
502             $this->handler->addPlugin('TestNonInstantiablePluginFromFile');
503         } catch(Phergie_Plugin_Exception $e) {
504             $this->assertEquals(
505                 Phergie_Plugin_Exception::ERR_CLASS_NOT_INSTANTIABLE,
506                 $e->getCode()
507             );
508             return;
509         }
510
511         $this->fail('An expected exception has not been raised');
512     }
513
514     /**
515      * Tests adding a plugin by its short name with arguments passed to the
516      * plugin constructor.
517      *
518      * @return void
519      */
520     public function testAddPluginShortNamePassesArgsToConstructor()
521     {
522         $pluginName = 'Mock';
523         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
524
525         $arguments = array('a', 'b', 'c');
526         $plugin = $this->handler->addPlugin($pluginName, $arguments);
527
528         $this->assertAttributeSame(
529             $arguments,
530             'arguments',
531             $plugin,
532             'Arguments do not match'
533         );
534     }
535
536     /**
537      * Tests addPlugin() passing Phergie_Config to an instantiated plugin.
538      *
539      * @return void
540      */
541     public function testAddPluginPassesConstructorArguments()
542     {
543         $pluginName = 'Mock';
544         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
545         $plugin = $this->handler->addPlugin($pluginName);
546
547         $this->assertSame(
548             $this->config,
549             $plugin->getConfig(),
550             'Phergie_Config instances do not match'
551         );
552
553         $this->assertSame(
554             $this->events,
555             $plugin->getEventHandler(),
556             'Phergie_Event_Handler instances do not match'
557         );
558     }
559
560     /**
561      * Tests addPlugin() calling onLoad() on an instantiated plugin.
562      *
563      * @return void
564      */
565     public function testAddPluginCallsOnLoadOnInstantiatedPlugin()
566     {
567         $plugin = $this->getMockPlugin(null, array('onLoad'));
568         $plugin
569             ->expects($this->once())
570             ->method('onLoad');
571         $this->handler->addPlugin($plugin);
572     }
573
574     /**
575      * Tests addPlugin() returning the same plugin when called twice.
576      *
577      * @return void
578      */
579     public function testAddPluginReturnsSamePluginWhenAskedTwice()
580     {
581         $pluginName = 'Mock';
582         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
583         $plugin1 = $this->handler->addPlugin($pluginName);
584         $plugin2 = $this->handler->addPlugin($pluginName);
585         $this->assertSame($plugin1, $plugin2);
586     }
587
588     /**
589      * Tests getPlugin() throwing an exception when trying to get an
590      * unloaded plugin with autoload disabled.
591      *
592      * @depends testGetAutoloadDefaultsToNotAutoload
593      * @return void
594      */
595     public function testExceptionThrownWhenLoadingPluginWithoutAutoload()
596     {
597         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
598
599         try {
600             $this->handler->getPlugin('Mock');
601         } catch (Phergie_Plugin_Exception $expected) {
602             $this->assertEquals(
603                 Phergie_Plugin_Exception::ERR_PLUGIN_NOT_LOADED,
604                 $expected->getCode()
605             );
606             return;
607         }
608
609         $this->fail('An expected exception has not been raised');
610     }
611
612     /**
613      * Tests addPlugins() with a plugin short name and no plugin constructor
614      * arguments.
615      *
616      * @depends testAddPluginByShortName
617      * @depends testAddPluginByInstance
618      * @return void
619      */
620     public function testAddPluginsWithoutArguments()
621     {
622         $prefix = 'Phergie_Plugin_';
623         $this->handler->addPath(dirname(__FILE__), $prefix);
624
625         $plugin = 'Mock';
626         $this->handler->addPlugins(array($plugin));
627         $returnedPlugin = $this->handler->getPlugin($plugin);
628         $this->assertContains(
629             get_class($returnedPlugin),
630             $prefix . $plugin,
631             'Short name plugin not of expected class'
632         );
633     }
634
635     /**
636      * Tests addPlugins() with a plugin short name and plugin constructor
637      * arguments.
638      *
639      * @depends testAddPluginByShortName
640      * @depends testAddPluginByInstance
641      * @return void
642      */
643     public function testAddPluginsWithArguments()
644     {
645         $prefix = 'Phergie_Plugin_';
646         $this->handler->addPath(dirname(__FILE__), $prefix);
647
648         $arguments = array(1, 2, 3);
649         $plugin = array('Mock', $arguments);
650         $this->handler->addPlugins(array($plugin));
651         $returnedPlugin = $this->handler->getPlugin('Mock');
652         $this->assertEquals(
653             $arguments,
654             $returnedPlugin->getArguments(),
655             'Constructor arguments for instance plugin do not match'
656         );
657     }
658
659     /**
660      * Tests removePlugin() with a plugin instance.
661      *
662      * @depends testAddPluginByInstance
663      * @return void
664      */
665     public function testRemovePluginByInstance()
666     {
667         $plugin = $this->getMockPlugin();
668         $this->handler->addPlugin($plugin);
669         $this->handler->removePlugin($plugin);
670         $this->assertFalse(
671             $this->handler->hasPlugin($plugin->getName()),
672             'Plugin was not removed'
673         );
674     }
675
676     /**
677      * Tests removePlugin() with a plugin short name.
678      *
679      * @depends testAddPluginByShortName
680      * @return void
681      */
682     public function testRemovePluginByShortName()
683     {
684         $plugin = 'Mock';
685         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
686
687         $this->handler->addPlugin($plugin);
688         $this->handler->removePlugin($plugin);
689         $this->assertFalse(
690             $this->handler->hasPlugin($plugin),
691             'Plugin was not removed'
692         );
693     }
694
695     /**
696      * Tests getPlugin() when the plugin is not already loaded and
697      * autoloading is disabled.
698      *
699      * @depends testSetAutoload
700      * @return void
701      */
702     public function testGetPluginWithAutoloadEnabled()
703     {
704         $this->handler->setAutoload(true);
705         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
706         $plugin = $this->handler->getPlugin('Mock');
707         $this->assertType(
708             'Phergie_Plugin_Mock',
709             $plugin,
710             'Retrieved plugin not of expected class'
711         );
712     }
713
714     /**
715      * Tests getPlugins().
716      *
717      * @depends testGetPluginWithAutoloadEnabled
718      * @return void
719      */
720     public function testGetPlugins()
721     {
722         $plugin1 = $this->getMockPlugin('TestPlugin1');
723         $this->handler->addPlugin($plugin1);
724
725         $plugin2 = $this->getMockPlugin('TestPlugin2');
726         $this->handler->addPlugin($plugin2);
727
728         $expected = array(
729             'testplugin1' => $plugin1,
730             'testplugin2' => $plugin2,
731         );
732
733         $actual = $this->handler->getPlugins();
734         $this->assertEquals($expected, $actual);
735
736         $actual = $this->handler->getPlugins(array('testplugin1', 'testplugin2'));
737         $this->assertEquals($expected, $actual);
738     }
739 }