From afe2fcea3e7cdafeb3c895b0ec174a88a9f026d7 Mon Sep 17 00:00:00 2001 From: Rajesh Taneja Date: Fri, 18 Nov 2016 07:18:43 +0800 Subject: [PATCH] MDL-56898 behat: Try data reset if it fails because of pending process --- lib/behat/lib.php | 15 +++++++++++++++ lib/tests/behat/behat_hooks.php | 30 ++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/lib/behat/lib.php b/lib/behat/lib.php index b121e5e6346..6dd4784999d 100644 --- a/lib/behat/lib.php +++ b/lib/behat/lib.php @@ -134,6 +134,13 @@ function behat_error_handler($errno, $errstr, $errfile, $errline, $errcontext) { return true; } + // No need to report the before_scenario warning generated to clear last error. + // As error_clear_last is only available in php 7.0+, we trigger E_USER_WARNING + // to clear any last error which was generated during reset in before_scenario. + if (($errno === E_USER_WARNING) && $errstr == 'before_scenario') { + return; + } + // This error handler receives E_ALL | E_STRICT, running the behat test site the debug level is // set to DEVELOPER and will always include E_NOTICE,E_USER_NOTICE... as part of E_ALL, if the current // error_reporting() value does not include one of those levels is because it has been forced through @@ -175,6 +182,14 @@ function behat_shutdown_function() { if ($error = error_get_last()) { // Ignore E_WARNING, as they might come via ( @ )suppression and might lead to false failure. if (isset($error['type']) && !($error['type'] & E_WARNING)) { + + // No need to report the before_scenario warning generated to clear last error. + // As error_clear_last is only available in php 7.0+, we trigger E_USER_WARNING + // to clear any last error which was generated during reset in before_scenario. + if (($error['type'] & E_USER_WARNING) && $error['message'] == 'before_scenario') { + return; + } + $errors = behat_get_shutdown_process_errors(); $errors[] = $error; diff --git a/lib/tests/behat/behat_hooks.php b/lib/tests/behat/behat_hooks.php index db90140d178..adc150d3b08 100644 --- a/lib/tests/behat/behat_hooks.php +++ b/lib/tests/behat/behat_hooks.php @@ -96,6 +96,13 @@ class behat_hooks extends behat_base { */ protected static $timings = array(); + /** + * Keeps track of php error generated during reset. + * + * @var int keep track of how many php errors were generated. + */ + public static $phperrorduringresetcounter = 0; + /** * Hook to capture BeforeSuite event so as to give access to moodle codebase. * This will try and catch any exception and exists if anything fails. @@ -302,7 +309,30 @@ class behat_hooks extends behat_base { // Reset $SESSION. \core\session\manager::init_empty_session(); + // Set custom handler to try reset all data, if failed because of previous ajax. + set_error_handler( + function($errno, $errstr, $errfile, $errline) { + behat_hooks::$phperrorduringresetcounter++; + if (behat_hooks::$phperrorduringresetcounter < self::TIMEOUT) { + sleep(1); + behat_util::reset_all_data(); + } + return true; + }, -1 & ~E_NOTICE & ~E_WARNING); behat_util::reset_all_data(); + restore_error_handler(); + + // Trigger an error which will be ignored by behat_shutdown_function, this is hacky way to clear last error in php < 7.0. + if (self::$phperrorduringresetcounter > 0) { + if (function_exists('error_clear_last')) { + error_clear_last(); + } else { + trigger_error('before_scenario', E_USER_WARNING); + } + } + + // Reset the counter here, as this won't be required. + self::$phperrorduringresetcounter = 0; // Assign valid data to admin user (some generator-related code needs a valid user). $user = $DB->get_record('user', array('username' => 'admin'));