mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
Merge branch 'MDL-79637-master' of https://github.com/andrewnicols/moodle
This commit is contained in:
commit
73267a7848
@ -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,22 +216,36 @@ 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;
|
||||
|
||||
// load test case stub classes and other stuff
|
||||
(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");
|
||||
|
||||
// finish moodle init
|
||||
// Finish moodle init.
|
||||
define('ABORT_AFTER_CONFIG_CANCEL', true);
|
||||
if (isset($CFG->phpunit_profilingenabled) && $CFG->phpunit_profilingenabled) {
|
||||
$CFG->profilingenabled = true;
|
||||
@ -219,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;
|
||||
}
|
||||
|
||||
@ -227,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();
|
||||
|
@ -14,16 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* 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,57 +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);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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) {
|
||||
@ -110,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;
|
||||
}
|
||||
|
||||
@ -123,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);
|
||||
@ -149,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');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -252,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;
|
||||
}
|
||||
@ -295,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);
|
||||
@ -308,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);
|
||||
}
|
||||
@ -333,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);
|
||||
@ -355,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);
|
||||
@ -454,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);
|
||||
}
|
||||
|
||||
@ -548,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);
|
||||
@ -619,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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -656,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)) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
@ -650,13 +642,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])) {
|
||||
@ -672,7 +664,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;
|
||||
@ -680,16 +672,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));
|
||||
@ -723,10 +715,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);
|
||||
@ -738,10 +730,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);
|
||||
@ -773,15 +765,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'];
|
||||
@ -874,7 +866,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 = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@ -895,7 +887,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';
|
||||
}
|
||||
|
||||
@ -909,7 +901,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';
|
||||
}
|
||||
@ -979,7 +971,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.
|
||||
@ -987,8 +978,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;
|
||||
}
|
||||
}
|
||||
@ -1004,8 +997,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;
|
||||
@ -1045,7 +1037,7 @@ abstract class testing_util {
|
||||
public static function get_environment() {
|
||||
global $CFG, $DB;
|
||||
|
||||
$env = array();
|
||||
$env = [];
|
||||
|
||||
// Add moodle version.
|
||||
$release = null;
|
||||
|
Loading…
x
Reference in New Issue
Block a user