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
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
23 * Unit test suite for Pherge_Plugin_Handler.
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
31 class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase
34 * Plugin handler instance being tested
36 * @var Phergie_Plugin_Handler
41 * Mock Phergie_Config instance passed to the plugin handler constructor
48 * Mock Phergie_Event_Handler instance passed to the plugin handler
51 * @var Phergie_Event_Handler
56 * Returns a mock plugin instance.
58 * @param string $name Optional short name for the mock plugin, defaults
60 * @param array $methods Optional list of methods to override
62 * @return Phergie_Plugin_Abstract
64 protected function getMockPlugin($name = 'TestPlugin', array $methods = array())
66 $methods[] = 'getName';
67 $plugin = $this->getMock('Phergie_Plugin_Abstract', $methods);
69 ->expects($this->any())
71 ->will($this->returnValue($name));
76 * Sets up a new handler instance before each test.
80 public function setUp()
82 $this->config = $this->getMock('Phergie_Config');
83 $this->events = $this->getMock('Phergie_Event_Handler');
84 $this->handler = new Phergie_Plugin_Handler(
91 * Tests iterability of the plugin handler.
95 public function testImplementsIteratorAggregate()
97 $reflection = new ReflectionObject($this->handler);
100 $reflection->implementsInterface('IteratorAggregate'),
101 'Handler does not implement IteratorAggregate'
106 $this->handler->getIterator(),
107 'getIterator() must return an iterator'
112 * Tests countability of the plugin handler.
116 public function testImplementsCountable()
118 $reflection = new ReflectionObject($this->handler);
121 $reflection->implementsInterface('Countable'),
122 'Handler does not implement Countable'
127 count($this->handler),
128 'count() must return an integer'
133 * Tests the plugin handler exposing added plugins as instance
134 * properties of the handler via isset().
138 public function testImplementsIsset()
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}));
148 * Tests the plugin handler exposing added plugins as instance
149 * properties of the handler.
151 * @depends testImplementsIsset
154 public function testImplementsGet()
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);
166 * Tests the plugin handler allowing for plugin removal via unset().
168 * @depends testImplementsGet
171 public function testImplementsUnset()
173 $plugin = $this->getMockPlugin();
174 $this->handler->addPlugin($plugin);
175 unset($this->handler->{$plugin->getName()});
176 $this->assertFalse($this->handler->hasPlugin($plugin->getName()));
180 * Tests the plugin handler executing a callback on all contained
185 public function testImplementsCall()
187 foreach (range(1, 2) as $index) {
188 $plugin = $this->getMockPlugin('TestPlugin' . $index, array('callback'));
190 ->expects($this->once())
191 ->method('callback');
192 $this->handler->addPlugin($plugin);
195 $this->assertTrue($this->handler->callback());
199 * Tests a newly instantiated handler not having plugins associated with
202 * @depends testImplementsCountable
205 public function testEmptyHandlerHasNoPlugins()
207 $this->assertEquals(0, count($this->handler));
211 * Tests a newly instantiated handler not having autoloading enabled by
216 public function testGetAutoloadDefaultsToNotAutoload()
218 $this->assertFalse($this->handler->getAutoload());
222 * Tests setAutoload().
224 * @depends testGetAutoloadDefaultsToNotAutoload
227 public function testSetAutoload()
230 $this->handler->setAutoload(true),
232 'setAutoload() does not provide a fluent interface'
236 $this->handler->getAutoload(),
237 'setAutoload() had no effect on getAutoload()'
242 * Tests addPath() providing a fluent interface.
246 public function testAddPathProvidesFluentInterface()
248 $handler = $this->handler->addPath(dirname(__FILE__));
249 $this->assertSame($this->handler, $handler);
253 * Tests addPath() throwing an exception when it cannot read the
258 public function testAddPathThrowsExceptionOnUnreadableDirectory()
261 $this->handler->addPath('/an/unreadable/directory/path');
262 } catch(Phergie_Plugin_Exception $e) {
264 Phergie_Plugin_Exception::ERR_DIRECTORY_NOT_READABLE,
270 $this->fail('An expected exception has not been raised');
274 * Tests adding a path to the plugin handler.
278 public function testAddPath()
280 $pluginName = 'Mock';
283 $this->handler->addPlugin($pluginName);
284 } catch(Phergie_Plugin_Exception $e) {
286 Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
292 $this->fail('Plugin loaded, path was already present');
295 $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
298 $this->handler->addPlugin($pluginName);
299 } catch(Phergie_Plugin_Exception $e) {
300 $this->fail('Added path, plugin still not found');
305 * Tests addPlugin() returning an added plugin instance.
309 public function testAddPluginByInstanceReturnsPluginInstance()
311 $plugin = $this->getMockPlugin();
312 $returnedPlugin = $this->handler->addPlugin($plugin);
316 'addPlugin() does not return the instance passed to it'
321 * Tests adding a plugin to the handler using the plugin's short name.
325 public function testAddPluginByShortName()
327 $pluginName = 'Mock';
328 $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
330 $returnedPlugin = $this->handler->addPlugin($pluginName);
331 $this->assertTrue($this->handler->hasPlugin($pluginName));
334 'Phergie_Plugin_Mock',
335 $this->handler->getPlugin($pluginName)
339 $this->handler->getPlugin($pluginName),
341 'Handler does not contain added plugin'
347 * Tests adding a plugin instance to the handler.
351 public function testAddPluginByInstance()
353 $plugin = $this->getMockPlugin();
354 $returnedPlugin = $this->handler->addPlugin($plugin);
355 $this->assertTrue($this->handler->hasPlugin('TestPlugin'));
360 'addPlugin() does not return added plugin instance'
365 $this->handler->getPlugin('TestPlugin'),
366 'getPlugin() does not return added plugin instance'
371 * Tests addPlugin() throwing an exception when the plugin class file
376 public function testAddPluginThrowsExceptionWhenPluginFileNotFound()
379 $this->handler->addPlugin('TestPlugin');
380 } catch(Phergie_Plugin_Exception $e) {
382 Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
388 $this->fail('An expected exception has not been raised');
392 * Recursively removes all files and subdirectories in a directory.
394 * @param string $path Directory path
397 private function removeDirectory($path)
399 if (file_exists($path)) {
400 $it = new RecursiveIteratorIterator(
401 new RecursiveDirectoryIterator($path),
402 RecursiveIteratorIterator::CHILD_FIRST
404 foreach ($it as $entry) {
408 if ($entry->isDir()) {
409 rmdir($entry->getPathname());
411 unlink($entry->getPathname());
418 * Tests addPlugin() throwing an exception when the plugin class file is
419 * found, but does not contain the plugin class as expected.
423 public function testAddPluginThrowsExceptionWhenPluginClassNotFound()
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_');
432 $this->handler->addPlugin('TestPlugin');
433 } catch(Phergie_Plugin_Exception $e) { }
437 Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
441 $this->fail('An expected exception has not been raised');
444 $this->removeDirectory(dirname($path));
448 * Tests addPlugin() throwing an exception when trying to instantiate a
449 * class that doesn't extend Phergie_Plugin_Abstract.
453 public function testAddPluginThrowsExceptionIfRequestingNonPlugin()
456 $this->handler->addPlugin('Handler');
457 } catch(Phergie_Plugin_Exception $e) {
459 Phergie_Plugin_Exception::ERR_INCORRECT_BASE_CLASS,
465 $this->fail('An expected exception has not been raised');
469 * Tests addPlugin() throwing an exception when trying to instantiate a
470 * class that can't be instantiated.
474 public function testAddPluginThrowsExceptionIfPluginNotInstantiable()
476 $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
478 $this->handler->addPlugin('TestNonInstantiablePluginFromFile');
479 } catch(Phergie_Plugin_Exception $e) {
481 Phergie_Plugin_Exception::ERR_CLASS_NOT_INSTANTIABLE,
487 $this->fail('An expected exception has not been raised');
491 * Tests adding a plugin by its short name with arguments passed to the
492 * plugin constructor.
496 public function testAddPluginShortNamePassesArgsToConstructor()
498 $pluginName = 'Mock';
499 $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
501 $arguments = array('a', 'b', 'c');
502 $plugin = $this->handler->addPlugin($pluginName, $arguments);
504 $this->assertAttributeSame(
508 'Arguments do not match'
513 * Tests addPlugin() passing Phergie_Config to an instantiated plugin.
517 public function testAddPluginPassesConstructorArguments()
519 $pluginName = 'Mock';
520 $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
521 $plugin = $this->handler->addPlugin($pluginName);
525 $plugin->getConfig(),
526 'Phergie_Config instances do not match'
531 $plugin->getEventHandler(),
532 'Phergie_Event_Handler instances do not match'
537 * Tests addPlugin() calling onLoad() on an instantiated plugin.
541 public function testAddPluginCallsOnLoadOnInstantiatedPlugin()
543 $plugin = $this->getMockPlugin(null, array('onLoad'));
545 ->expects($this->once())
547 $this->handler->addPlugin($plugin);
551 * Tests addPlugin() returning the same plugin when called twice.
555 public function testAddPluginReturnsSamePluginWhenAskedTwice()
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);
565 * Tests getPlugin() throwing an exception when trying to get an
566 * unloaded plugin with autoload disabled.
568 * @depends testGetAutoloadDefaultsToNotAutoload
571 public function testExceptionThrownWhenLoadingPluginWithoutAutoload()
573 $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
576 $this->handler->getPlugin('Mock');
577 } catch (Phergie_Plugin_Exception $expected) {
579 Phergie_Plugin_Exception::ERR_PLUGIN_NOT_LOADED,
585 $this->fail('An expected exception has not been raised');
589 * Tests addPlugins() with a plugin short name and no plugin constructor
592 * @depends testAddPluginByShortName
593 * @depends testAddPluginByInstance
596 public function testAddPluginsWithoutArguments()
598 $prefix = 'Phergie_Plugin_';
599 $this->handler->addPath(dirname(__FILE__), $prefix);
602 $this->handler->addPlugins(array($plugin));
603 $returnedPlugin = $this->handler->getPlugin($plugin);
604 $this->assertContains(
605 get_class($returnedPlugin),
607 'Short name plugin not of expected class'
612 * Tests addPlugins() with a plugin short name and plugin constructor
615 * @depends testAddPluginByShortName
616 * @depends testAddPluginByInstance
619 public function testAddPluginsWithArguments()
621 $prefix = 'Phergie_Plugin_';
622 $this->handler->addPath(dirname(__FILE__), $prefix);
624 $arguments = array(1, 2, 3);
625 $plugin = array('Mock', $arguments);
626 $this->handler->addPlugins(array($plugin));
627 $returnedPlugin = $this->handler->getPlugin('Mock');
630 $returnedPlugin->getArguments(),
631 'Constructor arguments for instance plugin do not match'
636 * Tests removePlugin() with a plugin instance.
638 * @depends testAddPluginByInstance
641 public function testRemovePluginByInstance()
643 $plugin = $this->getMockPlugin();
644 $this->handler->addPlugin($plugin);
645 $this->handler->removePlugin($plugin);
647 $this->handler->hasPlugin($plugin->getName()),
648 'Plugin was not removed'
653 * Tests removePlugin() with a plugin short name.
655 * @depends testAddPluginByShortName
658 public function testRemovePluginByShortName()
661 $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
663 $this->handler->addPlugin($plugin);
664 $this->handler->removePlugin($plugin);
666 $this->handler->hasPlugin($plugin),
667 'Plugin was not removed'
672 * Tests getPlugin() when the plugin is not already loaded and
673 * autoloading is disabled.
675 * @depends testSetAutoload
678 public function testGetPluginWithAutoloadEnabled()
680 $this->handler->setAutoload(true);
681 $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
682 $plugin = $this->handler->getPlugin('Mock');
684 'Phergie_Plugin_Mock',
686 'Retrieved plugin not of expected class'
691 * Tests getPlugins().
693 * @depends testGetPluginWithAutoloadEnabled
696 public function testGetPlugins()
698 $plugin1 = $this->getMockPlugin('TestPlugin1');
699 $this->handler->addPlugin($plugin1);
701 $plugin2 = $this->getMockPlugin('TestPlugin2');
702 $this->handler->addPlugin($plugin2);
705 'testplugin1' => $plugin1,
706 'testplugin2' => $plugin2,
709 $actual = $this->handler->getPlugins();
710 $this->assertEquals($expected, $actual);
712 $actual = $this->handler->getPlugins(array('testplugin1', 'testplugin2'));
713 $this->assertEquals($expected, $actual);
717 * Tests the plugin receiving and using a predefined iterator instance.
719 * @depends testGetPlugins
722 public function testSetIterator()
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);
731 foreach ($this->handler as $plugin) {
732 $iterated[strtolower($plugin->getName())] = $plugin;
734 $this->assertEquals($iterated, $plugins);