diff --git a/cache/README.md b/cache/README.md index 7e9cd59a88b..7745f0ed787 100644 --- a/cache/README.md +++ b/cache/README.md @@ -246,3 +246,23 @@ The following snippet illustates how to configure the three core cache stores th define('TEST_CACHESTORE_MEMCACHE_TESTSERVERS', '127.0.0.1:11211'); define('TEST_CACHESTORE_MEMCACHED_TESTSERVERS', '127.0.0.1:11211'); define('TEST_CACHESTORE_MONGODB_TESTSERVER', 'mongodb://localhost:27017'); + +As of Moodle 2.8 it is also possible to set the default cache stores used when running unit tests. +You can do this by adding the following define to your config.php file: + + // xxx is one of Memcache, Memecached, mongodb or other cachestore with a test define. + define('TEST_CACHE_USING_APPLICATION_STORE', 'xxx'); + +This allows you to run tests against a defined test store. It uses the defined value to identify a store to test against with a matching TEST_CACHESTORE define. +Alternatively you can also run unit tests against an actual cache config. +To do this you must add the following to your config.php file: + + define('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH', true'); + $CFG->altcacheconfigpath = '/a/temp/directory/yoursite.php' + +This tells Moodle to use the config at $CFG->altcacheconfigpath when running unit tests. +There are a couple of considerations to using this method: +* By setting $CFG->altcacheconfigpath your site will store the cache config in the specified path, not just the unit test cache config but your site config as well. +* If you have configured your cache before setting $CFG->altcacheconfigpath you will need to copy it from moodledata/muc/config.php to the destination you specified. +* This allows you to share a cache config between sites. +* It also allows you to use unit tests to test your sites cache config. diff --git a/cache/classes/config.php b/cache/classes/config.php index 322035fa093..5fdf2b95cd3 100644 --- a/cache/classes/config.php +++ b/cache/classes/config.php @@ -100,8 +100,8 @@ class cache_config { * @return bool True if it exists */ public static function config_file_exists() { - // Allow for late static binding. - return file_exists(self::get_config_file_path()); + // Allow for late static binding by using static. + return file_exists(static::get_config_file_path()); } /** @@ -324,7 +324,8 @@ class cache_config { */ protected function include_configuration() { $configuration = array(); - $cachefile = self::get_config_file_path(); + // We need to allow for late static bindings to allow for class path mudling happending for unit tests. + $cachefile = static::get_config_file_path(); if (!file_exists($cachefile)) { throw new cache_exception('Default cache config could not be found. It should have already been created by now.'); diff --git a/cache/classes/factory.php b/cache/classes/factory.php index 825a44102ed..6cf975f81b2 100644 --- a/cache/classes/factory.php +++ b/cache/classes/factory.php @@ -126,6 +126,14 @@ class cache_factory { // situation. It will use disabled alternatives where available. require_once($CFG->dirroot.'/cache/disabledlib.php'); self::$instance = new cache_factory_disabled(); + } else if (defined('PHPUNIT_TEST') && PHPUNIT_TEST) { + // We're using the regular factory. + require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php'); + self::$instance = new cache_phpunit_factory(); + if (defined('CACHE_DISABLE_STORES') && CACHE_DISABLE_STORES !== false) { + // The cache stores have been disabled. + self::$instance->set_state(self::STATE_STORES_DISABLED); + } } else { // We're using the regular factory. self::$instance = new cache_factory(); @@ -325,18 +333,12 @@ class cache_factory { public function create_config_instance($writer = false) { global $CFG; - // Check if we need to create a config file with defaults. - $needtocreate = !cache_config::config_file_exists(); - // The class to use. $class = 'cache_config'; - if ($writer || $needtocreate) { - require_once($CFG->dirroot.'/cache/locallib.php'); - $class .= '_writer'; - } + $unittest = defined('PHPUNIT_TEST') && PHPUNIT_TEST; // Check if this is a PHPUnit test and redirect to the phpunit config classes if it is. - if (defined('PHPUNIT_TEST') && PHPUNIT_TEST) { + if ($unittest) { require_once($CFG->dirroot.'/cache/locallib.php'); require_once($CFG->dirroot.'/cache/tests/fixtures/lib.php'); // We have just a single class for PHP unit tests. We don't care enough about its @@ -345,11 +347,22 @@ class cache_factory { $class = 'cache_config_phpunittest'; } + // Check if we need to create a config file with defaults. + $needtocreate = !$class::config_file_exists(); + + if ($writer || $needtocreate) { + require_once($CFG->dirroot.'/cache/locallib.php'); + if (!$unittest) { + $class .= '_writer'; + } + } + $error = false; if ($needtocreate) { // Create the default configuration. // Update the state, we are now initialising the cache. self::set_state(self::STATE_INITIALISING); + /** @var cache_config_writer $class */ $configuration = $class::create_default_configuration(); if ($configuration !== true) { // Failed to create the default configuration. Disable the cache stores and update the state. diff --git a/cache/classes/store.php b/cache/classes/store.php index ab225756f19..22c20db21b1 100644 --- a/cache/classes/store.php +++ b/cache/classes/store.php @@ -79,6 +79,17 @@ interface cache_store_interface { * @return cache_store|false */ public static function initialise_test_instance(cache_definition $definition); + + /** + * Initialises a test instance for unit tests. + * + * This differs from initialise_test_instance in that it doesn't rely on interacting with the config table. + * + * @since 2.8 + * @param cache_definition $definition + * @return cache_store|false + */ + public static function initialise_unit_test_instance(cache_definition $definition); } /** @@ -340,4 +351,18 @@ abstract class cache_store implements cache_store_interface { // Any stores that have an issue with this will need to override the create_clone method. return clone($this); } + + /** + * Initialises a test instance for unit tests. + * + * This differs from initialise_test_instance in that it doesn't rely on interacting with the config table. + * By default however it calls initialise_test_instance to support backwards compatability. + * + * @since 2.8 + * @param cache_definition $definition + * @return cache_store|false + */ + public static function initialise_unit_test_instance(cache_definition $definition) { + return self::initialise_test_instance($definition); + } } diff --git a/cache/locallib.php b/cache/locallib.php index c7948cf6fd7..042b89127b5 100644 --- a/cache/locallib.php +++ b/cache/locallib.php @@ -68,7 +68,7 @@ class cache_config_writer extends cache_config { */ protected function config_save() { global $CFG; - $cachefile = self::get_config_file_path(); + $cachefile = static::get_config_file_path(); $directory = dirname($cachefile); if ($directory !== $CFG->dataroot && !file_exists($directory)) { $result = make_writable_directory($directory, false); diff --git a/cache/stores/memcache/lib.php b/cache/stores/memcache/lib.php index 21e8f6c2c52..42db75b2e5d 100644 --- a/cache/stores/memcache/lib.php +++ b/cache/stores/memcache/lib.php @@ -430,6 +430,27 @@ class cachestore_memcache extends cache_store implements cache_is_configurable { return $store; } + /** + * Creates a test instance for unit tests if possible. + * @param cache_definition $definition + * @return bool|cachestore_memcache + */ + public static function initialise_unit_test_instance(cache_definition $definition) { + if (!self::are_requirements_met()) { + return false; + } + if (!defined('TEST_CACHESTORE_MEMCACHE_TESTSERVERS')) { + return false; + } + $configuration = array(); + $configuration['servers'] = explode("\n", TEST_CACHESTORE_MEMCACHE_TESTSERVERS); + + $store = new cachestore_memcache('Test memcache', $configuration); + $store->initialise($definition); + + return $store; + } + /** * Returns the name of this instance. * @return string diff --git a/cache/stores/memcache/tests/memcache_test.php b/cache/stores/memcache/tests/memcache_test.php index 4e3c2aa9e43..62b52f45b6d 100644 --- a/cache/stores/memcache/tests/memcache_test.php +++ b/cache/stores/memcache/tests/memcache_test.php @@ -42,16 +42,6 @@ require_once($CFG->dirroot.'/cache/stores/memcache/lib.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class cachestore_memcache_test extends cachestore_tests { - /** - * Prepare to run tests. - */ - public function setUp() { - if (defined('TEST_CACHESTORE_MEMCACHE_TESTSERVERS')) { - set_config('testservers', TEST_CACHESTORE_MEMCACHE_TESTSERVERS, 'cachestore_memcache'); - $this->resetAfterTest(); - } - parent::setUp(); - } /** * Returns the memcache class name * @return string @@ -65,7 +55,7 @@ class cachestore_memcache_test extends cachestore_tests { */ public function test_valid_keys() { $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcache', 'phpunit_test'); - $instance = cachestore_memcache::initialise_test_instance($definition); + $instance = cachestore_memcache::initialise_unit_test_instance($definition); if (!$instance) { // Something prevented memcache store to be inited (extension, TEST_CACHESTORE_MEMCACHE_TESTSERVERS...). $this->markTestSkipped(); diff --git a/cache/stores/memcached/lib.php b/cache/stores/memcached/lib.php index 2c601fefe1a..1570a70b5cf 100644 --- a/cache/stores/memcached/lib.php +++ b/cache/stores/memcached/lib.php @@ -487,6 +487,28 @@ class cachestore_memcached extends cache_store implements cache_is_configurable return $store; } + /** + * Creates a test instance for unit tests if possible. + * @param cache_definition $definition + * @return bool|cachestore_memcached + */ + public static function initialise_unit_test_instance(cache_definition $definition) { + if (!self::are_requirements_met()) { + return false; + } + if (!defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS')) { + return false; + } + + $configuration = array(); + $configuration['servers'] = explode("\n", TEST_CACHESTORE_MEMCACHED_TESTSERVERS); + + $store = new cachestore_memcached('Test memcached', $configuration); + $store->initialise($definition); + + return $store; + } + /** * Returns the name of this instance. * @return string diff --git a/cache/stores/memcached/tests/memcached_test.php b/cache/stores/memcached/tests/memcached_test.php index 80a918a38c7..a6c34962002 100644 --- a/cache/stores/memcached/tests/memcached_test.php +++ b/cache/stores/memcached/tests/memcached_test.php @@ -42,16 +42,6 @@ require_once($CFG->dirroot.'/cache/stores/memcached/lib.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class cachestore_memcached_test extends cachestore_tests { - /** - * Prepare to run tests. - */ - public function setUp() { - if (defined('TEST_CACHESTORE_MEMCACHED_TESTSERVERS')) { - set_config('testservers', TEST_CACHESTORE_MEMCACHED_TESTSERVERS, 'cachestore_memcached'); - $this->resetAfterTest(); - } - parent::setUp(); - } /** * Returns the memcached class name * @return string @@ -65,7 +55,7 @@ class cachestore_memcached_test extends cachestore_tests { */ public function test_valid_keys() { $definition = cache_definition::load_adhoc(cache_store::MODE_APPLICATION, 'cachestore_memcached', 'phpunit_test'); - $instance = cachestore_memcached::initialise_test_instance($definition); + $instance = cachestore_memcached::initialise_unit_test_instance($definition); if (!$instance) { // Something prevented memcached store to be inited (extension, TEST_CACHESTORE_MEMCACHED_TESTSERVERS...). $this->markTestSkipped(); diff --git a/cache/stores/mongodb/lib.php b/cache/stores/mongodb/lib.php index f30323d37bd..db8653f5421 100644 --- a/cache/stores/mongodb/lib.php +++ b/cache/stores/mongodb/lib.php @@ -561,6 +561,30 @@ class cachestore_mongodb extends cache_store implements cache_is_configurable { return $store; } + + /** + * Generates an instance of the cache store that can be used for testing. + * + * @param cache_definition $definition + * @return false + */ + public static function initialise_unit_test_instance(cache_definition $definition) { + if (!self::are_requirements_met()) { + return false; + } + if (!defined('TEST_CACHESTORE_MONGODB_TESTSERVER')) { + return false; + } + + $configuration = array(); + $configuration['servers'] = explode("\n", TEST_CACHESTORE_MONGODB_TESTSERVER); + + $store = new cachestore_mongodb('Test mongodb', $configuration); + $store->initialise($definition); + + return $store; + } + /** * Returns the name of this instance. * @return string diff --git a/cache/stores/mongodb/tests/mongodb_test.php b/cache/stores/mongodb/tests/mongodb_test.php index b1a3390907e..97bfb9dba63 100644 --- a/cache/stores/mongodb/tests/mongodb_test.php +++ b/cache/stores/mongodb/tests/mongodb_test.php @@ -42,16 +42,6 @@ require_once($CFG->dirroot.'/cache/stores/mongodb/lib.php'); * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class cachestore_mongodb_test extends cachestore_tests { - /** - * Prepare to run tests. - */ - public function setUp() { - if (defined('TEST_CACHESTORE_MONGODB_TESTSERVER')) { - set_config('testserver', TEST_CACHESTORE_MONGODB_TESTSERVER, 'cachestore_mongodb'); - $this->resetAfterTest(); - } - parent::setUp(); - } /** * Returns the MongoDB class name * @return string diff --git a/cache/tests/administration_helper_test.php b/cache/tests/administration_helper_test.php index c30ae0c648e..68f8d9576b7 100644 --- a/cache/tests/administration_helper_test.php +++ b/cache/tests/administration_helper_test.php @@ -165,9 +165,9 @@ class core_cache_administration_helper_testcase extends advanced_testcase { */ public function test_get_edit_store_form() { $config = cache_config_writer::instance(); - $this->assertTrue($config->add_store_instance('summariesstore', 'file')); + $this->assertTrue($config->add_store_instance('test_get_edit_store_form', 'file')); - $form = cache_administration_helper::get_edit_store_form('file', 'summariesstore'); + $form = cache_administration_helper::get_edit_store_form('file', 'test_get_edit_store_form'); $this->assertInstanceOf('moodleform', $form); try { diff --git a/cache/tests/cache_test.php b/cache/tests/cache_test.php index 5a85f1465e8..9e003720de4 100644 --- a/cache/tests/cache_test.php +++ b/cache/tests/cache_test.php @@ -58,10 +58,37 @@ class core_cache_testcase extends advanced_testcase { cache_factory::reset(); } + /** + * Returns the expected application cache store. + * @return string + */ + protected function get_expected_application_cache_store() { + $expected = 'cachestore_file'; + if (defined('TEST_CACHE_USING_APPLICATION_STORE') && preg_match('#[a-zA-Z][a-zA-Z0-9_]*#', TEST_CACHE_USING_APPLICATION_STORE)) { + $expected = 'cachestore_'.(string)TEST_CACHE_USING_APPLICATION_STORE; + } + return $expected; + } + /** * Tests cache configuration */ public function test_cache_config() { + global $CFG; + + if (defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') && TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH && + !empty($CFG->altcacheconfigpath)) { + // We need to skip this test - it checks the default config structure, but very likely we arn't using the + // default config structure here so theres no point in running the test. + $this->markTestSkipped('Skipped testing default cache config structure as alt cache path is being used.'); + } + + if (defined('TEST_CACHE_USING_APPLICATION_STORE')) { + // We need to skip this test - it checks the default config structure, but very likely we arn't using the + // default config structure here because we are testing against an alternative application store. + $this->markTestSkipped('Skipped testing default cache config structure as alt application store is being used.'); + } + $instance = cache_config::instance(); $this->assertInstanceOf('cache_config_phpunittest', $instance); @@ -474,27 +501,29 @@ class core_cache_testcase extends advanced_testcase { * Test the mappingsonly setting. */ public function test_definition_mappings_only() { + /** @var cache_config_phpunittest $instance */ $instance = cache_config_phpunittest::instance(true); $instance->phpunit_add_definition('phpunit/mappingsonly', array( 'mode' => cache_store::MODE_APPLICATION, 'component' => 'phpunit', 'area' => 'mappingsonly', 'mappingsonly' => true - )); + ), false); $instance->phpunit_add_definition('phpunit/nonmappingsonly', array( 'mode' => cache_store::MODE_APPLICATION, 'component' => 'phpunit', 'area' => 'nonmappingsonly', 'mappingsonly' => false - )); + ), false); $cacheonly = cache::make('phpunit', 'mappingsonly'); $this->assertInstanceOf('cache_application', $cacheonly); $this->assertEquals('cachestore_dummy', $cacheonly->phpunit_get_store_class()); + $expected = $this->get_expected_application_cache_store(); $cachenon = cache::make('phpunit', 'nonmappingsonly'); $this->assertInstanceOf('cache_application', $cachenon); - $this->assertEquals('cachestore_file', $cachenon->phpunit_get_store_class()); + $this->assertEquals($expected, $cachenon->phpunit_get_store_class()); } /** @@ -1074,6 +1103,9 @@ class core_cache_testcase extends advanced_testcase { */ public function test_alt_cache_path() { global $CFG; + if ((defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') && TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH) || !empty($CFG->altcacheconfigpath)) { + $this->markTestSkipped('Skipped testing alt cache path as it is already being used.'); + } $this->resetAfterTest(); $CFG->altcacheconfigpath = $CFG->dataroot.'/cache/altcacheconfigpath'; $instance = cache_config_phpunittest::instance(); @@ -1150,6 +1182,12 @@ class core_cache_testcase extends advanced_testcase { public function test_disable() { global $CFG; + if ((defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') && TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH) || !empty($CFG->altcacheconfigpath)) { + // We can't run this test as it requires us to delete the cache configuration script which we just + // cant do with a custom path in play. + $this->markTestSkipped('Skipped testing cache disable functionality as alt cache path is being used.'); + } + $configfile = $CFG->dataroot.'/muc/config.php'; // That's right, we're deleting the config file. diff --git a/cache/tests/fixtures/lib.php b/cache/tests/fixtures/lib.php index e6ecbe0f407..0e662cbe29d 100644 --- a/cache/tests/fixtures/lib.php +++ b/cache/tests/fixtures/lib.php @@ -28,6 +28,8 @@ defined('MOODLE_INTERNAL') || die(); +require_once($CFG->dirroot.'/cache/locallib.php'); + /** * Override the default cache configuration for our own maniacle purposes. * @@ -36,12 +38,143 @@ defined('MOODLE_INTERNAL') || die(); */ class cache_config_phpunittest extends cache_config_writer { + /** + * Creates the default configuration and saves it. + * + * This function calls config_save, however it is safe to continue using it afterwards as this function should only ever + * be called when there is no configuration file already. + * + * @param bool $forcesave If set to true then we will forcefully save the default configuration file. + * @return true|array Returns true if the default configuration was successfully created. + * Returns a configuration array if it could not be saved. This is a bad situation. Check your error logs. + */ + public static function create_default_configuration($forcesave = false) { + global $CFG; + // HACK ALERT. + // We probably need to come up with a better way to create the default stores, or at least ensure 100% that the + // default store plugins are protected from deletion. + $writer = new self; + $writer->configstores = self::get_default_stores(); + $writer->configdefinitions = self::locate_definitions(); + $defaultapplication = 'default_application'; + + $appdefine = defined('TEST_CACHE_USING_APPLICATION_STORE') ? TEST_CACHE_USING_APPLICATION_STORE : false; + if ($appdefine !== false && preg_match('/^[a-zA-Z][a-zA-Z0-9_]+$/', $appdefine)) { + $expectedstore = $appdefine; + $expecteddefine = 'TEST_CACHESTORE_'.strtoupper($expectedstore).'_TESTSERVERS'; + $file = $CFG->dirroot.'/cache/stores/'.$appdefine.'/lib.php'; + $class = 'cachestore_'.$appdefine; + if (file_exists($file)) { + require_once($file); + } + if (defined($expecteddefine) && class_exists($class)) { + /** @var cache_store $class */ + $writer->configstores['test_application'] = array( + 'use_test_store' => true, + 'name' => 'test_application', + 'plugin' => $expectedstore, + 'alt' => $writer->configstores[$defaultapplication], + 'modes' => $class::get_supported_modes(), + 'features' => $class::get_supported_features() + ); + $defaultapplication = 'test_application'; + } + } + + $writer->configmodemappings = array( + array( + 'mode' => cache_store::MODE_APPLICATION, + 'store' => $defaultapplication, + 'sort' => -1 + ), + array( + 'mode' => cache_store::MODE_SESSION, + 'store' => 'default_session', + 'sort' => -1 + ), + array( + 'mode' => cache_store::MODE_REQUEST, + 'store' => 'default_request', + 'sort' => -1 + ) + ); + $writer->configlocks = array( + 'default_file_lock' => array( + 'name' => 'cachelock_file_default', + 'type' => 'cachelock_file', + 'dir' => 'filelocks', + 'default' => true + ) + ); + + $factory = cache_factory::instance(); + // We expect the cache to be initialising presently. If its not then something has gone wrong and likely + // we are now in a loop. + if (!$forcesave && $factory->get_state() !== cache_factory::STATE_INITIALISING) { + return $writer->generate_configuration_array(); + } + $factory->set_state(cache_factory::STATE_SAVING); + $writer->config_save(); + return true; + } + + /** + * Returns the expected path to the configuration file. + * + * We override this function to add handling for $CFG->altcacheconfigpath. + * We want to support it so that people can run unit tests against alternative cache setups. + * However we don't want to ever make changes to the file at $CFG->altcacheconfigpath so we + * always use dataroot and copy the alt file there as required. + * + * @throws cache_exception + * @return string The absolute path + */ + protected static function get_config_file_path() { + global $CFG; + // We always use this path. + $configpath = $CFG->dataroot.'/muc/config.php'; + + if (!empty($CFG->altcacheconfigpath)) { + + if (defined('PHPUNIT_TEST') && PHPUNIT_TEST && + (!defined('TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH') || !TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH)) { + // We're within a unit test, but TEST_CACHE_USING_ALT_CACHE_CONFIG_PATH has not being defined or is + // false, we want to use the default. + return $configpath; + } + + $path = $CFG->altcacheconfigpath; + if (is_dir($path) && is_writable($path)) { + // Its a writable directory, thats fine. Convert it to a file. + $path = $CFG->altcacheconfigpath.'/cacheconfig.php'; + } + if (is_readable($path)) { + $directory = dirname($configpath); + if ($directory !== $CFG->dataroot && !file_exists($directory)) { + $result = make_writable_directory($directory, false); + if (!$result) { + throw new cache_exception('ex_configcannotsave', 'cache', '', null, 'Cannot create config directory. Check the permissions on your moodledata directory.'); + } + } + // We don't care that this fails but we should let the developer know. + if (!is_readable($configpath) && !@copy($path, $configpath)) { + debugging('Failed to copy alt cache config file to required location'); + } + } + } + + // We always use the dataroot location. + return $configpath; + } + /** * Adds a definition to the stack * @param string $area * @param array $properties + * @param bool $addmapping By default this method adds a definition and a mapping for that definition. You can + * however set this to false if you only want it to add the definition and not the mapping. */ - public function phpunit_add_definition($area, array $properties) { + public function phpunit_add_definition($area, array $properties, $addmapping = true) { if (!array_key_exists('overrideclass', $properties)) { switch ($properties['mode']) { case cache_store::MODE_APPLICATION: @@ -56,6 +189,19 @@ class cache_config_phpunittest extends cache_config_writer { } } $this->configdefinitions[$area] = $properties; + if ($addmapping) { + switch ($properties['mode']) { + case cache_store::MODE_APPLICATION: + $this->phpunit_add_definition_mapping($area, 'default_application', 0); + break; + case cache_store::MODE_SESSION: + $this->phpunit_add_definition_mapping($area, 'default_session', 0); + break; + case cache_store::MODE_REQUEST: + $this->phpunit_add_definition_mapping($area, 'default_request', 0); + break; + } + } } /** @@ -343,4 +489,34 @@ class cache_phpunit_factory extends cache_factory { public static function phpunit_disable() { parent::disable(); } + + /** + * Creates a store instance given its name and configuration. + * + * If the store has already been instantiated then the original object will be returned. (reused) + * + * @param string $name The name of the store (must be unique remember) + * @param array $details + * @param cache_definition $definition The definition to instantiate it for. + * @return boolean|cache_store + */ + public function create_store_from_config($name, array $details, cache_definition $definition) { + + if (isset($details['use_test_store'])) { + // name, plugin, alt + $class = 'cachestore_'.$details['plugin']; + $method = 'initialise_unit_test_instance'; + if (class_exists($class) && method_exists($class, $method)) { + $instance = $class::$method($definition); + + if ($instance) { + return $instance; + } + } + $details = $details['alt']; + $name = $details['name']; + } + + return parent::create_store_from_config($name, $details, $definition); + } } \ No newline at end of file diff --git a/lib/phpunit/bootstrap.php b/lib/phpunit/bootstrap.php index 983e5e2b5ea..683e76403c0 100644 --- a/lib/phpunit/bootstrap.php +++ b/lib/phpunit/bootstrap.php @@ -181,6 +181,7 @@ $CFG->dboptions = isset($CFG->phpunit_dboptions) ? $CFG->phpunit_dboptions : $CF $allowed = array('wwwroot', 'dataroot', 'dirroot', 'admin', 'directorypermissions', 'filepermissions', 'dbtype', 'dblibrary', 'dbhost', 'dbname', 'dbuser', 'dbpass', 'prefix', 'dboptions', 'proxyhost', 'proxyport', 'proxytype', 'proxyuser', 'proxypassword', 'proxybypass', // keep proxy settings from config.php + 'altcacheconfigpath' ); $productioncfg = (array)$CFG; $CFG = new stdClass();