From 361feecdcfefa729c728d80ea3f712708ecf507d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mudr=C3=A1k?= Date: Thu, 24 Sep 2015 20:53:04 +0200 Subject: [PATCH] MDL-49329 admin: Make core_plugin_manager better suited for unit testing We can now override the plugin manager's methods in the testable subclass while still keeping the singleton behaviour of it. The change makes use of late static binding. --- lib/classes/plugin_manager.php | 30 +++++++-------- .../fixtures/testable_plugin_manager.php | 38 +++++++++++++++++++ lib/tests/plugin_manager_test.php | 31 ++++++++++++--- 3 files changed, 79 insertions(+), 20 deletions(-) create mode 100644 lib/tests/fixtures/testable_plugin_manager.php diff --git a/lib/classes/plugin_manager.php b/lib/classes/plugin_manager.php index af27537f84e..254e04f2281 100644 --- a/lib/classes/plugin_manager.php +++ b/lib/classes/plugin_manager.php @@ -86,10 +86,10 @@ class core_plugin_manager { * @return core_plugin_manager the singleton instance */ public static function instance() { - if (is_null(self::$singletoninstance)) { - self::$singletoninstance = new self(); + if (is_null(static::$singletoninstance)) { + static::$singletoninstance = new static(); } - return self::$singletoninstance; + return static::$singletoninstance; } /** @@ -98,15 +98,15 @@ class core_plugin_manager { */ public static function reset_caches($phpunitreset = false) { if ($phpunitreset) { - self::$singletoninstance = null; + static::$singletoninstance = null; } else { - if (self::$singletoninstance) { - self::$singletoninstance->pluginsinfo = null; - self::$singletoninstance->subpluginsinfo = null; - self::$singletoninstance->installedplugins = null; - self::$singletoninstance->enabledplugins = null; - self::$singletoninstance->presentplugins = null; - self::$singletoninstance->plugintypes = null; + if (static::$singletoninstance) { + static::$singletoninstance->pluginsinfo = null; + static::$singletoninstance->subpluginsinfo = null; + static::$singletoninstance->installedplugins = null; + static::$singletoninstance->enabledplugins = null; + static::$singletoninstance->presentplugins = null; + static::$singletoninstance->plugintypes = null; } } $cache = cache::make('core', 'plugin_manager'); @@ -238,7 +238,7 @@ class core_plugin_manager { $plugintypes = core_component::get_plugin_types(); foreach ($plugintypes as $plugintype => $fulldir) { - $plugininfoclass = self::resolve_plugininfo_class($plugintype); + $plugininfoclass = static::resolve_plugininfo_class($plugintype); if (class_exists($plugininfoclass)) { $enabled = $plugininfoclass::get_enabled_plugins(); if (!is_array($enabled)) { @@ -374,13 +374,13 @@ class core_plugin_manager { if (!isset($types[$type])) { // Orphaned subplugins! - $plugintypeclass = self::resolve_plugininfo_class($type); + $plugintypeclass = static::resolve_plugininfo_class($type); $this->pluginsinfo[$type] = $plugintypeclass::get_plugins($type, null, $plugintypeclass); return $this->pluginsinfo[$type]; } /** @var \core\plugininfo\base $plugintypeclass */ - $plugintypeclass = self::resolve_plugininfo_class($type); + $plugintypeclass = static::resolve_plugininfo_class($type); $plugins = $plugintypeclass::get_plugins($type, $types[$type], $plugintypeclass); $this->pluginsinfo[$type] = $plugins; @@ -1297,7 +1297,7 @@ class core_plugin_manager { return false; } - if ($pluginfo->get_status() === self::PLUGIN_STATUS_NEW) { + if ($pluginfo->get_status() === static::PLUGIN_STATUS_NEW) { // The plugin is not installed. It should be either installed or removed from the disk. // Relying on this temporary state may be tricky. return false; diff --git a/lib/tests/fixtures/testable_plugin_manager.php b/lib/tests/fixtures/testable_plugin_manager.php new file mode 100644 index 00000000000..847bff43ab9 --- /dev/null +++ b/lib/tests/fixtures/testable_plugin_manager.php @@ -0,0 +1,38 @@ +. + +/** + * Provides testable_core_plugin_manager class. + * + * @package core + * @category test + * @copyright 2015 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Testable variant of the core_plugin_manager + * + * @copyright 2015 David Mudrak + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class testable_core_plugin_manager extends core_plugin_manager { + + /** @var testable_core_plugin_manager holds the singleton instance */ + protected static $singletoninstance; +} diff --git a/lib/tests/plugin_manager_test.php b/lib/tests/plugin_manager_test.php index d3ff088c1e6..f9726e878cb 100644 --- a/lib/tests/plugin_manager_test.php +++ b/lib/tests/plugin_manager_test.php @@ -25,21 +25,31 @@ defined('MOODLE_INTERNAL') || die(); +global $CFG; +require_once($CFG->dirroot.'/lib/tests/fixtures/testable_plugin_manager.php'); + /** * Tests of the basic API of the plugin manager. */ class core_plugin_manager_testcase extends advanced_testcase { public function test_instance() { - $pluginman = core_plugin_manager::instance(); - $this->assertInstanceOf('core_plugin_manager', $pluginman); + $pluginman1 = core_plugin_manager::instance(); + $this->assertInstanceOf('core_plugin_manager', $pluginman1); $pluginman2 = core_plugin_manager::instance(); - $this->assertSame($pluginman, $pluginman2); + $this->assertSame($pluginman1, $pluginman2); + $pluginman3 = testable_core_plugin_manager::instance(); + $this->assertInstanceOf('core_plugin_manager', $pluginman3); + $this->assertInstanceOf('testable_core_plugin_manager', $pluginman3); + $pluginman4 = testable_core_plugin_manager::instance(); + $this->assertSame($pluginman3, $pluginman4); + $this->assertNotSame($pluginman1, $pluginman3); } public function test_reset_caches() { // Make sure there are no warnings or errors. core_plugin_manager::reset_caches(); + testable_core_plugin_manager::reset_caches(); } public function test_get_plugin_types() { @@ -95,12 +105,23 @@ class core_plugin_manager_testcase extends advanced_testcase { } public function test_get_plugins() { - $plugininfos = core_plugin_manager::instance()->get_plugins(); - foreach ($plugininfos as $type => $infos) { + $plugininfos1 = core_plugin_manager::instance()->get_plugins(); + foreach ($plugininfos1 as $type => $infos) { foreach ($infos as $name => $info) { $this->assertInstanceOf('\core\plugininfo\base', $info); } } + + // The testable variant of the manager holds its own tree of the + // plugininfo objects. + $plugininfos2 = testable_core_plugin_manager::instance()->get_plugins(); + $this->assertNotSame($plugininfos1['mod']['forum'], $plugininfos2['mod']['forum']); + + // Singletons of each manager class share the same tree. + $plugininfos3 = core_plugin_manager::instance()->get_plugins(); + $this->assertSame($plugininfos1['mod']['forum'], $plugininfos3['mod']['forum']); + $plugininfos4 = testable_core_plugin_manager::instance()->get_plugins(); + $this->assertSame($plugininfos2['mod']['forum'], $plugininfos4['mod']['forum']); } public function test_get_plugins_of_type() {