/** * Prevent parallel test execution - this can not work in Mahara because we modify database and dataroot. * * Note: do not call manually! * * @internal * @static * @param string $framework Test framework can be 'phpunit' or 'behat' * @return void */ public static function acquire($framework) { global $CFG; $datarootpath = $CFG->{$framework . '_dataroot'} . '/' . $framework; $lockfile = $datarootpath . '/lock'; if (!file_exists($datarootpath)) { // Dataroot not initialised yet. return; } if (!file_exists($lockfile)) { file_put_contents($lockfile, 'This file prevents concurrent execution of Mahara ' . $framework . ' tests'); testing_fix_file_permissions($lockfile); } if (self::$lockhandles[$framework] = fopen($lockfile, 'r')) { $wouldblock = null; $locked = flock(self::$lockhandles[$framework], LOCK_EX | LOCK_NB, $wouldblock); if (!$locked) { if ($wouldblock) { echo "Waiting for other test execution to complete...\n"; } $locked = flock(self::$lockhandles[$framework], LOCK_EX); } if (!$locked) { fclose(self::$lockhandles[$framework]); self::$lockhandles[$framework] = null; } } register_shutdown_function(array('TestLock', 'release'), $framework); }
/** * Builds phpunit.xml files for all components using defaults from /phpunit.xml.dist * * @static * @return void, stops if can not write files */ public static function build_component_config_files() { global $CFG; $template = ' <testsuites> <testsuite name="@component@"> <directory suffix="_test.php">.</directory> </testsuite> </testsuites>'; // Use the upstream file as source for the distributed configurations $ftemplate = file_get_contents("{$CFG->dirroot}/phpunit.xml.dist"); $ftemplate = preg_replace('|<!--All core suites.*</testsuites>|s', '<!--@component_suite@-->', $ftemplate); // Gets all the components with tests $components = tests_finder::get_components_with_tests('phpunit'); // Create the corresponding phpunit.xml file for each component foreach ($components as $cname => $cpath) { // Calculate the component suite $ctemplate = $template; $ctemplate = str_replace('@component@', $cname, $ctemplate); // Apply it to the file template $fcontents = str_replace('<!--@component_suite@-->', $ctemplate, $ftemplate); // fix link to schema $level = substr_count(str_replace('\\', '/', $cpath), '/') - substr_count(str_replace('\\', '/', $CFG->dirroot), '/'); $fcontents = str_replace('lib/phpunit/', str_repeat('../', $level) . 'lib/phpunit/', $fcontents); // Write the file $result = false; if (is_writable($cpath)) { if ($result = (bool) file_put_contents("{$cpath}/phpunit.xml", $fcontents)) { testing_fix_file_permissions("{$cpath}/phpunit.xml"); } } // Problems writing file, throw error if (!$result) { phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGWARNING, "Can not create {$cpath}/phpunit.xml configuration file, verify dir permissions"); } } }
/** * Stores the version hash in both database and dataroot */ protected static function store_versions_hash() { global $CFG; $framework = self::get_framework(); $hash = self::get_version_hash(); // add test db flag set_config($framework . 'test', $hash); // hash all plugin versions - helps with very fast detection of db structure changes $hashfile = $CFG->dataroot . '/' . $framework . '/versionshash.txt'; file_put_contents($hashfile, $hash); testing_fix_file_permissions($hashfile); }
/** * Builds phpunit.xml files for all components using defaults from /phpunit.xml.dist * * @static * @return void, stops if can not write files */ public static function build_component_config_files() { global $CFG; $template = ' <testsuites> <testsuite name="@component@_testsuite"> <directory suffix="_test.php">.</directory> </testsuite> </testsuites>'; // Start a sequence between 100000 and 199000 to ensure each call to init produces // different ids in the database. This reduces the risk that hard coded values will // end up being placed in phpunit or behat test code. $sequencestart = 100000 + mt_rand(0, 99) * 1000; // Use the upstream file as source for the distributed configurations $ftemplate = file_get_contents("{$CFG->dirroot}/phpunit.xml.dist"); $ftemplate = preg_replace('|<!--All core suites.*</testsuites>|s', '<!--@component_suite@-->', $ftemplate); // Gets all the components with tests $components = tests_finder::get_components_with_tests('phpunit'); // Create the corresponding phpunit.xml file for each component foreach ($components as $cname => $cpath) { // Calculate the component suite $ctemplate = $template; $ctemplate = str_replace('@component@', $cname, $ctemplate); // Apply it to the file template $fcontents = str_replace('<!--@component_suite@-->', $ctemplate, $ftemplate); $fcontents = str_replace('<const name="PHPUNIT_SEQUENCE_START" value=""/>', '<const name="PHPUNIT_SEQUENCE_START" value="' . $sequencestart . '"/>', $fcontents); // fix link to schema $level = substr_count(str_replace('\\', '/', $cpath), '/') - substr_count(str_replace('\\', '/', $CFG->dirroot), '/'); $fcontents = str_replace('lib/phpunit/', str_repeat('../', $level) . 'lib/phpunit/', $fcontents); // Write the file $result = false; if (is_writable($cpath)) { if ($result = (bool) file_put_contents("{$cpath}/phpunit.xml", $fcontents)) { testing_fix_file_permissions("{$cpath}/phpunit.xml"); } } // Problems writing file, throw error if (!$result) { phpunit_bootstrap_error(PHPUNIT_EXITCODE_CONFIGWARNING, "Can not create {$cpath}/phpunit.xml configuration file, verify dir permissions"); } } }
/** * Mark empty dataroot to be used for testing. * @param string $dataroot The dataroot directory * @param string $framework The test framework * @return void */ function testing_initdataroot($dataroot, $framework) { global $CFG; $filename = $dataroot . '/' . $framework . 'testdir.txt'; umask(0); if (!file_exists($filename)) { file_put_contents($filename, 'Contents of this directory are used during tests only, do not delete this file!'); } testing_fix_file_permissions($filename); $varname = $framework . '_dataroot'; $datarootdir = $CFG->{$varname} . '/' . $framework; if (!file_exists($datarootdir)) { mkdir($datarootdir, $CFG->directorypermissions); } }
/** * Stores the status of the database * * Serializes the contents and the structure and * stores it in the test framework space in dataroot * @param string $statename name - Name of the site state. * - $filename_data.ser and * - $filename_structure.ser */ public static function store_database_state($statename = 'default') { global $DB; // Store data for all tables. $data = array(); $structure = array(); $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'); } else { // There should not be many of these. $data[$table] = $DB->get_records($table, array()); } } $data = serialize($data); $datafile = util::get_tool_dir() . DIRECTORY_SEPARATOR . $statename . '_data.ser'; file_put_contents($datafile, $data); testing_fix_file_permissions($datafile); $structure = serialize($structure); $structurefile = util::get_tool_dir() . DIRECTORY_SEPARATOR . $statename . '_structure.ser'; file_put_contents($structurefile, $structure); testing_fix_file_permissions($structurefile); }