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;