diff --git a/admin/tool/behat/cli/run.php b/admin/tool/behat/cli/run.php index 4787e843b23..667118b28e4 100644 --- a/admin/tool/behat/cli/run.php +++ b/admin/tool/behat/cli/run.php @@ -93,11 +93,31 @@ if (!empty($options['help'])) { exit(0); } -$parallelrun = behat_config_manager::get_parallel_test_runs($options['fromrun']); +$parallelrun = behat_config_manager::get_behat_run_config_value('parallel'); -// Default torun is maximum parallel runs. -if (empty($options['torun'])) { - $options['torun'] = $parallelrun; +// Check if the options provided are valid to run behat. +if ($parallelrun === false) { + // Parallel run should not have fromrun or torun options greater than 1. + if (($options['fromrun'] > 1) || ($options['torun'] > 1)) { + echo "Test site is not initialized for parallel run." . PHP_EOL; + exit(1); + } +} else { + // Ensure fromrun is within limits of initialized test site. + if (!empty($options['fromrun']) && ($options['fromrun'] > $parallelrun)) { + echo "From run (" . $options['fromrun'] . ") is more than site with parallel runs (" . $parallelrun . ")" . PHP_EOL; + exit(1); + } + + // Default torun is maximum parallel runs and should be less than equal to parallelruns. + if (empty($options['torun'])) { + $options['torun'] = $parallelrun; + } else { + if ($options['torun'] > $parallelrun) { + echo "To run (" . $options['torun'] . ") is more than site with parallel runs (" . $parallelrun . ")" . PHP_EOL; + exit(1); + } + } } // Capture signals and ensure we clean symlinks. @@ -158,7 +178,36 @@ if ($options['feature']) { // Set of options to pass to behat. $extraoptstr = implode(' ', $extraopts); -// If empty parallelrun then just check with user if it's a run single behat test. +// If rerun is passed then ensure we just run the failed processes. +$lastfailedstatus = 0; +$lasttorun = $options['torun']; +$lastfromrun = $options['fromrun']; +if ($options['rerun']) { + // Get last combined failed status. + $lastfailedstatus = behat_config_manager::get_behat_run_config_value('lastcombinedfailedstatus'); + $lasttorun = behat_config_manager::get_behat_run_config_value('lasttorun'); + $lastfromrun = behat_config_manager::get_behat_run_config_value('lastfromrun'); + + if ($lastfailedstatus !== false) { + $extraoptstr .= ' --rerun'; + } + + // If torun is less than last torun, then just set this to min last to run and similar for fromrun. + if ($options['torun'] < $lasttorun) { + $options['torun']; + } + if ($options['fromrun'] > $lastfromrun) { + $options['fromrun']; + } + unset($options['rerun']); +} + +$cmds = array(); +$exitcodes = array(); +$status = 0; +$verbose = empty($options['verbose']) ? false : true; + +// Execute behat run commands. if (empty($parallelrun)) { $cwd = getcwd(); chdir(__DIR__); @@ -166,125 +215,100 @@ if (empty($parallelrun)) { $runtestscommand .= ' --config ' . behat_config_manager::get_behat_cli_config_filepath(); $runtestscommand .= ' ' . $extraoptstr; echo "Running single behat site:" . PHP_EOL; - passthru("php $runtestscommand", $code); + passthru("php $runtestscommand", $status); chdir($cwd); - exit($code); -} +} else { -// If rerun is passed then ensure we just run the failed processes. -$lastfailedstatus = 0; -if ($options['rerun']) { - $lastfailedstatus = get_last_failed_status($options['fromrun'], $options['torun']); - unset($options['rerun']); - $extraoptstr .= ' --rerun'; -} + echo "Running " . ($options['torun'] - $options['fromrun'] + 1) . " parallel behat sites:" . PHP_EOL; -$cmds = array(); -echo "Running " . ($options['torun'] - $options['fromrun'] + 1) . " parallel behat sites:" . PHP_EOL; + for ($i = $options['fromrun']; $i <= $options['torun']; $i++) { + $lastfailed = 1 & $lastfailedstatus >> ($i - 1); -for ($i = $options['fromrun']; $i <= $options['torun']; $i++) { - // Bypass if not failed in last run. - if ($lastfailedstatus && !($i & $lastfailedstatus)) { - continue; + // Bypass if not failed in last run. + if ($lastfailedstatus && !$lastfailed && ($i <= $lasttorun) && ($i >= $lastfromrun)) { + continue; + } + + $CFG->behatrunprocess = $i; + + // Options parameters to be added to each run. + $myopts = !empty($options['replace']) ? str_replace($options['replace'], $i, $extraoptstr) : $extraoptstr; + + $behatcommand = behat_command::get_behat_command(false, false, true); + $behatconfigpath = behat_config_manager::get_behat_cli_config_filepath($i); + + // Command to execute behat run. + $cmds[BEHAT_PARALLEL_SITE_NAME . $i] = $behatcommand . ' --config ' . $behatconfigpath . " " . $myopts; + echo "[" . BEHAT_PARALLEL_SITE_NAME . $i . "] " . $cmds[BEHAT_PARALLEL_SITE_NAME . $i] . PHP_EOL; } - $CFG->behatrunprocess = $i; - - // Options parameters to be added to each run. - $myopts = !empty($options['replace']) ? str_replace($options['replace'], $i, $extraoptstr) : $extraoptstr; - - $behatcommand = behat_command::get_behat_command(false, false, true); - $behatconfigpath = behat_config_manager::get_behat_cli_config_filepath($i); - - // Command to execute behat run. - $cmds[BEHAT_PARALLEL_SITE_NAME . $i] = $behatcommand . ' --config ' . $behatconfigpath . " " . $myopts; - echo "[" . BEHAT_PARALLEL_SITE_NAME . $i . "] " . $cmds[BEHAT_PARALLEL_SITE_NAME . $i] . PHP_EOL; - - // Remove any old last failed status files. - $filepath = behat_command::get_last_failed_test_status_file_path($options['fromrun']); - if (file_exists($filepath)) { - @unlink($filepath); + if (empty($cmds)) { + echo "No commands to execute " . PHP_EOL; + exit(1); } -} -if (empty($cmds)) { - echo "No commands to execute " . PHP_EOL; - exit(1); -} - -// Create site symlink if necessary. -if (!behat_config_manager::create_parallel_site_links($options['fromrun'], $options['torun'])) { - echo "Check permissions. If on windows, make sure you are running this command as admin" . PHP_EOL; - exit(1); -} - -// Execute all commands, relative to moodle root directory. -$processes = cli_execute_parallel($cmds, __DIR__ . "/../../../../"); -$stoponfail = empty($options['stop-on-failure']) ? false : true; - -// Print header. -print_process_start_info($processes); - -// Print combined run o/p from processes. -$exitcodes = print_combined_run_output($processes, $stoponfail); -$time = round(microtime(true) - $time, 1); -echo "Finished in " . gmdate("G\h i\m s\s", $time) . PHP_EOL . PHP_EOL; - -ksort($exitcodes); - -// Print exit info from each run. -// Status bits contains pass/fail status of parallel runs. -$status = 0; -foreach ($exitcodes as $name => $exitcode) { - if ($exitcode) { - $runno = str_replace(BEHAT_PARALLEL_SITE_NAME, '', $name); - $status |= (1 << ($runno - 1)); + // Create site symlink if necessary. + if (!behat_config_manager::create_parallel_site_links($options['fromrun'], $options['torun'])) { + echo "Check permissions. If on windows, make sure you are running this command as admin" . PHP_EOL; + exit(1); } + + // Save torun and from run, so it can be used to detect if it was executed in last run. + behat_config_manager::set_behat_run_config_value('lasttorun', $options['torun']); + behat_config_manager::set_behat_run_config_value('lastfromrun', $options['fromrun']); + + // Execute all commands, relative to moodle root directory. + $processes = cli_execute_parallel($cmds, __DIR__ . "/../../../../"); + $stoponfail = empty($options['stop-on-failure']) ? false : true; + + // Print header. + print_process_start_info($processes); + + // Print combined run o/p from processes. + $exitcodes = print_combined_run_output($processes, $stoponfail); + // Time to finish run. + $time = round(microtime(true) - $time, 1); + echo "Finished in " . gmdate("G\h i\m s\s", $time) . PHP_EOL . PHP_EOL; + ksort($exitcodes); + + // Print exit info from each run. + // Status bits contains pass/fail status of parallel runs. + foreach ($exitcodes as $name => $exitcode) { + if ($exitcode) { + $runno = str_replace(BEHAT_PARALLEL_SITE_NAME, '', $name); + $status |= (1 << ($runno - 1)); + } + } + + // Print each process information. + print_each_process_info($processes, $verbose, $status); } -// Run finished. Show exit code and output from individual process. -$verbose = empty($options['verbose']) ? false : true; - -// Show exit code from each process, if any process failed. +// Show exit code from each process, if any process failed and how to rerun failed process. if ($verbose || $status) { - // Echo exit codes. - echo "Exit codes for each behat run: " . PHP_EOL; - foreach ($exitcodes as $run => $exitcode) { - echo $run . ": " . $exitcode . PHP_EOL; - } + // Save final exit code containing which run failed. + behat_config_manager::set_behat_run_config_value('lastcombinedfailedstatus', $status); // Show failed re-run commands. if ($status) { - echo "To re-run failed processes, you can use following commands:" . PHP_EOL; - foreach ($cmds as $name => $cmd) { - if (!empty($exitcodes[$name])) { - // Show rerun command only for the failed runs. - $runno = str_replace(BEHAT_PARALLEL_SITE_NAME, '', $name); - if ((1 << ($runno - 1)) & $status) { - $extraopts['fromrun'] = '--fromrun=' . $runno; - $extraopts['torun'] = '--torun=' . $runno; - $extraopts['rerun'] = '--rerun'; - $extraoptstr = implode(' ', $extraopts); - - $myopts = !empty($options['replace']) ? str_replace($options['replace'], $runno, $extraoptstr) : $extraoptstr; - - $behatcommand = behat_command::get_behat_command(true, true, true); - echo "[" . $name . "] " . $behatcommand . ' ' . $myopts . PHP_EOL; - } - - // Save information about this failure. - $filepath = behat_command::get_last_failed_test_status_file_path($runno); - if (!file_put_contents($filepath, $status)) { - behat_error(BEHAT_EXITCODE_PERMISSIONS, 'File ' . $filepath . ' can not be created'); - } + if (!empty($cmds)) { + // Echo exit codes. + echo "Exit codes for each behat run: " . PHP_EOL; + foreach ($exitcodes as $run => $exitcode) { + echo $run . ": " . $exitcode . PHP_EOL; } } + + echo "To re-run failed processes, you can use following command:" . PHP_EOL; + unset($extraopts['fromrun']); + unset($extraopts['torun']); + $extraopts['rerun'] = '--rerun'; + $extraoptstr = implode(' ', $extraopts); + echo behat_command::get_behat_command(true, true, true) . " " . $extraoptstr . PHP_EOL; } echo PHP_EOL; } -print_each_process_info($processes, $verbose, $status); - // Remove site symlink if necessary. behat_config_manager::drop_parallel_site_links(); @@ -445,26 +469,3 @@ function get_status_lines_from_run_op(Symfony\Component\Process\Process $process return $statusstr; } -/** - * Return last failed status of parallel runs. - * - * @param int $fromrun starting run. - * @param int $torun end run. - * @return int status of last failure. - */ -function get_last_failed_status($fromrun, $torun) { - $lastfailedstatus = 0; - - for ($i = $fromrun; $i <= $torun; $i++) { - $filepath = behat_command::get_last_failed_test_status_file_path($i); - if (file_exists($filepath)) { - if ($lastfailedstatus = file_get_contents($filepath)) { - $lastfailedstatus = (int)$lastfailedstatus; - break; - } - } - } - - return $lastfailedstatus; -} - diff --git a/admin/tool/behat/cli/util.php b/admin/tool/behat/cli/util.php index b157ca7f757..8efa4ed955b 100644 --- a/admin/tool/behat/cli/util.php +++ b/admin/tool/behat/cli/util.php @@ -36,11 +36,7 @@ define('NO_OUTPUT_BUFFERING', true); define('IGNORE_COMPONENT_CACHE', true); define('ABORT_AFTER_CONFIG', true); -require_once(__DIR__ . '/../../../../config.php'); require_once(__DIR__ . '/../../../../lib/clilib.php'); -require_once(__DIR__ . '/../../../../lib/behat/lib.php'); -require_once(__DIR__ . '/../../../../lib/behat/classes/behat_command.php'); -require_once(__DIR__ . '/../../../../lib/behat/classes/behat_config_manager.php'); // CLI options. list($options, $unrecognized) = cli_get_params( @@ -103,14 +99,26 @@ if (!empty($options['help'])) { $cwd = getcwd(); +// If Behat parallel site is being initiliased, then define a param to be used to ignore single run install. +if (!empty($options['parallel'])) { + define('BEHAT_PARALLEL_UTIL', true); +} + +require_once(__DIR__ . '/../../../../config.php'); +require_once(__DIR__ . '/../../../../lib/behat/lib.php'); +require_once(__DIR__ . '/../../../../lib/behat/classes/behat_command.php'); +require_once(__DIR__ . '/../../../../lib/behat/classes/behat_config_manager.php'); + // For drop option check if parallel site. if ((empty($options['parallel'])) && ($options['drop']) || $options['updatesteps']) { - // Get parallel run info from first run. - $options['parallel'] = behat_config_manager::get_parallel_test_runs($options['fromrun']); + $options['parallel'] = behat_config_manager::get_behat_run_config_value('parallel'); } // If not a parallel site then open single run. if (empty($options['parallel'])) { + // Set run config value for single run. + behat_config_manager::set_behat_run_config_value('singlerun', 1); + chdir(__DIR__); // Check if behat is initialised, if not exit. passthru("php util_single_run.php --diag", $status); @@ -147,6 +155,21 @@ if ($options['diag'] || $options['enable'] || $options['disable']) { $status = (bool)$status || (bool)$exitcode; } + // Remove run config file. + $behatrunconfigfile = behat_config_manager::get_behat_run_config_file_path(); + if (file_exists($behatrunconfigfile)) { + if (!unlink($behatrunconfigfile)) { + behat_error(BEHAT_EXITCODE_PERMISSIONS, 'Can not delete behat run config file'); + } + } + + // Remove test file path. + if (file_exists(behat_util::get_test_file_path())) { + if (!unlink(behat_util::get_test_file_path())) { + behat_error(BEHAT_EXITCODE_PERMISSIONS, 'Can not delete test file enable info'); + } + } + } else if ($options['install']) { // This is intensive compared to behat itself so run them in chunk if option maxruns not set. if ($options['maxruns']) { @@ -233,6 +256,19 @@ if ($options['install']) { } else if ($options['enable']) { echo "Acceptance tests environment enabled on $CFG->behat_wwwroot, to run the tests use:" . PHP_EOL; echo behat_command::get_behat_command(true, true); + + // Save fromrun and to run information. + if (isset($options['fromrun'])) { + behat_config_manager::set_behat_run_config_value('fromrun', $options['fromrun']); + } + + if (isset($options['torun'])) { + behat_config_manager::set_behat_run_config_value('torun', $options['torun']); + } + if (isset($options['parallel'])) { + behat_config_manager::set_behat_run_config_value('parallel', $options['parallel']); + } + echo PHP_EOL; } else if ($options['disable']) { diff --git a/admin/tool/behat/cli/util_single_run.php b/admin/tool/behat/cli/util_single_run.php index 3d0e2db310a..2e98656a90b 100644 --- a/admin/tool/behat/cli/util_single_run.php +++ b/admin/tool/behat/cli/util_single_run.php @@ -143,7 +143,7 @@ if ($options['run']) { $run = $options['run']; // If parallel option is not passed, then try get it form config. if (!$options['parallel']) { - $parallel = behat_config_manager::get_parallel_test_runs(); + $parallel = behat_config_manager::get_behat_run_config_value('parallel'); } else { $parallel = $options['parallel']; } @@ -176,10 +176,7 @@ if ($options['install']) { } else if ($options['enable']) { if (!empty($parallel)) { // Save parallel site info for enable and install options. - $filepath = behat_config_manager::get_parallel_test_file_path(); - if (!file_put_contents($filepath, $parallel)) { - behat_error(BEHAT_EXITCODE_PERMISSIONS, 'File ' . $filepath . ' can not be created'); - } + behat_config_manager::set_behat_run_config_value('behatsiteenabled', 1); } // Enable test mode. @@ -200,7 +197,7 @@ if ($options['install']) { } } else if ($options['disable']) { - behat_util::stop_test_mode(); + behat_util::stop_test_mode($run); // This is only displayed once for parallel install. if (empty($run)) { mtrace("Acceptance tests environment disabled"); diff --git a/lib/behat/classes/behat_command.php b/lib/behat/classes/behat_command.php index a0be36a9c4b..0070634326a 100644 --- a/lib/behat/classes/behat_command.php +++ b/lib/behat/classes/behat_command.php @@ -42,6 +42,22 @@ class behat_command { */ const DOCS_URL = 'http://docs.moodle.org/dev/Acceptance_testing'; + /** + * Ensures the behat dir exists in moodledata + * + * @return string Full path + */ + public static function get_parent_behat_dir() { + global $CFG; + + // If not set then return empty string. + if (!isset($CFG->behat_dataroot_parent)) { + return ""; + } + + return $CFG->behat_dataroot_parent; + } + /** * Ensures the behat dir exists in moodledata * @param int $runprocess run process for which behat dir is returned. @@ -55,12 +71,11 @@ class behat_command { return ""; } - if (empty($runprocess)) { - $behatdir = $CFG->behat_dataroot . '/behat'; - } else if (isset($CFG->behat_parallel_run[$runprocess - 1]['behat_dataroot'])) { + // If $CFG->behat_parallel_run starts with index 0 and $runprocess for parallel run starts with 1. + if (!empty($runprocess) && isset($CFG->behat_parallel_run[$runprocess - 1]['behat_dataroot'])) { $behatdir = $CFG->behat_parallel_run[$runprocess - 1]['behat_dataroot'] . '/behat';; } else { - $behatdir = $CFG->behat_dataroot . $runprocess . '/behat'; + $behatdir = $CFG->behat_dataroot . '/behat'; } if (!is_dir($behatdir)) { @@ -218,17 +233,6 @@ class behat_command { return true; } - /** - * Returns the path to the parallel run file which specifies if parallel test environment is enabled - * and how many parallel runs to execute. - * - * @param int $runprocess run process for which behat dir is returned. - * @return string - */ - public final static function get_last_failed_test_status_file_path($runprocess = 0) { - return self::get_behat_dir($runprocess) . '/lastfailed.txt'; - } - /** * Outputs a message. * diff --git a/lib/behat/classes/behat_config_manager.php b/lib/behat/classes/behat_config_manager.php index 6b237f2a204..7285e3907c0 100644 --- a/lib/behat/classes/behat_config_manager.php +++ b/lib/behat/classes/behat_config_manager.php @@ -87,7 +87,7 @@ class behat_config_manager { // Behat must have a separate behat.yml to have access to the whole set of features and steps definitions. if ($testsrunner === true) { - $configfilepath = behat_command::get_behat_dir() . '/behat.yml'; + $configfilepath = behat_command::get_behat_dir($run) . '/behat.yml'; } else { // Alternative for steps definitions filtering, one for each user. $configfilepath = self::get_steps_list_config_filepath(); @@ -117,7 +117,7 @@ class behat_config_manager { // Get number of parallel runs if not passed. if (empty($parallelruns) && ($parallelruns !== false)) { - $parallelruns = self::get_parallel_test_runs(); + $parallelruns = self::get_behat_run_config_value('parallel'); } // Behat config file specifing the main context class, @@ -212,31 +212,49 @@ class behat_config_manager { * Returns the path to the parallel run file which specifies if parallel test environment is enabled * and how many parallel runs to execute. * - * @param int $runprocess run process for which behat dir is returned. * @return string */ - public final static function get_parallel_test_file_path($runprocess = 0) { - return behat_command::get_behat_dir($runprocess) . '/parallel_environment_enabled.txt'; + public final static function get_behat_run_config_file_path() { + return behat_command::get_parent_behat_dir() . '/run_environment.json'; } /** - * Returns number of parallel runs for which site is initialised. + * Get config for parallel run. * - * @param int $runprocess run process for which behat dir is returned. - * @return int + * @param string $key Key to store + * @return string|int|array value which is stored. */ - public final static function get_parallel_test_runs($runprocess = 0) { + public final static function get_behat_run_config_value($key) { + $parallelrunconfigfile = self::get_behat_run_config_file_path(); - $parallelrun = 0; - // Get parallel run info from first file and last file. - $parallelrunconfigfile = self::get_parallel_test_file_path($runprocess); if (file_exists($parallelrunconfigfile)) { - if ($parallel = file_get_contents($parallelrunconfigfile)) { - $parallelrun = (int) $parallel; + if ($parallelrunconfigs = @json_decode(file_get_contents($parallelrunconfigfile), true)) { + if (isset($parallelrunconfigs[$key])) { + return $parallelrunconfigs[$key]; + } } } - return $parallelrun; + return false; + } + + /** + * Save/update config for parallel run. + * + * @param string $key Key to store + * @param string|int|array $value to store. + */ + public final static function set_behat_run_config_value($key, $value) { + $parallelrunconfigs = array(); + $parallelrunconfigfile = self::get_behat_run_config_file_path(); + + // Get any existing config first. + if (file_exists($parallelrunconfigfile)) { + $parallelrunconfigs = @json_decode(file_get_contents($parallelrunconfigfile), true); + } + $parallelrunconfigs[$key] = $value; + + @file_put_contents($parallelrunconfigfile, json_encode($parallelrunconfigs, JSON_PRETTY_PRINT)); } /** @@ -247,8 +265,8 @@ class behat_config_manager { public final static function drop_parallel_site_links() { global $CFG; - // Get parallel test runs from first run. - $parallelrun = self::get_parallel_test_runs(1); + // Get parallel test runs. + $parallelrun = self::get_behat_run_config_value('parallel'); if (empty($parallelrun)) { return false; diff --git a/lib/behat/classes/behat_config_util.php b/lib/behat/classes/behat_config_util.php index 8df778ee423..1546d0b179a 100644 --- a/lib/behat/classes/behat_config_util.php +++ b/lib/behat/classes/behat_config_util.php @@ -147,7 +147,7 @@ class behat_config_util { public function get_number_of_parallel_run() { // Get number of parallel runs if not passed. if (empty($this->parallelruns) && ($this->parallelruns !== false)) { - $this->parallelruns = behat_config_manager::get_parallel_test_runs(); + $this->parallelruns = behat_config_manager::get_behat_run_config_value('parallel'); } return $this->parallelruns; diff --git a/lib/behat/classes/util.php b/lib/behat/classes/util.php index 09cf9ccd8b9..ab97abb6240 100644 --- a/lib/behat/classes/util.php +++ b/lib/behat/classes/util.php @@ -139,8 +139,23 @@ class behat_util extends testing_util { } self::reset_dataroot(); - self::drop_dataroot(); self::drop_database(true); + self::drop_dataroot(); + } + + /** + * Delete files and directories under dataroot. + */ + public static function drop_dataroot() { + global $CFG; + + // As behat directory is now created under default $CFG->behat_dataroot_parent, so remove the whole dir. + if ($CFG->behat_dataroot !== $CFG->behat_dataroot_parent) { + remove_dir($CFG->behat_dataroot, false); + } else { + // It should never come here. + throw new moodle_exception("Behat dataroot should not be same as parent behat data root."); + } } /** @@ -290,6 +305,7 @@ class behat_util extends testing_util { } $testenvfile = self::get_test_file_path(); + behat_config_manager::set_behat_run_config_value('behatsiteenabled', 0); if (!self::is_test_mode_enabled()) { echo "Test environment was already disabled\n"; @@ -322,8 +338,8 @@ class behat_util extends testing_util { * Returns the path to the file which specifies if test environment is enabled * @return string */ - protected final static function get_test_file_path() { - return behat_command::get_behat_dir() . '/test_environment_enabled.txt'; + public final static function get_test_file_path() { + return behat_command::get_parent_behat_dir() . '/test_environment_enabled.txt'; } /** diff --git a/lib/behat/lib.php b/lib/behat/lib.php index 662a784ec18..1ca3f098be2 100644 --- a/lib/behat/lib.php +++ b/lib/behat/lib.php @@ -274,6 +274,33 @@ function behat_check_config_vars() { 'Define $CFG->behat_dataroot in config.php'); } clearstatcache(); + if (!file_exists($CFG->behat_dataroot_parent)) { + $permissions = isset($CFG->directorypermissions) ? $CFG->directorypermissions : 02777; + umask(0); + if (!mkdir($CFG->behat_dataroot_parent, $permissions, true)) { + behat_error(BEHAT_EXITCODE_PERMISSIONS, '$CFG->behat_dataroot directory can not be created'); + } + } + $CFG->behat_dataroot_parent = realpath($CFG->behat_dataroot_parent); + if (empty($CFG->behat_dataroot_parent) or !is_dir($CFG->behat_dataroot_parent) or !is_writable($CFG->behat_dataroot_parent)) { + behat_error(BEHAT_EXITCODE_CONFIG, + '$CFG->behat_dataroot in config.php must point to an existing writable directory'); + } + if (!empty($CFG->dataroot) and $CFG->behat_dataroot_parent == realpath($CFG->dataroot)) { + behat_error(BEHAT_EXITCODE_CONFIG, + '$CFG->behat_dataroot in config.php must be different from $CFG->dataroot'); + } + if (!empty($CFG->phpunit_dataroot) and $CFG->behat_dataroot_parent == realpath($CFG->phpunit_dataroot)) { + behat_error(BEHAT_EXITCODE_CONFIG, + '$CFG->behat_dataroot in config.php must be different from $CFG->phpunit_dataroot'); + } + + // This request is coming from admin/tool/behat/cli/util.php which will call util_single.php. So just return from + // here as we don't need to create a dataroot for single run. + if (defined('BEHAT_PARALLEL_UTIL') && BEHAT_PARALLEL_UTIL && empty($CFG->behatrunprocess)) { + return; + } + if (!file_exists($CFG->behat_dataroot)) { $permissions = isset($CFG->directorypermissions) ? $CFG->directorypermissions : 02777; umask(0); @@ -282,18 +309,6 @@ function behat_check_config_vars() { } } $CFG->behat_dataroot = realpath($CFG->behat_dataroot); - if (empty($CFG->behat_dataroot) or !is_dir($CFG->behat_dataroot) or !is_writable($CFG->behat_dataroot)) { - behat_error(BEHAT_EXITCODE_CONFIG, - '$CFG->behat_dataroot in config.php must point to an existing writable directory'); - } - if (!empty($CFG->dataroot) and $CFG->behat_dataroot == realpath($CFG->dataroot)) { - behat_error(BEHAT_EXITCODE_CONFIG, - '$CFG->behat_dataroot in config.php must be different from $CFG->dataroot'); - } - if (!empty($CFG->phpunit_dataroot) and $CFG->behat_dataroot == realpath($CFG->phpunit_dataroot)) { - behat_error(BEHAT_EXITCODE_CONFIG, - '$CFG->behat_dataroot in config.php must be different from $CFG->phpunit_dataroot'); - } } /** @@ -336,6 +351,10 @@ function behat_update_vars_for_process() { $behatrunprocess = behat_get_run_process(); $CFG->behatrunprocess = $behatrunprocess; + // Data directory will be a directory under parent directory. + $CFG->behat_dataroot_parent = $CFG->behat_dataroot; + $CFG->behat_dataroot .= '/'. BEHAT_PARALLEL_SITE_NAME; + if ($behatrunprocess) { if (empty($CFG->behat_parallel_run[$behatrunprocess - 1]['behat_wwwroot'])) { // Set www root for run process. @@ -459,7 +478,7 @@ function behat_get_run_process() { } // Check if default behat datroot increment was done. if (empty($behatrunprocess)) { - $behatdataroot = str_replace("\\", "/", $CFG->behat_dataroot); + $behatdataroot = str_replace("\\", "/", $CFG->behat_dataroot . '/' . BEHAT_PARALLEL_SITE_NAME); $behatrunprocess = preg_filter("#^{$behatdataroot}" . "(.+?)[/|\\\]behat[/|\\\]behat\.yml#", '$1', $behatconfig); } diff --git a/lib/phpunit/classes/util.php b/lib/phpunit/classes/util.php index 6152374cb85..f390f14f07f 100644 --- a/lib/phpunit/classes/util.php +++ b/lib/phpunit/classes/util.php @@ -412,10 +412,12 @@ class phpunit_util extends testing_util { self::reset_dataroot(); testing_initdataroot($CFG->dataroot, 'phpunit'); - self::drop_dataroot(); - // drop all tables + // Drop all tables. self::drop_database($displayprogress); + + // Drop dataroot. + self::drop_dataroot(); } /** diff --git a/lib/setup.php b/lib/setup.php index fb16784eccd..0f71dc6fabe 100644 --- a/lib/setup.php +++ b/lib/setup.php @@ -84,7 +84,8 @@ if (defined('BEHAT_SITE_RUNNING')) { // Update config variables for parallel behat runs. behat_update_vars_for_process(); - if (behat_is_test_site()) { + // If behat is being installed for parallel run, then we modify params for parallel run only. + if (behat_is_test_site() && !(defined('BEHAT_PARALLEL_UTIL') && empty($CFG->behatrunprocess))) { clearstatcache(); // Checking the integrity of the provided $CFG->behat_* vars and the @@ -116,7 +117,8 @@ if (defined('BEHAT_SITE_RUNNING')) { if (!defined('BEHAT_UTIL') and !defined('BEHAT_TEST')) { // Somebody tries to access test site directly, tell them if not enabled. - if (!file_exists($CFG->behat_dataroot . '/behat/test_environment_enabled.txt')) { + $behatdir = preg_replace("#[/|\\\]" . BEHAT_PARALLEL_SITE_NAME . "\d{0,}$#", '', $CFG->behat_dataroot); + if (!file_exists($behatdir . '/test_environment_enabled.txt')) { behat_error(BEHAT_EXITCODE_CONFIG, 'Behat is configured but not enabled on this test site.'); } }