]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - plugins/Irc/extlib/phergie/Tests/Phergie/Plugin/HandlerTest.php
Introduced common_location_shared() to check if location sharing is always,
[quix0rs-gnu-social.git] / plugins / Irc / extlib / phergie / Tests / Phergie / Plugin / HandlerTest.php
index b359c11554732d42b9cc39cd08bba9fa86e38d97..98c70dfceeae881439fcd5137e6a699faa845b6e 100644 (file)
@@ -37,6 +37,41 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase
      */
     protected $handler;
 
+    /**
+     * Mock Phergie_Config instance passed to the plugin handler constructor
+     *
+     * @var Phergie_Config
+     */
+    protected $config;
+
+    /**
+     * Mock Phergie_Event_Handler instance passed to the plugin handler
+     * constructor
+     *
+     * @var Phergie_Event_Handler
+     */
+    protected $events;
+
+    /**
+     * Returns a mock plugin instance.
+     *
+     * @param string $name    Optional short name for the mock plugin, defaults
+     *        to 'TestPlugin'
+     * @param array  $methods Optional list of methods to override
+     *
+     * @return Phergie_Plugin_Abstract
+     */
+    protected function getMockPlugin($name = 'TestPlugin', array $methods = array())
+    {
+        $methods[] = 'getName';
+        $plugin = $this->getMock('Phergie_Plugin_Abstract', $methods);
+        $plugin
+            ->expects($this->any())
+            ->method('getName')
+            ->will($this->returnValue($name));
+        return $plugin;
+    }
+
     /**
      * Sets up a new handler instance before each test.
      *
@@ -44,69 +79,238 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase
      */
     public function setUp()
     {
+        $this->config = $this->getMock('Phergie_Config');
+        $this->events = $this->getMock('Phergie_Event_Handler');
         $this->handler = new Phergie_Plugin_Handler(
-            new Phergie_Config(),
-            new Phergie_Event_Handler()
+            $this->config,
+            $this->events
         );
     }
 
     /**
-     * Destroys the handler instance after each test
+     * Tests iterability of the plugin handler.
      *
      * @return void
      */
-    public function tearDown()
+    public function testImplementsIteratorAggregate()
     {
-        unset($this->handler);
+        $reflection = new ReflectionObject($this->handler);
+
+        $this->assertTrue(
+            $reflection->implementsInterface('IteratorAggregate'),
+            'Handler does not implement IteratorAggregate'
+        );
+
+        $this->assertType(
+            'Iterator',
+            $this->handler->getIterator(),
+            'getIterator() must return an iterator'
+        );
+    }
+
+    /**
+     * Tests that a default iterator is returned if none is explicitly set.
+     *
+     * @return void
+     */
+    public function testGetIteratorReturnsDefault()
+    {
+        $this->assertType(
+            'Phergie_Plugin_Iterator',
+            $this->handler->getIterator()
+        );
     }
 
     /**
-     * Ensures that we can iterate over the handler
+     * Tests the ability to change the handler's iterator class when a valid
+     * class is specified.
      *
      * @return void
      */
-    public function testImplementsIterator()
+    public function testSetIteratorClassWithValidClass()
+    {
+        eval('
+            class DummyIterator extends FilterIterator {
+                public function accept() {
+                    return true;
+                }
+            }
+        ');
+
+        $this->handler->setIteratorClass('DummyIterator');
+
+        $this->assertType(
+            'DummyIterator',
+            $this->handler->getIterator()
+        );
+    }
+
+    /**
+     * Tests that a failure occurs when a nonexistent iterator class is
+     * specified.
+     *
+     * @return void
+     */
+    public function testSetIteratorClassWithNonexistentClass()
+    {
+        try {
+            $this->handler->setIteratorClass('FooIterator');
+            $this->fail('Expected exception was not thrown');
+        } catch (Phergie_Plugin_Exception $e) {
+            return;
+        }
+        $this->fail('Unexpected exception was thrown');
+    }
+
+    /**
+     * Tests that a failure occurs when a class that is not a subclass of
+     * FilterIterator is specified.
+     *
+     * @return void
+     */
+    public function testSetIteratorClassWithNonFilterIteratorClass()
+    {
+        try {
+            $this->handler->setIteratorClass('ArrayIterator');
+            $this->fail('Expected exception was not thrown');
+        } catch (Phergie_Plugin_Exception $e) {
+            return;
+        }
+        $this->fail('Unexpected exception was thrown');
+    }
+
+    /**
+     * Tests countability of the plugin handler.
+     *
+     * @return void
+     */
+    public function testImplementsCountable()
     {
         $reflection = new ReflectionObject($this->handler);
+
         $this->assertTrue(
-            $reflection->implementsInterface('IteratorAggregate')
+            $reflection->implementsInterface('Countable'),
+            'Handler does not implement Countable'
         );
 
         $this->assertType(
-            'Iterator', $this->handler->getIterator(),
-            'getIterator() must actually return an Iterator'
+            'int',
+            count($this->handler),
+            'count() must return an integer'
         );
     }
 
     /**
-     * Ensures a newly instantiated handler does not have plugins associated
-     * with it
+     * Tests the plugin handler exposing added plugins as instance
+     * properties of the handler via isset().
      *
-     * @depends testImplementsIterator
      * @return void
      */
-    public function testEmptyHandlerHasNoPlugins()
+    public function testImplementsIsset()
     {
-        $count = 0;
-        foreach ($this->handler as $plugin) {
-            $count++;
+        $pluginName = 'TestPlugin';
+        $this->assertFalse(isset($this->handler->{$pluginName}));
+        $plugin = $this->getMockPlugin($pluginName);
+        $this->handler->addPlugin($plugin);
+        $this->assertTrue(isset($this->handler->{$pluginName}));
+    }
+
+    /**
+     * Tests the plugin handler exposing added plugins as instance
+     * properties of the handler.
+     *
+     * @depends testImplementsIsset
+     * @return void
+     */
+    public function testImplementsGet()
+    {
+        $plugin = $this->getMockPlugin();
+        $this->handler->addPlugin($plugin);
+        $name = $plugin->getName();
+        $getPlugin = $this->handler->getPlugin($name);
+        $this->assertTrue(isset($this->handler->$name));
+        $get = $this->handler->$name;
+        $this->assertSame($getPlugin, $get);
+    }
+
+    /**
+     * Tests the plugin handler allowing for plugin removal via unset().
+     *
+     * @depends testImplementsGet
+     * @return void
+     */
+    public function testImplementsUnset()
+    {
+        $plugin = $this->getMockPlugin();
+        $this->handler->addPlugin($plugin);
+        unset($this->handler->{$plugin->getName()});
+        $this->assertFalse($this->handler->hasPlugin($plugin->getName()));
+    }
+
+    /**
+     * Tests the plugin handler executing a callback on all contained
+     * plugins.
+     *
+     * @return void
+     */
+    public function testImplementsCall()
+    {
+        foreach (range(1, 2) as $index) {
+            $plugin = $this->getMockPlugin('TestPlugin' . $index, array('callback'));
+            $plugin
+                ->expects($this->once())
+                ->method('callback');
+            $this->handler->addPlugin($plugin);
         }
 
-        $this->assertEquals(0, $count);
+        $this->assertTrue($this->handler->callback());
     }
-    
+
     /**
-     * Ensures a newly instantiated handler does not default to autoload
+     * Tests a newly instantiated handler not having plugins associated with
+     * it.
      *
+     * @depends testImplementsCountable
      * @return void
      */
-    public function testDefaultsToNotAutoload()
+    public function testEmptyHandlerHasNoPlugins()
+    {
+        $this->assertEquals(0, count($this->handler));
+    }
+
+    /**
+     * Tests a newly instantiated handler not having autoloading enabled by
+     * default.
+     *
+     * @return void
+     */
+    public function testGetAutoloadDefaultsToNotAutoload()
     {
         $this->assertFalse($this->handler->getAutoload());
     }
 
     /**
-     * addPath provides a fluent interface
+     * Tests setAutoload().
+     *
+     * @depends testGetAutoloadDefaultsToNotAutoload
+     * @return void
+     */
+    public function testSetAutoload()
+    {
+        $this->assertSame(
+            $this->handler->setAutoload(true),
+            $this->handler,
+            'setAutoload() does not provide a fluent interface'
+        );
+
+        $this->assertTrue(
+            $this->handler->getAutoload(),
+            'setAutoload() had no effect on getAutoload()'
+        );
+    }
+
+    /**
+     * Tests addPath() providing a fluent interface.
      *
      * @return void
      */
@@ -117,7 +321,8 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase
     }
 
     /**
-     * addPath throws an exception when it cannot read the directory
+     * Tests addPath() throwing an exception when it cannot read the
+     * directory.
      *
      * @return void
      */
@@ -133,122 +338,113 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase
             return;
         }
 
-        $this->fail('An expected exception has not been raised.');
+        $this->fail('An expected exception has not been raised');
     }
 
     /**
-     * adds a path into the plugin handler and then ensures that files
-     * in that location can be found
+     * Tests adding a path to the plugin handler.
      *
      * @return void
      */
     public function testAddPath()
     {
-        $plugin_name = 'Mock';
+        $pluginName = 'Mock';
+
         try {
-            $this->handler->addPlugin($plugin_name);
+            $this->handler->addPlugin($pluginName);
         } catch(Phergie_Plugin_Exception $e) {
             $this->assertEquals(
                 Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
                 $e->getCode()
             );
-            
-            $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
-
-            try {
-                $this->handler->addPlugin($plugin_name);
-            } catch(Phergie_Plugin_Exception $e) {
-                $this->fail(
-                    'After adding the directory, the plugin was still '
-                    . 'not found.'
-                );
-            }
-            
-            return;
         }
 
-        $this->fail(
-            'Before adding the directory, an expected exception '
-            . 'was not raised'
-        );
+        if (!isset($e)) {
+            $this->fail('Plugin loaded, path was already present');
+        }
+
+        $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
+
+        try {
+            $this->handler->addPlugin($pluginName);
+        } catch(Phergie_Plugin_Exception $e) {
+            $this->fail('Added path, plugin still not found');
+        }
     }
 
     /**
-     * addPlugin returns the plugin instance that was added
+     * Tests addPlugin() returning an added plugin instance.
      *
      * @return void
      */
-    public function testAddPluginByInstanceReturnsPluginInstance() {
-        $plugin = $this->getMock('Phergie_Plugin_Abstract');
-        $plugin
-            ->expects($this->any())
-            ->method('getName')
-            ->will($this->returnValue('TestPlugin'));
-
-        $returned_plugin = $this->handler->addPlugin($plugin);
+    public function testAddPluginByInstanceReturnsPluginInstance()
+    {
+        $plugin = $this->getMockPlugin();
+        $returnedPlugin = $this->handler->addPlugin($plugin);
         $this->assertSame(
-            $returned_plugin,
+            $returnedPlugin,
             $plugin,
-            'addPlugin returns the same instance that is passed to it'
+            'addPlugin() does not return the instance passed to it'
         );
     }
 
     /**
-     * Can add a plugin to the handler by shortname
+     * Tests adding a plugin to the handler using the plugin's short name.
      *
      * @return void
      */
-    public function testAddPluginToHandlerByShortname()
+    public function testAddPluginByShortName()
     {
-        $plugin_name = 'Mock';
+        $pluginName = 'Mock';
         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
 
-        $returned_plugin = $this->handler->addPlugin($plugin_name);
-        $this->assertTrue($this->handler->hasPlugin($plugin_name));
+        $returnedPlugin = $this->handler->addPlugin($pluginName);
+        $this->assertTrue($this->handler->hasPlugin($pluginName));
+
         $this->assertType(
             'Phergie_Plugin_Mock',
-            $this->handler->getPlugin($plugin_name)
+            $this->handler->getPlugin($pluginName)
         );
+
         $this->assertSame(
-            $this->handler->getPlugin($plugin_name),
-            $returned_plugin,
-            'Handler contains plugin when added by shortname.'
+            $this->handler->getPlugin($pluginName),
+            $returnedPlugin,
+            'Handler does not contain added plugin'
         );
     }
 
 
     /**
-     * Can add a plugin to the handler by instance
+     * Tests adding a plugin instance to the handler.
      *
      * @return void
      */
-    public function testAddPluginToHandlerByInstance()
+    public function testAddPluginByInstance()
     {
-        $plugin = $this->getMock('Phergie_Plugin_Abstract');
-        $plugin
-            ->expects($this->any())
-            ->method('getName')
-            ->will($this->returnValue('TestPlugin'));
-
-        $returned_plugin = $this->handler->addPlugin($plugin);
-
+        $plugin = $this->getMockPlugin();
+        $returnedPlugin = $this->handler->addPlugin($plugin);
         $this->assertTrue($this->handler->hasPlugin('TestPlugin'));
+
         $this->assertSame(
-            $plugin, $returned_plugin,
-            'addPlugin returns the same plugin'
+            $plugin,
+            $returnedPlugin,
+            'addPlugin() does not return added plugin instance'
         );
+
         $this->assertSame(
-            $plugin, $this->handler->getPlugin('TestPlugin'),
-            'getPlugin returns the same plugin'
+            $plugin,
+            $this->handler->getPlugin('TestPlugin'),
+            'getPlugin() does not return added plugin instance'
         );
     }
 
     /**
-     * addPlugin throws an exception when it can't find the plugin
+     * Tests addPlugin() throwing an exception when the plugin class file
+     * can't be found.
      *
      * @return void
      */
-    public function testAddPluginThrowsExceptionIfCannotFindPlugin()
+    public function testAddPluginThrowsExceptionWhenPluginFileNotFound()
     {
         try {
             $this->handler->addPlugin('TestPlugin');
@@ -260,12 +456,68 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase
             return;
         }
 
-        $this->fail('An expected exception has not been raised.');
+        $this->fail('An expected exception has not been raised');
     }
 
     /**
-     * addPlugin throws an exception when trying to instantiate a
-     * class that doesn't extend from Phergie_Plugin_Abstract
+     * Recursively removes all files and subdirectories in a directory.
+     *
+     * @param string $path Directory path
+     * @return void
+     */
+    private function removeDirectory($path)
+    {
+        if (file_exists($path)) {
+            $it = new RecursiveIteratorIterator(
+                new RecursiveDirectoryIterator($path),
+                RecursiveIteratorIterator::CHILD_FIRST
+            );
+            foreach ($it as $entry) {
+                if ($it->isDot()) {
+                    continue;
+                }
+                if ($entry->isDir()) {
+                    rmdir($entry->getPathname());
+                } else {
+                    unlink($entry->getPathname());
+                }
+            }
+        }
+    }
+
+    /**
+     * Tests addPlugin() throwing an exception when the plugin class file is
+     * found, but does not contain the plugin class as expected.
+     *
+     * @return void
+     */
+    public function testAddPluginThrowsExceptionWhenPluginClassNotFound()
+    {
+        $path = common_get_temp_dir() . '/Phergie/Plugin';
+        $this->removeDirectory(dirname($path));
+        mkdir($path, 0777, true);
+        touch($path . '/TestPlugin.php');
+        $this->handler->addPath($path, 'Phergie_Plugin_');
+
+        try {
+            $this->handler->addPlugin('TestPlugin');
+        } catch(Phergie_Plugin_Exception $e) { }
+
+        if (isset($e)) {
+            $this->assertEquals(
+                Phergie_Plugin_Exception::ERR_CLASS_NOT_FOUND,
+                $e->getCode()
+            );
+        } else {
+            $this->fail('An expected exception has not been raised');
+        }
+
+        $this->removeDirectory(dirname($path));
+    }
+
+    /**
+     * Tests addPlugin() throwing an exception when trying to instantiate a
+     * class that doesn't extend Phergie_Plugin_Abstract.
      *
      * @return void
      */
@@ -281,11 +533,11 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase
             return;
         }
 
-        $this->fail('An expected exception has not been raised.');
+        $this->fail('An expected exception has not been raised');
     }
 
     /**
-     * addPlugin throws an exception when trying to instantiate a
+     * Tests addPlugin() throwing an exception when trying to instantiate a
      * class that can't be instantiated.
      *
      * @return void
@@ -303,159 +555,283 @@ class Phergie_Plugin_HandlerTest extends PHPUnit_Framework_TestCase
             return;
         }
 
-        $this->fail('An expected exception has not been raised.');
+        $this->fail('An expected exception has not been raised');
     }
 
     /**
-     * addPlugin with shortname and arguments passes args to constructor
+     * Tests adding a plugin by its short name with arguments passed to the
+     * plugin constructor.
      *
-     * @return null
+     * @return void
      */
-    public function testAddPluginShortnamePassesArgsToConstructor()
+    public function testAddPluginShortNamePassesArgsToConstructor()
     {
-        $plugin_name = 'Mock';
+        $pluginName = 'Mock';
         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
 
         $arguments = array('a', 'b', 'c');
+        $plugin = $this->handler->addPlugin($pluginName, $arguments);
 
-        $plugin = $this->handler->addPlugin($plugin_name, $arguments);
         $this->assertAttributeSame(
             $arguments,
-            'args',
+            'arguments',
             $plugin,
-            'Arguments passed in to addPlugin match the arguments '
-            . 'the Mock plugin constructor received'
+            'Arguments do not match'
         );
     }
 
     /**
-     * addPlugin passes Phergie_Config to instantiated plugin
+     * Tests addPlugin() passing Phergie_Config to an instantiated plugin.
      *
-     * @return null
+     * @return void
      */
-    public function testAddPluginPassesPhergieConfigToInstantiatedPlugin()
+    public function testAddPluginPassesConstructorArguments()
     {
-        $my_config = new Phergie_Config();
-        $my_config['my_option'] = 'my_value';
-
-        // create a new handler with this config
-        unset($this->handler);
-        $this->handler = new Phergie_Plugin_Handler(
-            $my_config,
-            new Phergie_Event_Handler()
-        );
-
-        $plugin_name = 'Mock';
+        $pluginName = 'Mock';
         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
-
-        $plugin = $this->handler->addPlugin($plugin_name);
+        $plugin = $this->handler->addPlugin($pluginName);
 
         $this->assertSame(
-            $my_config,
+            $this->config,
             $plugin->getConfig(),
-            'addPlugin passes Phergie_Config to instantiated plugin'
+            'Phergie_Config instances do not match'
+        );
+
+        $this->assertSame(
+            $this->events,
+            $plugin->getEventHandler(),
+            'Phergie_Event_Handler instances do not match'
         );
     }
 
     /**
-     * addPlugin passes Phergie_Event_Handler to instantiated plugin
+     * Tests addPlugin() calling onLoad() on an instantiated plugin.
      *
-     * @return null
+     * @return void
      */
-    public function testAddPluginPassesPhergieEventHandlerToInstantiatedPlugin()
+    public function testAddPluginCallsOnLoadOnInstantiatedPlugin()
     {
-        $plugin = $this->getMock('Phergie_Plugin_Abstract');
+        $plugin = $this->getMockPlugin(null, array('onLoad'));
         $plugin
-            ->expects($this->any())
-            ->method('getName')
-            ->will($this->returnValue('TestPlugin'));
-
-        $my_event_handler = new Phergie_Event_Handler();
-        $my_event_handler->addEvent($plugin, 'ping');
+            ->expects($this->once())
+            ->method('onLoad');
+        $this->handler->addPlugin($plugin);
+    }
 
-        // create a new plugin handler with this event handler
-        unset($this->handler);
-        $this->handler = new Phergie_Plugin_Handler(
-            new Phergie_Config(),
-            $my_event_handler
-        );
+    /**
+     * Tests addPlugin() returning the same plugin when called twice.
+     *
+     * @return void
+     */
+    public function testAddPluginReturnsSamePluginWhenAskedTwice()
+    {
+        $pluginName = 'Mock';
+        $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
+        $plugin1 = $this->handler->addPlugin($pluginName);
+        $plugin2 = $this->handler->addPlugin($pluginName);
+        $this->assertSame($plugin1, $plugin2);
+    }
 
-        $plugin_name = 'Mock';
+    /**
+     * Tests getPlugin() throwing an exception when trying to get an
+     * unloaded plugin with autoload disabled.
+     *
+     * @depends testGetAutoloadDefaultsToNotAutoload
+     * @return void
+     */
+    public function testExceptionThrownWhenLoadingPluginWithoutAutoload()
+    {
         $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
 
-        $plugin = $this->handler->addPlugin($plugin_name);
+        try {
+            $this->handler->getPlugin('Mock');
+        } catch (Phergie_Plugin_Exception $expected) {
+            $this->assertEquals(
+                Phergie_Plugin_Exception::ERR_PLUGIN_NOT_LOADED,
+                $expected->getCode()
+            );
+            return;
+        }
 
-        $this->assertSame(
-            $my_event_handler,
-            $plugin->getEventHandler(),
-            'addPlugin passes Phergie_Event_Handler to instantiated plugin'
-        );
+        $this->fail('An expected exception has not been raised');
     }
 
     /**
-     * @todo addPlugin calls onLoad() to instantiated plugin
+     * Tests addPlugins() with a plugin short name and no plugin constructor
+     * arguments.
+     *
+     * @depends testAddPluginByShortName
+     * @depends testAddPluginByInstance
+     * @return void
      */
+    public function testAddPluginsWithoutArguments()
+    {
+        $prefix = 'Phergie_Plugin_';
+        $this->handler->addPath(dirname(__FILE__), $prefix);
+
+        $plugin = 'Mock';
+        $this->handler->addPlugins(array($plugin));
+        $returnedPlugin = $this->handler->getPlugin($plugin);
+        $this->assertContains(
+            get_class($returnedPlugin),
+            $prefix . $plugin,
+            'Short name plugin not of expected class'
+        );
+    }
 
     /**
-     * implements __isset
+     * Tests addPlugins() with a plugin short name and plugin constructor
+     * arguments.
      *
+     * @depends testAddPluginByShortName
+     * @depends testAddPluginByInstance
      * @return void
      */
-    public function testPluginHandlerImplementsIsset()
+    public function testAddPluginsWithArguments()
     {
-        $plugin_name = 'TestPlugin';
+        $prefix = 'Phergie_Plugin_';
+        $this->handler->addPath(dirname(__FILE__), $prefix);
+
+        $arguments = array(1, 2, 3);
+        $plugin = array('Mock', $arguments);
+        $this->handler->addPlugins(array($plugin));
+        $returnedPlugin = $this->handler->getPlugin('Mock');
+        $this->assertEquals(
+            $arguments,
+            $returnedPlugin->getArguments(),
+            'Constructor arguments for instance plugin do not match'
+        );
+    }
 
-        $this->assertFalse(isset($this->handler->{$plugin_name}));
+    /**
+     * Tests removePlugin() with a plugin instance.
+     *
+     * @depends testAddPluginByInstance
+     * @return void
+     */
+    public function testRemovePluginByInstance()
+    {
+        $plugin = $this->getMockPlugin();
+        $this->handler->addPlugin($plugin);
+        $this->handler->removePlugin($plugin);
+        $this->assertFalse(
+            $this->handler->hasPlugin($plugin->getName()),
+            'Plugin was not removed'
+        );
+    }
 
-        $plugin = $this->getMock('Phergie_Plugin_Abstract');
-        $plugin
-            ->expects($this->any())
-            ->method('getName')
-            ->will($this->returnValue($plugin_name));
+    /**
+     * Tests removePlugin() with a plugin short name.
+     *
+     * @depends testAddPluginByShortName
+     * @return void
+     */
+    public function testRemovePluginByShortName()
+    {
+        $plugin = 'Mock';
+        $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
 
         $this->handler->addPlugin($plugin);
+        $this->handler->removePlugin($plugin);
+        $this->assertFalse(
+            $this->handler->hasPlugin($plugin),
+            'Plugin was not removed'
+        );
+    }
+
+    /**
+     * Tests getPlugin() when the plugin is not already loaded and
+     * autoloading is disabled.
+     *
+     * @depends testSetAutoload
+     * @return void
+     */
+    public function testGetPluginWithAutoloadEnabled()
+    {
+        $this->handler->setAutoload(true);
+        $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
+        $plugin = $this->handler->getPlugin('Mock');
+        $this->assertType(
+            'Phergie_Plugin_Mock',
+            $plugin,
+            'Retrieved plugin not of expected class'
+        );
+    }
+
+    /**
+     * Tests getPlugins().
+     *
+     * @depends testGetPluginWithAutoloadEnabled
+     * @return void
+     */
+    public function testGetPlugins()
+    {
+        $plugin1 = $this->getMockPlugin('TestPlugin1');
+        $this->handler->addPlugin($plugin1);
 
-        $this->assertTrue(isset($this->handler->{$plugin_name}));
+        $plugin2 = $this->getMockPlugin('TestPlugin2');
+        $this->handler->addPlugin($plugin2);
+
+        $expected = array(
+            'testplugin1' => $plugin1,
+            'testplugin2' => $plugin2,
+        );
 
+        $actual = $this->handler->getPlugins();
+        $this->assertEquals($expected, $actual);
+
+        $actual = $this->handler->getPlugins(array('testplugin1', 'testplugin2'));
+        $this->assertEquals($expected, $actual);
     }
 
     /**
-     * addPlugin() returns the same plugin when requested twice
+     * Tests that multiple plugin iterators can be used concurrently.
      *
      * @return void
      */
-    public function testAddPluginReturnsSamePluginWhenAskedTwice()
+    public function testUseMultiplePluginIteratorsConcurrently()
     {
-        $plugin_name = 'Mock';
-        $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
+        $plugin1 = $this->getMockPlugin('TestPlugin1');
+        $this->handler->addPlugin($plugin1);
 
-        $plugin1 = $this->handler->addPlugin($plugin_name);
-        $plugin2 = $this->handler->addPlugin($plugin_name);
-        $this->assertSame($plugin1, $plugin2);
+        $plugin2 = $this->getMockPlugin('TestPlugin2');
+        $this->handler->addPlugin($plugin2);
+
+        $iterator1 = $this->handler->getIterator();
+        $iterator1->next();
+        $this->assertSame($plugin2, $iterator1->current());
+
+        $iterator2 = $this->handler->getIterator();
+        $this->assertSame($plugin1, $iterator2->current());
     }
 
-    
     /**
-     * Tests an exception is thrown when trying to get a plugin
-     * that is not already loaded and autoload is off
+     * Tests adding plugin paths via configuration.
      *
-     * @depends testDefaultsToNotAutoload
      * @return void
      */
-    public function testExceptionThrownWhenLoadingPluginWithoutAutoload()
+    public function testAddPluginPathsViaConfiguration()
     {
-        $this->handler->addPath(dirname(__FILE__), 'Phergie_Plugin_');
+        $dir = dirname(__FILE__);
+        $prefix = 'Phergie_Plugin_';
+        $paths = array($dir => $prefix);
+        $this->config
+            ->expects($this->any())
+            ->method('offsetExists')
+            ->will($this->returnValue(true));
+        $this->config
+            ->expects($this->any())
+            ->method('offsetGet')
+            ->will($this->returnValue($paths));
 
-        try {
-            $this->handler->getPlugin('Mock');
-        } catch (Phergie_Plugin_Exception $expected) {
-            $this->assertEquals(
-                Phergie_Plugin_Exception::ERR_PLUGIN_NOT_LOADED,
-                $expected->getCode()
-            );
-            return;
-        }
+        // Reinitialize the handler so the configuration change takes effect
+        // within the constructor
+        $this->handler = new Phergie_Plugin_Handler(
+            $this->config,
+            $this->events
+        );
 
-        $this->fail('An expected exception has not been raised.');
+        $this->handler->setAutoload(true);
+        $this->handler->getPlugin('Mock');
     }
 }