Problem/Motivation
If the test suite is run in versions of PHP 7 or above, there are some situations where exceptions happen, but they are not caught by the custom error handler set in DrupalTestCase and the exit code is 0 (success), even with clear errors.
This leads to false positives in tests.
Steps to reproduce
See successful run with clear errors: https://git.drupalcode.org/issue/scheduler-3387331/-/jobs/159694
- See the "*** Status: 0" which is debug added to the script.
- We can also see HTML thrown into the error output and the test summary full of fails and exceptions, yet the status code is still 0
To force this error, you just need to call $this->drupalLogin(FALSE);
Proposed resolution
Newer versions of PHP throw other type of errors, not just "Exception", but they are all "Throwable", so try to catch that and then default into "Exception".
try {
$this->$method();
// Finish up.
}
catch (Throwable $e) {
// PHP7+ versions
$this->exceptionHandler($e);
}
catch (Exception $e) {
// PHP5.6 version
$this->exceptionHandler($e);
}
Suggested here: https://www.php.net/manual/en/class.throwable.php#124604
We can see that if the suggestion above is put in place, the exception is now caught and the exit code and results are as excepted. See here: https://git.drupalcode.org/issue/scheduler-3387331/-/jobs/159786
Remaining tasks
MR
User interface changes
API changes
Data model changes
Release notes snippet
Issue fork drupal-3393147
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3393147-exceptions-ignored-in
changes, plain diff MR !4984
Comments
Comment #2
fjgarlin commentedComment #4
fjgarlin commentedMR is ready for review and the issue summary contains the findings and links with the fix in place too.
Comment #5
mcdruid commentedInteresting, thanks!
It probably doesn't make much difference, but it might be better to catch
Throwablefirst as we'd hope earlier versions of PHP are now in the minority?The examples given are that way around, but the MR currently adds
catch (Throwable $e)aftercatch (Exception $e).I'd probably then have a comment only in the Exception section to note that it's catering for older PHP.
These are nits though; the overall idea seems a good one.
Comment #6
fjgarlin commentedI've made the change suggested in #5.
Comment #7
poker10 commentedI think this looks good, thanks!
I have done a quick research and it seems like other frameworks used the same try-catch construction for cross-compatibility between PHP 5.6 and PHP 7. For example cakePHP (https://github.com/cakephp/cakephp/pull/11462/files).
DrupalCI is green on PHP 5.6 and I tested this also manually to see if the
catch (Throwable $e)can cause any errors on PHP 5.6 and lower (where theThrowableinterface is not defined). But it seem to work correctly.The change of order should be correct, as starting in PHP 7, the
Exceptionclass also implementsThrowable, so thecatch (Exception $e)will be only a fallback for PHP 5.6 and thus better to be a second.I am not sure if it is possible to add a test for this, because the code from
DrupalTestCase::run():is intended to catch only exceptions triggered by the testing methods itself and therefore it is not run when testing
DrupalErrorHandlerTestCase::testExceptionHandler(). So I am moving this to RTBC.Comment #9
mcdruid commentedGreat, thanks for fixing this!
Comment #10
jonathan1055 commentedThanks for fixing this. I discovered it whilst helping to implement gitlab pipelines for D7 Contrib testing. But @fjgarlin did the work to fix it.
On #3391902: [D7] Phpunit job ends green OK, hiding a fatal php error or exception I am also proposing a fix to the gitlab template to replicate the commit above, by patching the core file, see MR58 so that we get the benefit immediately, not having to wait for D7.99 to be released. It is unnerving having tests appear to pass green, when in fact they are not working at all :-)
Comment #12
poker10 commentedUpdating credits for @jonathan1055 as per #10.
Comment #13
jonathan1055 commentedThank you @poker10