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..b9b42f4d877 100644 --- a/cache/classes/factory.php +++ b/cache/classes/factory.php @@ -325,11 +325,21 @@ 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'; + // Check if this is a PHPUnit test and redirect to the phpunit config classes if it is. + if (defined('PHPUNIT_TEST') && PHPUNIT_TEST) { + 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 + // performance to do otherwise and having a single method allows us to inject things into it + // while testing. + $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'); $class .= '_writer'; @@ -350,6 +360,7 @@ class cache_factory { // 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/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/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..7d8fe16434a 100644 --- a/cache/tests/cache_test.php +++ b/cache/tests/cache_test.php @@ -62,6 +62,14 @@ class core_cache_testcase extends advanced_testcase { * Tests cache configuration */ public function test_cache_config() { + global $CFG; + + if (!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.'); + } + $instance = cache_config::instance(); $this->assertInstanceOf('cache_config_phpunittest', $instance); @@ -1074,6 +1082,9 @@ class core_cache_testcase extends advanced_testcase { */ public function test_alt_cache_path() { global $CFG; + if ($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 +1161,12 @@ class core_cache_testcase extends advanced_testcase { public function test_disable() { global $CFG; + if (!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..845ca41deaa 100644 --- a/cache/tests/fixtures/lib.php +++ b/cache/tests/fixtures/lib.php @@ -36,6 +36,47 @@ defined('MOODLE_INTERNAL') || die(); */ class cache_config_phpunittest extends cache_config_writer { + /** + * 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)) { + $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 @@ -56,6 +97,17 @@ class cache_config_phpunittest extends cache_config_writer { } } $this->configdefinitions[$area] = $properties; + 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; + } } /** 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();