From 99a6cd12b2b2bedde24170e217e2987fde211ac8 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Thu, 21 Sep 2023 23:46:22 +0800 Subject: [PATCH 1/2] MDL-79637 phpunit: Do not reset DB during init of isolated tests During the bootstrap of PHPUnit we ensure that the database has been reset to its initial state. We do this by checking the internally-stored DB write count between runs. If the count is not yet set (null), or it has been increased, we force a reset. When running an isolated test the test runner resets the database, it then sets up a new isolated test environment by writing a new PHPUnit test case and passing it to a new PHP Process using standard in. As part of this, the bootstrap is run for that process. Because we are in a new process, the db write count is fresh and not yet set. This has been leading to an additional db reset before the isolated test. To handle this we want to _not_ perform a reset during the initialisation for isolated runs. We know that the DB is in a fresh state before we start the run. To support this we need to know whether the test is an isolated test during the bootstrap, which means we cannot use the previous approach to calculating this. Instead we look at the PHP_SELF value. PHP sets this to "Standard input code" when run from stdin, instead of running a file. There should not be any other legitimate reason to run a PHPUnit bootstrap via this stdin approach. Unfortunately this approach is a little bit risky as it depends on the presence of a specific string, however this string has been in place since 2016, and there is no legitimate way of calculating this. I did consider looking at whether the called script included `/vendor/` and `/phpunit`, but this is also likely a risky approach if someone calls PHPUnit in an unexpected way. This approach is itself unit tested so any change to PHP's stdin string before we deprecate this approach entirely in 12 months time will be caught. --- lib/phpunit/bootstrap.php | 14 ++++++++++++++ lib/phpunit/classes/advanced_testcase.php | 13 ------------- lib/phpunit/classes/util.php | 8 +++++++- lib/setuplib.php | 2 +- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/lib/phpunit/bootstrap.php b/lib/phpunit/bootstrap.php index dd15d1bb189..c7cf470686c 100644 --- a/lib/phpunit/bootstrap.php +++ b/lib/phpunit/bootstrap.php @@ -205,6 +205,20 @@ ini_set('log_errors', '1'); $CFG->themerev = 1; $CFG->jsrev = 1; +(function () { + // Determine if this test is being run with isolation. + // This is tricky because neither PHPUnit, nor PHP provide an official way to work this out. + // PHPUnit does set a value, but not until later on and we need this earlier. + // PHPUnit runs isolated tests by creating a class on the fly and running it through proc_open as standard input. + // There is no other legitimate reason to run PHPUnit this way that I'm aware of. + // When run in this way, PHP sets the value of $_SERVER['PHP_SELF'] to "Standard input code". + // It has done this since 2016, and it is unlikely to change. + define( + 'PHPUNIT_ISOLATED_TEST', + $_SERVER['PHP_SELF'] === 'Standard input code', + ); +})(); + // load test case stub classes and other stuff require_once("$CFG->dirroot/lib/phpunit/lib.php"); diff --git a/lib/phpunit/classes/advanced_testcase.php b/lib/phpunit/classes/advanced_testcase.php index 25ceef15107..eb7a9ae1a24 100644 --- a/lib/phpunit/classes/advanced_testcase.php +++ b/lib/phpunit/classes/advanced_testcase.php @@ -60,19 +60,6 @@ abstract class advanced_testcase extends base_testcase { } - /** - * Hook into the setInIsolation method to define an optional constant. - * - * @param bool $inisolation - */ - public function setInIsolation(bool $inisolation): void { - parent::setInIsolation($inisolation); - if ($inisolation) { - // Note: This is safe to do because it will only be set once per test run. - define('PHPUNIT_ISOLATED_TEST', true); - } - } - /** * Runs the bare test sequence. * @return void diff --git a/lib/phpunit/classes/util.php b/lib/phpunit/classes/util.php index fc131dc2614..0b0aec7eae6 100644 --- a/lib/phpunit/classes/util.php +++ b/lib/phpunit/classes/util.php @@ -320,7 +320,13 @@ class phpunit_util extends testing_util { public static function reset_database() { global $DB; - if (!is_null(self::$lastdbwrites) and self::$lastdbwrites == $DB->perf_get_writes()) { + if (defined('PHPUNIT_ISOLATED_TEST') && PHPUNIT_ISOLATED_TEST && self::$lastdbwrites === null) { + // This is an isolated test and the lastdbwrites has not yet been initialised. + // Isolated test runs are reset by the test runner before the run starts. + self::$lastdbwrites = $DB->perf_get_writes(); + } + + if (!is_null(self::$lastdbwrites) && self::$lastdbwrites == $DB->perf_get_writes()) { return false; } diff --git a/lib/setuplib.php b/lib/setuplib.php index 0a5af63d64e..47cc23030a6 100644 --- a/lib/setuplib.php +++ b/lib/setuplib.php @@ -2202,7 +2202,7 @@ function require_phpunit_isolation(): void { return; } - if (defined('PHPUNIT_ISOLATED_TEST')) { + if (defined('PHPUNIT_ISOLATED_TEST') && PHPUNIT_ISOLATED_TEST) { // Already isolated. return; } From 49fc711a0768bb0d0b6bf1a1846ef93904ec7b0a Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Tue, 10 Oct 2023 14:44:13 +0800 Subject: [PATCH 2/2] MDL-79637 testing: Update for current coding standards --- lib/phpunit/bootstrap.php | 109 ++++++----- lib/phpunit/classes/advanced_testcase.php | 93 +++++----- lib/testing/classes/util.php | 213 +++++++++++----------- 3 files changed, 210 insertions(+), 205 deletions(-) diff --git a/lib/phpunit/bootstrap.php b/lib/phpunit/bootstrap.php index c7cf470686c..0ac815e3143 100644 --- a/lib/phpunit/bootstrap.php +++ b/lib/phpunit/bootstrap.php @@ -26,18 +26,20 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +// phpcs:disable moodle.Files.MoodleInternal.MoodleInternalGlobalState + if (isset($_SERVER['REMOTE_ADDR'])) { die; // No access from web! } -// we want to know about all problems +// We want to know about all problems. error_reporting(E_ALL | E_STRICT); ini_set('display_errors', '1'); ini_set('log_errors', '1'); // Make sure OPcache does not strip comments, we need them in phpunit! -if (ini_get('opcache.enable') and strtolower(ini_get('opcache.enable')) !== 'off') { - if (!ini_get('opcache.save_comments') or strtolower(ini_get('opcache.save_comments')) === 'off') { +if (ini_get('opcache.enable') && strtolower(ini_get('opcache.enable')) !== 'off') { + if (!ini_get('opcache.save_comments') || strtolower(ini_get('opcache.save_comments')) === 'off') { ini_set('opcache.enable', 0); } } @@ -46,8 +48,8 @@ if (!defined('IGNORE_COMPONENT_CACHE')) { define('IGNORE_COMPONENT_CACHE', true); } -require_once(__DIR__.'/bootstraplib.php'); -require_once(__DIR__.'/../testing/lib.php'); +require_once(__DIR__ . '/bootstraplib.php'); +require_once(__DIR__ . '/../testing/lib.php'); if (isset($_SERVER['REMOTE_ADDR'])) { phpunit_bootstrap_error(1, 'Unit tests can be executed only from command line!'); @@ -56,6 +58,7 @@ if (isset($_SERVER['REMOTE_ADDR'])) { if (defined('PHPUNIT_TEST')) { phpunit_bootstrap_error(1, "PHPUNIT_TEST constant must not be manually defined anywhere!"); } + /** PHPUnit testing framework active */ define('PHPUNIT_TEST', true); @@ -70,14 +73,15 @@ if (defined('CLI_SCRIPT')) { define('CLI_SCRIPT', true); $phpunitversion = PHPUnit\Runner\Version::id(); +// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedIf if ($phpunitversion === '@package_version@') { - // library checked out from git, let's hope dev knows that 3.6.0 is required + // Library checked out from git, let's hope dev knows that 3.6.0 is required. } else if (version_compare($phpunitversion, '3.6.0', 'lt')) { phpunit_bootstrap_error(PHPUNIT_EXITCODE_PHPUNITWRONG, $phpunitversion); } unset($phpunitversion); -// only load CFG from config.php, stop ASAP in lib/setup.php +// Only load CFG from config.php, stop ASAP in lib/setup.php. define('ABORT_AFTER_CONFIG', true); require(__DIR__ . '/../../config.php'); @@ -86,13 +90,13 @@ if (!defined('PHPUNIT_LONGTEST')) { define('PHPUNIT_LONGTEST', false); } -// remove error handling overrides done in config.php +// Remove error handling overrides done in config.php. error_reporting(E_ALL | E_STRICT); ini_set('display_errors', '1'); ini_set('log_errors', '1'); -set_time_limit(0); // no time limit in CLI scripts, user may cancel execution +set_time_limit(0); // No time limit in CLI scripts, user may cancel execution. -// prepare dataroot +// Prepare dataroot. umask(0); if (isset($CFG->phpunit_directorypermissions)) { $CFG->directorypermissions = $CFG->phpunit_directorypermissions; @@ -101,7 +105,10 @@ if (isset($CFG->phpunit_directorypermissions)) { } $CFG->filepermissions = ($CFG->directorypermissions & 0666); if (!isset($CFG->phpunit_dataroot)) { - phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGERROR, 'Missing $CFG->phpunit_dataroot in config.php, can not run tests!'); + phpunit_bootstrap_error( + PHPUNIT_EXITCODE_CONFIGERROR, + 'Missing $CFG->phpunit_dataroot in config.php, can not run tests!', + ); } // Create test dir if does not exists yet. @@ -109,18 +116,24 @@ if (!file_exists($CFG->phpunit_dataroot)) { mkdir($CFG->phpunit_dataroot, $CFG->directorypermissions); } if (!is_dir($CFG->phpunit_dataroot)) { - phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGERROR, '$CFG->phpunit_dataroot directory can not be created, can not run tests!'); + phpunit_bootstrap_error( + PHPUNIT_EXITCODE_CONFIGERROR, + '$CFG->phpunit_dataroot directory can not be created, can not run tests!', + ); } // Ensure we access to phpunit_dataroot realpath always. $CFG->phpunit_dataroot = realpath($CFG->phpunit_dataroot); -if (isset($CFG->dataroot) and $CFG->phpunit_dataroot === $CFG->dataroot) { - phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGERROR, '$CFG->dataroot and $CFG->phpunit_dataroot must not be identical, can not run tests!'); +if (isset($CFG->dataroot) && $CFG->phpunit_dataroot === $CFG->dataroot) { + phpunit_bootstrap_error( + PHPUNIT_EXITCODE_CONFIGERROR, + '$CFG->dataroot and $CFG->phpunit_dataroot must not be identical, can not run tests!', + ); } if (!is_writable($CFG->phpunit_dataroot)) { - // try to fix permissions if possible + // Try to fix permissions if possible. if (function_exists('posix_getuid')) { $chmod = fileperms($CFG->phpunit_dataroot); if (fileowner($CFG->phpunit_dataroot) == posix_getuid()) { @@ -129,38 +142,47 @@ if (!is_writable($CFG->phpunit_dataroot)) { } } if (!is_writable($CFG->phpunit_dataroot)) { - phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGERROR, '$CFG->phpunit_dataroot directory is not writable, can not run tests!'); + phpunit_bootstrap_error( + PHPUNIT_EXITCODE_CONFIGERROR, + '$CFG->phpunit_dataroot directory is not writable, can not run tests!', + ); } } if (!file_exists("$CFG->phpunit_dataroot/phpunittestdir.txt")) { if ($dh = opendir($CFG->phpunit_dataroot)) { while (($file = readdir($dh)) !== false) { - if ($file === 'phpunit' or $file === '.' or $file === '..' or $file === '.DS_Store') { + if ($file === 'phpunit' || $file === '.' || $file === '..' || $file === '.DS_Store') { continue; } - phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGERROR, '$CFG->phpunit_dataroot directory is not empty, can not run tests! Is it used for anything else?'); + phpunit_bootstrap_error( + PHPUNIT_EXITCODE_CONFIGERROR, + '$CFG->phpunit_dataroot directory is not empty, can not run tests! Is it used for anything else?', + ); } closedir($dh); unset($dh); unset($file); } - // now we are 100% sure this dir is used only for phpunit tests + // Now we are 100% sure this dir is used only for phpunit tests. testing_initdataroot($CFG->phpunit_dataroot, 'phpunit'); } -// verify db prefix +// Verify db prefix. if (!isset($CFG->phpunit_prefix)) { phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGERROR, 'Missing $CFG->phpunit_prefix in config.php, can not run tests!'); } if ($CFG->phpunit_prefix === '') { phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGERROR, '$CFG->phpunit_prefix can not be empty, can not run tests!'); } -if (isset($CFG->prefix) and $CFG->prefix === $CFG->phpunit_prefix) { - phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGERROR, '$CFG->prefix and $CFG->phpunit_prefix must not be identical, can not run tests!'); +if (isset($CFG->prefix) && $CFG->prefix === $CFG->phpunit_prefix) { + phpunit_bootstrap_error( + PHPUNIT_EXITCODE_CONFIGERROR, + '$CFG->prefix and $CFG->phpunit_prefix must not be identical, can not run tests!', + ); } -// override CFG settings if necessary and throw away extra CFG settings +// Override CFG settings if necessary and throw away extra CFG settings. $CFG->wwwroot = 'https://www.example.com/moodle'; $CFG->dataroot = $CFG->phpunit_dataroot; $CFG->prefix = $CFG->phpunit_prefix; @@ -173,17 +195,18 @@ $CFG->dbpass = isset($CFG->phpunit_dbpass) ? $CFG->phpunit_dbpass : $CFG->dbp $CFG->prefix = isset($CFG->phpunit_prefix) ? $CFG->phpunit_prefix : $CFG->prefix; $CFG->dboptions = isset($CFG->phpunit_dboptions) ? $CFG->phpunit_dboptions : $CFG->dboptions; -$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', 'pathtogs', 'pathtophp', 'pathtodu', 'aspellpath', 'pathtodot', - 'pathtounoconv', 'alternative_file_system_class', 'pathtopython' - ); -$productioncfg = (array)$CFG; +$allowed = ['wwwroot', 'dataroot', 'dirroot', 'admin', 'directorypermissions', 'filepermissions', + 'dbtype', 'dblibrary', 'dbhost', 'dbname', 'dbuser', 'dbpass', 'prefix', 'dboptions', + // Keep proxy settings from config.php. + 'proxyhost', 'proxyport', 'proxytype', 'proxyuser', 'proxypassword', 'proxybypass', + 'altcacheconfigpath', 'pathtogs', 'pathtophp', 'pathtodu', 'aspellpath', 'pathtodot', + 'pathtounoconv', 'alternative_file_system_class', 'pathtopython', +]; +$productioncfg = (array) $CFG; $CFG = new stdClass(); -foreach ($productioncfg as $key=>$value) { - if (!in_array($key, $allowed) and strpos($key, 'phpunit_') !== 0 and strpos($key, 'behat_') !== 0) { - // ignore +foreach ($productioncfg as $key => $value) { + if (!in_array($key, $allowed) && strpos($key, 'phpunit_') !== 0 && strpos($key, 'behat_') !== 0) { + // Ignore. continue; } $CFG->{$key} = $value; @@ -193,15 +216,15 @@ unset($value); unset($allowed); unset($productioncfg); -// force the same CFG settings in all sites -$CFG->debug = (E_ALL | E_STRICT); // can not use DEBUG_DEVELOPER yet +// Force the same CFG settings in all sites. +$CFG->debug = (E_ALL | E_STRICT); // Can not use DEBUG_DEVELOPER yet. $CFG->debugdeveloper = true; $CFG->debugdisplay = 1; error_reporting($CFG->debug); ini_set('display_errors', '1'); ini_set('log_errors', '1'); -// some ugly hacks +// Some ugly hacks. $CFG->themerev = 1; $CFG->jsrev = 1; @@ -219,10 +242,10 @@ $CFG->jsrev = 1; ); })(); -// load test case stub classes and other stuff +// Load test case stub classes and other stuff. require_once("$CFG->dirroot/lib/phpunit/lib.php"); -// finish moodle init +// Finish moodle init. define('ABORT_AFTER_CONFIG_CANCEL', true); if (isset($CFG->phpunit_profilingenabled) && $CFG->phpunit_profilingenabled) { $CFG->profilingenabled = true; @@ -233,7 +256,7 @@ require("$CFG->dirroot/lib/setup.php"); raise_memory_limit(MEMORY_HUGE); if (PHPUNIT_UTIL) { - // we are not going to do testing, this is 'true' in utility scripts that only init database + // We are not going to do testing, this is 'true' in utility scripts that only init database. return; } @@ -241,13 +264,13 @@ if (PHPUNIT_UTIL) { // this is not using caches intentionally to help with development. \core\hook\manager::get_instance(); -// is database and dataroot ready for testing? -list($errorcode, $message) = phpunit_util::testing_ready_problem(); -// print some version info +// Is database and dataroot ready for testing? +[$errorcode, $message] = phpunit_util::testing_ready_problem(); +// Print some version info. phpunit_util::bootstrap_moodle_info(); if ($errorcode) { phpunit_bootstrap_error($errorcode, $message); } -// prepare for the first test run - store fresh globals, reset database and dataroot, etc. +// Prepare for the first test run - store fresh globals, reset database and dataroot, etc. phpunit_util::bootstrap_init(); diff --git a/lib/phpunit/classes/advanced_testcase.php b/lib/phpunit/classes/advanced_testcase.php index eb7a9ae1a24..87d2f442c7c 100644 --- a/lib/phpunit/classes/advanced_testcase.php +++ b/lib/phpunit/classes/advanced_testcase.php @@ -14,16 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Advanced test case. - * - * @package core - * @category phpunit - * @copyright 2012 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - - /** * Advanced PHPUnit test case customised for Moodle. * @@ -34,6 +24,7 @@ */ abstract class advanced_testcase extends base_testcase { /** @var bool automatically reset everything? null means log changes */ + // phpcs:ignore moodle.NamingConventions.ValidVariableName.MemberNameUnderscore private $resetAfterTest; /** @var moodle_transaction */ @@ -51,44 +42,40 @@ abstract class advanced_testcase extends base_testcase { * @param array $data * @param string $dataName */ - final public function __construct($name = null, array $data = array(), $dataName = '') { - parent::__construct($name, $data, $dataName); + final public function __construct($name = null, array $data = [], $dataname = '') { + parent::__construct($name, $data, $dataname); $this->setBackupGlobals(false); $this->setBackupStaticAttributes(false); $this->setPreserveGlobalState(false); - } /** * Runs the bare test sequence. - * @return void */ final public function runBare(): void { global $DB; if (phpunit_util::$lastdbwrites != $DB->perf_get_writes()) { - // this happens when previous test does not reset, we can not use transactions + // This happens when previous test does not reset, we can not use transactions. $this->testdbtransaction = null; - - } else if ($DB->get_dbfamily() === 'postgres' or $DB->get_dbfamily() === 'mssql') { - // database must allow rollback of DDL, so no mysql here + } else if ($DB->get_dbfamily() === 'postgres' || $DB->get_dbfamily() === 'mssql') { + // Database must allow rollback of DDL, so no mysql here. $this->testdbtransaction = $DB->start_delegated_transaction(); } try { $this->setCurrentTimeStart(); parent::runBare(); - // set DB reference in case somebody mocked it in test + // Set DB reference in case somebody mocked it in test. $DB = phpunit_util::get_global_backup('DB'); // Deal with any debugging messages. $debugerror = phpunit_util::display_debugging_messages(true); $this->resetDebugging(); if (!empty($debugerror)) { - trigger_error('Unexpected debugging() call detected.'."\n".$debugerror, E_USER_NOTICE); + trigger_error('Unexpected debugging() call detected.' . "\n" . $debugerror, E_USER_NOTICE); } - } catch (Exception $ex) { $e = $ex; } catch (Throwable $ex) { @@ -97,12 +84,12 @@ abstract class advanced_testcase extends base_testcase { } if (isset($e)) { - // cleanup after failed expectation + // Cleanup after failed expectation. self::resetAllData(); throw $e; } - if (!$this->testdbtransaction or $this->testdbtransaction->is_disposed()) { + if (!$this->testdbtransaction || $this->testdbtransaction->is_disposed()) { $this->testdbtransaction = null; } @@ -110,24 +97,22 @@ abstract class advanced_testcase extends base_testcase { if ($this->testdbtransaction) { $DB->force_transaction_rollback(); phpunit_util::reset_all_database_sequences(); - phpunit_util::$lastdbwrites = $DB->perf_get_writes(); // no db reset necessary + phpunit_util::$lastdbwrites = $DB->perf_get_writes(); // No db reset necessary. } self::resetAllData(null); - } else if ($this->resetAfterTest === false) { if ($this->testdbtransaction) { $this->testdbtransaction->allow_commit(); } - // keep all data untouched for other tests - + // Keep all data untouched for other tests. } else { - // reset but log what changed + // Reset but log what changed. if ($this->testdbtransaction) { try { $this->testdbtransaction->allow_commit(); } catch (dml_transaction_exception $e) { self::resetAllData(); - throw new coding_exception('Invalid transaction state detected in test '.$this->getName()); + throw new coding_exception('Invalid transaction state detected in test ' . $this->getName()); } } self::resetAllData(true); @@ -136,13 +121,15 @@ abstract class advanced_testcase extends base_testcase { // Reset context cache. context_helper::reset_caches(); - // make sure test did not forget to close transaction + // Make sure test did not forget to close transaction. if ($DB->is_transaction_started()) { self::resetAllData(); - if ($this->getStatus() == PHPUnit\Runner\BaseTestRunner::STATUS_PASSED - or $this->getStatus() == PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED - or $this->getStatus() == PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE) { - throw new coding_exception('Test '.$this->getName().' did not close database transaction'); + if ( + $this->getStatus() == PHPUnit\Runner\BaseTestRunner::STATUS_PASSED + || $this->getStatus() == PHPUnit\Runner\BaseTestRunner::STATUS_SKIPPED + || $this->getStatus() == PHPUnit\Runner\BaseTestRunner::STATUS_INCOMPLETE + ) { + throw new coding_exception('Test ' . $this->getName() . ' did not close database transaction'); } } } @@ -239,7 +226,7 @@ abstract class advanced_testcase extends base_testcase { * @return void */ public function preventResetByRollback() { - if ($this->testdbtransaction and !$this->testdbtransaction->is_disposed()) { + if ($this->testdbtransaction && !$this->testdbtransaction->is_disposed()) { $this->testdbtransaction->allow_commit(); $this->testdbtransaction = null; } @@ -282,7 +269,7 @@ abstract class advanced_testcase extends base_testcase { */ public function assertDebuggingCalled($debugmessage = null, $debuglevel = null, $message = '') { $debugging = $this->getDebuggingMessages(); - $debugdisplaymessage = "\n".phpunit_util::display_debugging_messages(true); + $debugdisplaymessage = "\n" . phpunit_util::display_debugging_messages(true); $this->resetDebugging(); $count = count($debugging); @@ -295,7 +282,7 @@ abstract class advanced_testcase extends base_testcase { } if ($count > 1) { if ($message === '') { - $message = 'Expectation failed, debugging() triggered '.$count.' times.'.$debugdisplaymessage; + $message = 'Expectation failed, debugging() triggered ' . $count . ' times.' . $debugdisplaymessage; } $this->fail($message); } @@ -320,20 +307,22 @@ abstract class advanced_testcase extends base_testcase { * @param string $message * @return void */ - public function assertDebuggingCalledCount($expectedcount, $debugmessages = array(), $debuglevels = array(), $message = '') { + public function assertdebuggingcalledcount($expectedcount, $debugmessages = [], $debuglevels = [], $message = '') { if (!is_int($expectedcount)) { throw new coding_exception('assertDebuggingCalledCount $expectedcount argument should be an integer.'); } $debugging = $this->getDebuggingMessages(); - $message .= "\n".phpunit_util::display_debugging_messages(true); + $message .= "\n" . phpunit_util::display_debugging_messages(true); $this->resetDebugging(); $this->assertEquals($expectedcount, count($debugging), $message); if ($debugmessages) { if (!is_array($debugmessages) || count($debugmessages) != $expectedcount) { - throw new coding_exception('assertDebuggingCalledCount $debugmessages should contain ' . $expectedcount . ' messages'); + throw new coding_exception( + 'assertDebuggingCalledCount $debugmessages should contain ' . $expectedcount . ' messages', + ); } foreach ($debugmessages as $key => $debugmessage) { $this->assertSame($debugmessage, $debugging[$key]->message, $message); @@ -342,7 +331,9 @@ abstract class advanced_testcase extends base_testcase { if ($debuglevels) { if (!is_array($debuglevels) || count($debuglevels) != $expectedcount) { - throw new coding_exception('assertDebuggingCalledCount $debuglevels should contain ' . $expectedcount . ' messages'); + throw new coding_exception( + 'assertDebuggingCalledCount $debuglevels should contain ' . $expectedcount . ' messages', + ); } foreach ($debuglevels as $key => $debuglevel) { $this->assertSame($debuglevel, $debugging[$key]->level, $message); @@ -441,9 +432,9 @@ abstract class advanced_testcase extends base_testcase { * @return void */ public function assertTimeCurrent($time, $message = '') { - $msg = ($message === '') ? 'Time is lower that allowed start value' : $message; + $msg = ($message === '') ? 'Time is lower that allowed start value' : $message; $this->assertGreaterThanOrEqual($this->currenttimestart, $time, $msg); - $msg = ($message === '') ? 'Time is in the future' : $message; + $msg = ($message === '') ? 'Time is in the future' : $message; $this->assertLessThanOrEqual(time(), $time, $msg); } @@ -535,7 +526,7 @@ abstract class advanced_testcase extends base_testcase { $user->id = 0; $user->mnethostid = $CFG->mnet_localhost_id; } else { - $user = $DB->get_record('user', array('id'=>$user)); + $user = $DB->get_record('user', ['id' => $user]); } unset($user->description); unset($user->access); @@ -606,25 +597,25 @@ abstract class advanced_testcase extends base_testcase { public function getExternalTestFileUrl($path, $https = false) { $path = ltrim($path, '/'); if ($path) { - $path = '/'.$path; + $path = '/' . $path; } if ($https) { if (defined('TEST_EXTERNAL_FILES_HTTPS_URL')) { if (!TEST_EXTERNAL_FILES_HTTPS_URL) { $this->markTestSkipped('Tests using external https test files are disabled'); } - return TEST_EXTERNAL_FILES_HTTPS_URL.$path; + return TEST_EXTERNAL_FILES_HTTPS_URL . $path; } - return 'https://download.moodle.org/unittest'.$path; + return 'https://download.moodle.org/unittest' . $path; } if (defined('TEST_EXTERNAL_FILES_HTTP_URL')) { if (!TEST_EXTERNAL_FILES_HTTP_URL) { $this->markTestSkipped('Tests using external http test files are disabled'); } - return TEST_EXTERNAL_FILES_HTTP_URL.$path; + return TEST_EXTERNAL_FILES_HTTP_URL . $path; } - return 'http://download.moodle.org/unittest'.$path; + return 'http://download.moodle.org/unittest' . $path; } /** @@ -643,9 +634,9 @@ abstract class advanced_testcase extends base_testcase { $files = scandir($path); foreach ($files as $file) { - $filepath = $path .'/'. $file; + $filepath = $path . '/' . $file; if (strpos($file, '.') === 0) { - /// Don't check hidden files. + // Don't check hidden files. continue; } else if (is_dir($filepath)) { if (!in_array($filepath, $ignorefolders)) { diff --git a/lib/testing/classes/util.php b/lib/testing/classes/util.php index 737c7532472..aca575def06 100644 --- a/lib/testing/classes/util.php +++ b/lib/testing/classes/util.php @@ -17,23 +17,12 @@ /** * Testing util classes * - * @abstract * @package core * @category test * @copyright 2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ - -/** - * Utils for test sites creation - * - * @package core - * @category test - * @copyright 2012 Petr Skoda {@link http://skodak.org} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ abstract class testing_util { - /** * @var string dataroot (likely to be $CFG->dataroot). */ @@ -62,12 +51,12 @@ abstract class testing_util { /** * @var array keep list of sequenceid used in a table. */ - private static $tablesequences = array(); + private static $tablesequences = []; /** * @var array list of updated tables. */ - public static $tableupdated = array(); + public static $tableupdated = []; /** * @var array original structure of all database tables @@ -108,7 +97,7 @@ abstract class testing_util { public static function get_dataroot() { global $CFG; - // By default it's the test framework dataroot. + // By default it's the test framework dataroot. if (empty(self::$dataroot)) { self::$dataroot = $CFG->dataroot; } @@ -131,7 +120,7 @@ abstract class testing_util { * @static * @return string */ - protected static final function get_framework() { + final protected static function get_framework() { $classname = get_called_class(); return substr($classname, 0, strpos($classname, '_')); } @@ -143,7 +132,7 @@ abstract class testing_util { */ public static function get_data_generator() { if (is_null(self::$generator)) { - require_once(__DIR__.'/../generator/lib.php'); + require_once(__DIR__ . '/../generator/lib.php'); self::$generator = new testing_data_generator(); } return self::$generator; @@ -162,8 +151,8 @@ abstract class testing_util { $framework = self::get_framework(); if (!file_exists(self::get_dataroot() . '/' . $framework . 'testdir.txt')) { - // this is already tested in bootstrap script, - // but anyway presence of this file means the dataroot is for testing + // This is already tested in bootstrap script, + // But anyway presence of this file means the dataroot is for testing. return false; } @@ -191,7 +180,7 @@ abstract class testing_util { $framework = self::get_framework(); $datarootpath = self::get_dataroot() . '/' . $framework; - if (!file_exists($datarootpath . '/tabledata.ser') or !file_exists($datarootpath . '/tablestructure.ser')) { + if (!file_exists($datarootpath . '/tabledata.ser') || !file_exists($datarootpath . '/tablestructure.ser')) { return false; } @@ -207,7 +196,7 @@ abstract class testing_util { } // A direct database request must be used to avoid any possible caching of an older value. - $dbhash = $DB->get_field('config', 'value', array('name' => $framework . 'test')); + $dbhash = $DB->get_field('config', 'value', ['name' => $framework . 'test']); if ($hash !== $dbhash) { return false; } @@ -226,18 +215,18 @@ abstract class testing_util { $framework = self::get_framework(); - // store data for all tables - $data = array(); - $structure = array(); + // Store data for all tables. + $data = []; + $structure = []; $tables = $DB->get_tables(); foreach ($tables as $table) { $columns = $DB->get_columns($table); $structure[$table] = $columns; - if (isset($columns['id']) and $columns['id']->auto_increment) { - $data[$table] = $DB->get_records($table, array(), 'id ASC'); + if (isset($columns['id']) && $columns['id']->auto_increment) { + $data[$table] = $DB->get_records($table, [], 'id ASC'); } else { - // there should not be many of these - $data[$table] = $DB->get_records($table, array()); + // There should not be many of these. + $data[$table] = $DB->get_records($table, []); } } $data = serialize($data); @@ -260,10 +249,10 @@ abstract class testing_util { $framework = self::get_framework(); $hash = core_component::get_all_versions_hash(); - // add test db flag + // Add test db flag. set_config($framework . 'test', $hash); - // hash all plugin versions - helps with very fast detection of db structure changes + // Hash all plugin versions - helps with very fast detection of db structure changes. $hashfile = self::get_dataroot() . '/' . $framework . '/versionshash.txt'; file_put_contents($hashfile, $hash); testing_fix_file_permissions($hashfile); @@ -281,7 +270,7 @@ abstract class testing_util { $datafile = self::get_dataroot() . '/' . $framework . '/tabledata.ser'; if (!file_exists($datafile)) { // Not initialised yet. - return array(); + return []; } $data = file_get_contents($datafile); @@ -289,7 +278,10 @@ abstract class testing_util { } if (!is_array(self::$tabledata)) { - testing_error(1, 'Can not read dataroot/' . $framework . '/tabledata.ser or invalid format, reinitialize test database.'); + testing_error( + 1, + 'Can not read dataroot/' . $framework . '/tabledata.ser or invalid format, reinitialize test database.', + ); } return self::$tabledata; @@ -307,7 +299,7 @@ abstract class testing_util { $structurefile = self::get_dataroot() . '/' . $framework . '/tablestructure.ser'; if (!file_exists($structurefile)) { // Not initialised yet. - return array(); + return []; } $data = file_get_contents($structurefile); @@ -315,7 +307,10 @@ abstract class testing_util { } if (!is_array(self::$tablestructure)) { - testing_error(1, 'Can not read dataroot/' . $framework . '/tablestructure.ser or invalid format, reinitialize test database.'); + testing_error( + 1, + "Can not read dataroot/{$framework}/tablestructure.ser or invalid format, reinitialize test database.", + ); } return self::$tablestructure; @@ -334,10 +329,10 @@ abstract class testing_util { } if (!$structure = self::get_tablestructure()) { - return array(); + return []; } - self::$sequencenames = array(); + self::$sequencenames = []; foreach ($structure as $table => $ignored) { $name = $DB->get_manager()->generator->getSequenceFromDB(new xmldb_table($table)); if ($name !== false) { @@ -360,26 +355,25 @@ abstract class testing_util { $dbfamily = $DB->get_dbfamily(); if ($dbfamily === 'mysql') { - $empties = array(); + $empties = []; $prefix = $DB->get_prefix(); - $rs = $DB->get_recordset_sql("SHOW TABLE STATUS LIKE ?", array($prefix.'%')); + $rs = $DB->get_recordset_sql("SHOW TABLE STATUS LIKE ?", [$prefix . '%']); foreach ($rs as $info) { $table = strtolower($info->name); if (strpos($table, $prefix) !== 0) { - // incorrect table match caused by _ + // Incorrect table match caused by _. continue; } if (!is_null($info->auto_increment) && $info->rows == 0 && ($info->auto_increment == 1)) { - $table = preg_replace('/^'.preg_quote($prefix, '/').'/', '', $table); + $table = preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $table); $empties[$table] = $table; } } $rs->close(); return $empties; - } else if ($dbfamily === 'mssql') { - $empties = array(); + $empties = []; $prefix = $DB->get_prefix(); $sql = "SELECT t.name FROM sys.identity_columns i @@ -387,25 +381,24 @@ abstract class testing_util { WHERE t.name LIKE ? AND i.name = 'id' AND i.last_value IS NULL"; - $rs = $DB->get_recordset_sql($sql, array($prefix.'%')); + $rs = $DB->get_recordset_sql($sql, [$prefix . '%']); foreach ($rs as $info) { $table = strtolower($info->name); if (strpos($table, $prefix) !== 0) { - // incorrect table match caused by _ + // Incorrect table match caused by _. continue; } - $table = preg_replace('/^'.preg_quote($prefix, '/').'/', '', $table); + $table = preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $table); $empties[$table] = $table; } $rs->close(); return $empties; - } else if ($dbfamily === 'oracle') { $sequences = self::get_sequencenames(); $sequences = array_map('strtoupper', $sequences); $lookup = array_flip($sequences); - $empties = array(); - list($seqs, $params) = $DB->get_in_or_equal($sequences); + $empties = []; + [$seqs, $params] = $DB->get_in_or_equal($sequences); $sql = "SELECT sequence_name FROM user_sequences WHERE last_number = 1 AND sequence_name $seqs"; $rs = $DB->get_recordset_sql($sql, $params); foreach ($rs as $seq) { @@ -414,9 +407,8 @@ abstract class testing_util { } $rs->close(); return $empties; - } else { - return array(); + return []; } } @@ -475,7 +467,7 @@ abstract class testing_util { // To reduce the chance of the coding error, we start sequences at different values where possible. // In a attempt to avoid tables with existing id's we start at a high number. // Reset the value each time all database sequences are reset. - if (defined('PHPUNIT_SEQUENCE_START') and PHPUNIT_SEQUENCE_START) { + if (defined('PHPUNIT_SEQUENCE_START') && PHPUNIT_SEQUENCE_START) { self::$sequencenextstartingid = PHPUNIT_SEQUENCE_START; } else { self::$sequencenextstartingid = 100000; @@ -483,14 +475,14 @@ abstract class testing_util { $dbfamily = $DB->get_dbfamily(); if ($dbfamily === 'postgres') { - $queries = array(); + $queries = []; $prefix = $DB->get_prefix(); foreach ($data as $table => $records) { // If table is not modified then no need to do anything. if (!isset($updatedtables[$table])) { continue; } - if (isset($structure[$table]['id']) and $structure[$table]['id']->auto_increment) { + if (isset($structure[$table]['id']) && $structure[$table]['id']->auto_increment) { $nextid = self::get_next_sequence_starting_value($records, $table); $queries[] = "ALTER SEQUENCE {$prefix}{$table}_id_seq RESTART WITH $nextid"; } @@ -498,20 +490,19 @@ abstract class testing_util { if ($queries) { $DB->change_database_structure(implode(';', $queries)); } - } else if ($dbfamily === 'mysql') { - $queries = array(); - $sequences = array(); + $queries = []; + $sequences = []; $prefix = $DB->get_prefix(); - $rs = $DB->get_recordset_sql("SHOW TABLE STATUS LIKE ?", array($prefix.'%')); + $rs = $DB->get_recordset_sql("SHOW TABLE STATUS LIKE ?", [$prefix . '%']); foreach ($rs as $info) { $table = strtolower($info->name); if (strpos($table, $prefix) !== 0) { - // incorrect table match caused by _ + // Incorrect table match caused by _. continue; } if (!is_null($info->auto_increment)) { - $table = preg_replace('/^'.preg_quote($prefix, '/').'/', '', $table); + $table = preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $table); $sequences[$table] = $info->auto_increment; } } @@ -522,14 +513,14 @@ abstract class testing_util { if (!isset($updatedtables[$table])) { continue; } - if (isset($structure[$table]['id']) and $structure[$table]['id']->auto_increment) { + if (isset($structure[$table]['id']) && $structure[$table]['id']->auto_increment) { if (isset($sequences[$table])) { $nextid = self::get_next_sequence_starting_value($records, $table); if ($sequences[$table] != $nextid) { $queries[] = "ALTER TABLE {$prefix}{$table} AUTO_INCREMENT = $nextid"; } } else { - // some problem exists, fallback to standard code + // Some problem exists, fallback to standard code. $DB->get_manager()->reset_sequence($table); } } @@ -537,14 +528,13 @@ abstract class testing_util { if ($queries) { $DB->change_database_structure(implode(';', $queries)); } - } else if ($dbfamily === 'oracle') { $sequences = self::get_sequencenames(); $sequences = array_map('strtoupper', $sequences); $lookup = array_flip($sequences); - $current = array(); - list($seqs, $params) = $DB->get_in_or_equal($sequences); + $current = []; + [$seqs, $params] = $DB->get_in_or_equal($sequences); $sql = "SELECT sequence_name, last_number FROM user_sequences WHERE sequence_name $seqs"; $rs = $DB->get_recordset_sql($sql, $params); foreach ($rs as $seq) { @@ -558,7 +548,7 @@ abstract class testing_util { if (!isset($updatedtables[$table])) { continue; } - if (isset($structure[$table]['id']) and $structure[$table]['id']->auto_increment) { + if (isset($structure[$table]['id']) ** $structure[$table]['id']->auto_increment) { $lastrecord = end($records); if ($lastrecord) { $nextid = $lastrecord->id + 1; @@ -570,26 +560,28 @@ abstract class testing_util { } else if ($nextid == $current[$table]) { continue; } - // reset as fast as possible - alternatively we could use http://stackoverflow.com/questions/51470/how-do-i-reset-a-sequence-in-oracle + // Reset as fast as possible. + // Alternatively we could use http://stackoverflow.com/questions/51470/how-do-i-reset-a-sequence-in-oracle. $seqname = $sequences[$table]; $cachesize = $DB->get_manager()->generator->sequence_cache_size; $DB->change_database_structure("DROP SEQUENCE $seqname"); - $DB->change_database_structure("CREATE SEQUENCE $seqname START WITH $nextid INCREMENT BY 1 NOMAXVALUE CACHE $cachesize"); + $DB->change_database_structure( + "CREATE SEQUENCE $seqname START WITH $nextid INCREMENT BY 1 NOMAXVALUE CACHE $cachesize", + ); } } - } else { - // note: does mssql support any kind of faster reset? + // Note: does mssql support any kind of faster reset? // This also implies mssql will not use unique sequence values. - if (is_null($empties) and (empty($updatedtables))) { + if (is_null($empties) && (empty($updatedtables))) { $empties = self::guess_unmodified_empty_tables(); } foreach ($data as $table => $records) { // If table is not modified then no need to do anything. - if (isset($empties[$table]) or (!isset($updatedtables[$table]))) { + if (isset($empties[$table]) || (!isset($updatedtables[$table]))) { continue; } - if (isset($structure[$table]['id']) and $structure[$table]['id']->auto_increment) { + if (isset($structure[$table]['id']) && $structure[$table]['id']->auto_increment) { $DB->get_manager()->reset_sequence($table); } } @@ -605,21 +597,21 @@ abstract class testing_util { global $DB; $tables = $DB->get_tables(false); - if (!$tables or empty($tables['config'])) { - // not installed yet + if (!$tables || empty($tables['config'])) { + // Not installed yet. return false; } if (!$data = self::get_tabledata()) { - // not initialised yet + // Not initialised yet. return false; } if (!$structure = self::get_tablestructure()) { - // not initialised yet + // Not initialised yet. return false; } - $empties = array(); + $empties = []; // Use local copy of self::$tableupdated, as list gets updated in for loop. $updatedtables = self::$tableupdated; @@ -643,17 +635,16 @@ abstract class testing_util { $borkedmysql = false; if ($DB->get_dbfamily() === 'mysql') { $version = $DB->get_server_info(); - if (version_compare($version['version'], '5.6.0') == 1 and version_compare($version['version'], '5.6.16') == -1) { + if (version_compare($version['version'], '5.6.0') == 1 && version_compare($version['version'], '5.6.16') == -1) { // Everything that comes from Oracle is evil! // // See http://dev.mysql.com/doc/refman/5.6/en/alter-table.html // You cannot reset the counter to a value less than or equal to to the value that is currently in use. // // From 5.6.16 release notes: - // InnoDB: The ALTER TABLE INPLACE algorithm would fail to decrease the auto-increment value. - // (Bug #17250787, Bug #69882) + // InnoDB: The ALTER TABLE INPLACE algorithm would fail to decrease the auto-increment value. + // (Bug #17250787, Bug #69882). $borkedmysql = true; - } else if (version_compare($version['version'], '10.0.0') == 1) { // And MariaDB is no better! // Let's hope they pick the patch sometime later... @@ -662,9 +653,9 @@ abstract class testing_util { } if ($borkedmysql) { - $mysqlsequences = array(); + $mysqlsequences = []; $prefix = $DB->get_prefix(); - $rs = $DB->get_recordset_sql("SHOW TABLE STATUS LIKE ?", array($prefix.'%')); + $rs = $DB->get_recordset_sql("SHOW TABLE STATUS LIKE ?", [$prefix . '%']); foreach ($rs as $info) { $table = strtolower($info->name); if (strpos($table, $prefix) !== 0) { @@ -672,7 +663,7 @@ abstract class testing_util { continue; } if (!is_null($info->auto_increment)) { - $table = preg_replace('/^'.preg_quote($prefix, '/').'/', '', $table); + $table = preg_replace('/^' . preg_quote($prefix, '/') . '/', '', $table); $mysqlsequences[$table] = $info->auto_increment; } } @@ -695,10 +686,10 @@ abstract class testing_util { continue; } - if (isset($structure[$table]['id']) and $structure[$table]['id']->auto_increment) { - $current = $DB->get_records($table, array(), 'id ASC'); + if (isset($structure[$table]['id']) && $structure[$table]['id']->auto_increment) { + $current = $DB->get_records($table, [], 'id ASC'); if ($current == $records) { - if (isset($mysqlsequences[$table]) and $mysqlsequences[$table] == $structure[$table]['id']->auto_increment) { + if (isset($mysqlsequences[$table]) && $mysqlsequences[$table] == $structure[$table]['id']->auto_increment) { continue; } } @@ -715,13 +706,13 @@ abstract class testing_util { if (empty($records)) { if (!isset($empties[$table])) { // Table has been modified and is not empty. - $DB->delete_records($table, array()); + $DB->delete_records($table, []); } continue; } - if (isset($structure[$table]['id']) and $structure[$table]['id']->auto_increment) { - $currentrecords = $DB->get_records($table, array(), 'id ASC'); + if (isset($structure[$table]['id']) && $structure[$table]['id']->auto_increment) { + $currentrecords = $DB->get_records($table, [], 'id ASC'); $changed = false; foreach ($records as $id => $record) { if (!isset($currentrecords[$id])) { @@ -737,7 +728,7 @@ abstract class testing_util { if (!$changed) { if ($currentrecords) { $lastrecord = end($records); - $DB->delete_records_select($table, "id > ?", array($lastrecord->id)); + $DB->delete_records_select($table, "id > ?", [$lastrecord->id]); continue; } else { continue; @@ -745,16 +736,16 @@ abstract class testing_util { } } - $DB->delete_records($table, array()); + $DB->delete_records($table, []); foreach ($records as $record) { $DB->import_record($table, $record, false, true); } } - // reset all next record ids - aka sequences + // Reset all next record ids - aka sequences. self::reset_all_database_sequences($empties); - // remove extra tables + // Remove extra tables. foreach ($tables as $table) { if (!isset($data[$table])) { $DB->get_manager()->drop_table(new xmldb_table($table)); @@ -788,10 +779,10 @@ abstract class testing_util { if (in_array($item, $childclassname::$datarootskiponreset)) { continue; } - if (is_dir(self::get_dataroot()."/$item")) { - remove_dir(self::get_dataroot()."/$item", false); + if (is_dir(self::get_dataroot() . "/$item")) { + remove_dir(self::get_dataroot() . "/$item", false); } else { - unlink(self::get_dataroot()."/$item"); + unlink(self::get_dataroot() . "/$item"); } } closedir($handle); @@ -803,10 +794,10 @@ abstract class testing_util { if (in_array('filedir' . DIRECTORY_SEPARATOR . $item, $childclassname::$datarootskiponreset)) { continue; } - if (is_dir(self::get_dataroot()."/filedir/$item")) { - remove_dir(self::get_dataroot()."/filedir/$item", false); + if (is_dir(self::get_dataroot() . "/filedir/$item")) { + remove_dir(self::get_dataroot() . "/filedir/$item", false); } else { - unlink(self::get_dataroot()."/filedir/$item"); + unlink(self::get_dataroot() . "/filedir/$item"); } } closedir($handle); @@ -838,15 +829,15 @@ abstract class testing_util { // All developers have to understand English, do not localise! $env = self::get_environment(); - $output .= "Moodle ".$env['moodleversion']; + $output .= "Moodle " . $env['moodleversion']; if ($hash = self::get_git_hash()) { $output .= ", $hash"; } $output .= "\n"; // Add php version. - require_once($CFG->libdir.'/environmentlib.php'); - $output .= "Php: ". normalize_version($env['phpversion']); + require_once($CFG->libdir . '/environmentlib.php'); + $output .= "Php: " . normalize_version($env['phpversion']); // Add database type and version. $output .= ", " . $env['dbtype'] . ": " . $env['dbversion']; @@ -939,7 +930,7 @@ abstract class testing_util { * Reset updated table list. This should be done after every reset. */ public static function reset_updated_table_list() { - self::$tableupdated = array(); + self::$tableupdated = []; } /** @@ -960,7 +951,7 @@ abstract class testing_util { * Returns the path to the file which holds list of tables updated in scenario. * @return string */ - protected final static function get_tables_updated_by_scenario_list_path() { + final protected static function get_tables_updated_by_scenario_list_path() { return self::get_dataroot() . '/tablesupdatedbyscenario.json'; } @@ -974,7 +965,7 @@ abstract class testing_util { $tables = $DB->get_tables(false); if (isset($tables['config'])) { - // config always last to prevent problems with interrupted drops! + // Config always last to prevent problems with interrupted drops! unset($tables['config']); $tables['config'] = 'config'; } @@ -1044,7 +1035,6 @@ abstract class testing_util { protected static function skip_original_data_files($utilclassname) { $jsonfilepath = self::get_dataroot() . '/' . self::$originaldatafilesjson; if (file_exists($jsonfilepath)) { - $listfiles = file_get_contents($jsonfilepath); // Mark each files as to not be reset. @@ -1052,8 +1042,10 @@ abstract class testing_util { $originaldatarootfiles = json_decode($listfiles); // Keep the json file. Only drop_dataroot() should delete it. $originaldatarootfiles[] = self::$originaldatafilesjson; - $utilclassname::$datarootskiponreset = array_merge($utilclassname::$datarootskiponreset, - $originaldatarootfiles); + $utilclassname::$datarootskiponreset = array_merge( + $utilclassname::$datarootskiponreset, + $originaldatarootfiles + ); self::$originaldatafilesjsonadded = true; } } @@ -1069,8 +1061,7 @@ abstract class testing_util { // Save the original dataroot files if not done (only executed the first time). if (!file_exists($jsonfilepath)) { - - $listfiles = array(); + $listfiles = []; $currentdir = 'filedir' . DIRECTORY_SEPARATOR . '.'; $parentdir = 'filedir' . DIRECTORY_SEPARATOR . '..'; $listfiles[$currentdir] = $currentdir; @@ -1110,7 +1101,7 @@ abstract class testing_util { public static function get_environment() { global $CFG, $DB; - $env = array(); + $env = []; // Add moodle version. $release = null;