Problem/Motivation
PHP default assertion handling has been changed in 7. The time has arrived to move to a PHP 7 conformant setup.
Proposed resolution
First we must remove calls to the assert_options() function. This allows for runtime manipulation of assertion activity, and we have unit tests that manipulate it as well as the PHP 5/7 compat shim in the Assertion\Handle library. These need to go. Relevant from the PHP docs:
While assert_options() can still be used to control behaviour as described above for backward compatibility reasons, PHP 7 only code should use the two new configuration directives to control the behaviour of assert() and not call assert_options().
I read this with a strong possibility that assert_options() might find itself deprecated and removed at some point in the future.
Since the .htaccess file does not affect the PHPUnit tests ran from the command line it becomes incumbent on the environment files to set this functionality up correctly. References to assertions will be removed from .htaccess as they set up a false expectation that this file alone can control them.
assert.exception
This flag determines whether exceptions are thrown on assert failure (1) or if a warning is emitted (0). The default is 0, errors, and this is the PHP 5 compatible behavior. The PHP default is 0, and Drupal should have this setting set to 1.
zend.assertions
There are three possible values as detailed in the PHP docs. They are:
- 1: generate and execute code (development mode)
- 0: generate code but jump around it at runtime
- -1: do not generate code (production mode)
1 is the default. 0 is an emulation of PHP 5 behavior for backwards compatibility and shouldn't be considered as a possible candidate. -1 should be the production default.
Performance Concerns
Since PHP ships with assertions on by default leaving it to the site admins to turn them off will incur a performance hit for those who fail to do so. If we are to follow the PHP Group recommendation though we have no choice. Also, there are advantages to this approach - we can run the tests with runtime assertions turned on or off at our leisure so long as all unit tests which check to see if an assertion was tripped are skipped when assertions are turned off.
Whither PHP 5?
Once the parent ticket to this one is implemented PHP 5 will always run assertion related code, it just won't check to see if the return was true or false. So if there's a site breaking bug in that code under PHP 5 it will be found when the test fails to run because of the bug. In effect we are taking advantage of PHP 5's bad design of running assertions at all times.
Remaining tasks
Resolve: #2934701: Improve assertion test failures with bad zend.assertions value
None for this ticket. There is a child issue ticket for the status report change.
User interface changes
The status report will include zend.assertions current setting and mark it as a potential problem if it isn't the production value of -1.
API changes
None.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #49 | 2916440-nr-bot.txt | 146 bytes | needs-review-queue-bot |
| #36 | interdiff-2916440-33-35.txt | 634 bytes | wengerk |
| #36 | 2916440-35.patch | 11.3 KB | wengerk |
| #25 | 2916440-25.patch | 11.01 KB | neclimdul |
| #17 | 2916440-17.interdiff.txt | 1.11 KB | neclimdul |
Comments
Comment #2
Aki Tendo commentedI have adjusted the summary to account for PHPUnit's command line behavior. It isn't going to be possible to rely on .htaccess to force assert.exceptions to be set - it will be incumbent on the server settings.
Comment #3
Aki Tendo commentedI have a working patch. There are still 2 assert_option() calls to set assert.exception to 1, otherwise all assertion related unit tests will fail. These lines appear in PHPUnit's bootstrap.php and the Simpletest TestBase class. They are marked for removal as soon as the test runners have had their settings updated as called for in a child ticket. This patch doesn't contain the status report modification - It's already getting big and I think it would be best to do the status report change in a child issue.
I've also updated the issue summary to more accurately describe what is in the patch.
Comment #4
Aki Tendo commentedPHP 5 breaks are arising out of my emergency ASSERT_EXCEPTION constant shim. Once the unit testers are updated with assert.exception set to 1 I'll be able to reroll the patch with those two lines removed and get a clean PHP 5 run.
Comment #5
Aki Tendo commentedComment #6
Aki Tendo commentedPHP 5.6 and 7.0 are running clean. Also had to change all zend_assertions references to zend.assertions. PHP and consistency...
This patch still needs the test runners to be updated to set assert.exception to 1 on their own - then I can drop the lines that are currently doing this.
Comment #7
drummComment #8
wim leersSupernit: s/. A/s. A/
Nit: s/settings local.php/settings.local.php/
Nit: Missing trailing period.
This definitely means that all core & contrib tests in PHP 5 would have to stop. For example
\Drupal\Tests\Core\Cache\Context\CacheContextsManagerTest::testInvalidContext()in core and\Drupal\Tests\cdn\Unit\CdnSettingsTest::testSimpleMappingWithConditionsAndNegatedConditions()in contrib use this class to ensure things work as expected in PHP 5.Unless of course we do this in all those tests…
The sole purpose of this test is to assert a failing
assert().Doesn't PHPUnit have a way to express this dependency, so we don't need to change the test logic of all these unit tests?
Comment #9
Aki Tendo commentedI have added the following issue to the PHPUnit github as there's no way I know at present to handle test skipping when assertions are off, but there needs to be:
https://github.com/sebastianbergmann/phpunit/issues/2846
The recommendation I put forward would allow us to use an annotation of
If accepted we may have other use cases involving other PHP settings.
I'll get a patch reroll addressing the nits later today :)
Comment #10
Aki Tendo commentedWith the parent being committed this issue comes to the front.
Question: Should I split the documentation part of this ticket off to another so that it can be folded in? Reason - Until this ticket is added the API documentation regarding runtime assertions is now slightly wrong.
This ticket also needs the test runners to be updated so that the patch can have the two stopgap assert_option() calls removed that are setting assert.exception to 1.
Comment #11
Aki Tendo commentedBump. While not as urgent as some tickets, until this is applied the documentation on runtime assertions in Drupal will be incorrect.
Comment #12
Aki Tendo commentedComment #13
Aki Tendo commentedMoving to critical as @neclimdul has encountered bugs arising from unit tests failing when zend.assertion is set to -1 and then they run anyway. The patch he composed addresses the same tests as this one (I think, I didn't do an exhaustive search, but there are at least 3 matches), a duplication of effort. This patch needs to be applied to prevent further duplication of effort and confusion.
EDIT: Also, for this patch to enter final phase the test runners must be set to assert.exception 1. Again, there is no existing test this will break as the current code base sets that value on its own using assert_options()
Comment #15
neclimdulQuick clean re-roll. Going to follow up with a couple of the cleanups Wim suggested. Then an additional patch on top of #2934701: Improve assertion test failures with bad zend.assertions value to see if it makes this patch more straightforward. (Hopefully at least partially addressing 8.4 and 8.5)
Comment #16
neclimdulgah, sorry. forgot to actually attach them.
Comment #17
neclimdulWith 8.1 8.2 and 8.3 addressed. Letting tests run for giggles since there where previous conflicts.
Comment #18
neclimdulAnd combined with #2934701: Improve assertion test failures with bad zend.assertions value. diff versus other issue, and full patch.
Comment #19
Aki Tendo commentedThis needs to be > 0 like all the others I think.
Otherwise this looks good to me.
As I mentioned in chat, I'm going to work on implementing annotation logic in PHPUnit, and that syntax should be our long term goal - but this is great for the interim I think. The inclusion of that logic in PHPUnit has been signed off on, so I just need to get a working pull request in place.
Comment #20
Aki Tendo commentedCould someone apply this interdiff to the patch at #18. I have a full patch, but jenkin's can't apply it because I'm on a windows machine and the long file names bug is rearing it's head. My Linux laptop that I normally do work for here on is currently down.
The interdiff instructs on how to get the patch to it's final form, removing the temp lines from the patch that were necessary to get it to run prior to the config change of the test runners. MixoLogic has applied that change, so the patch should now run without any temporary lines.
Comment #21
neclimdulCan we solve the other issue first so we can consider this issue as a simplified changeset directly related to assert_options()?
Comment #22
Aki Tendo commentedWell, at the end of the day your construction is closest to how PHPUnit is going to handle this for us. This is the relevant section of the pull request that was accepted this morning.
Eventually tests will converted to have this annotation
So worrying about a conditional that we know will be pulled in a future patch after Drupal has a version of PHPUnit supporting this annotation doesn't help, and I'm sorry I brought it up.
Anyway, I can't do the re-roll because I can't get any patches done on my work machine to apply because of the Windows long filenames bug and my Linux laptop is down, So could someone else reroll the patch at #18 ignoring my comment at #19 because the PHPUnit change makes it moot. Two changes only are needed, this
and this..
The test runners have been reconfigured so these temporary lines should now be removed please.
Comment #23
neclimdulIt sounds like you're in agreement. I'm happy to do re-rolls but if we're going to fix the other issue first lets focus on that. Regardless of if we start using the annotation, the helper is good syntax. And we don't know when we'll be able to use the annotation. It could be a month, it could be(and likely will be) over a year if its phpunit 5/6 only and we have to wait for PHP 5 support ending so having our own method till then is needed.
Comment #24
Aki Tendo commentedThe documentation changes in this are needed, but otherwise agree. I'll move work on getting those changes done to a child ticket.
Comment #25
neclimdulClean patch without assert helper stuff.
Also remove the temp testbot stuff per #20
Also a small merge fix (conflicting use statements)
This should remove any connection on the assert helper and so any postponement.
Comment #26
Aki Tendo commentedThis patch doesn't include the test skip logic. Are we deferring this?
Comment #27
neclimdulI thought that's what we'd talked about. "I'll move work on getting those changes done to a child ticket."
#2934701: Improve assertion test failures with bad zend.assertions value
Comment #28
Aki Tendo commentedNo. All that was moved to the child was the documentation changes in core.api.php.
Comment #29
alexpottThis should trigger a silenced deprecation notice - or actually maybe an unsilenced one because actually we need sites to do something about it.
Is this not still true? Or actually need to be updated with what's in the issue summary?
Comment #30
alexpottI don't see how this fits the description of a critical task and the justification in #13 doesn't meet the standards laid out in https://www.drupal.org/core/issue-priority
Comment #31
Aki Tendo commentedOn point 1, that's actually a very good idea.
On point 2 - the "if you are using PHP 7.0" bit can be dropped because this ticket isn't going to be applied until PHP drops 5 support anyway. PHP ships with this set to 1, "on"; and in production it is strongly recommended that the setting be switched to -1. I didn't mention the later part because of the file this would appear in - settings.local.php is supposed to be a dev environment setup file yes?
That reaches out to the reason this needs some profiling done. There's a high chance that some users will be running their production machines with zend.assertion set to 1. That won't break anything, but it could slow it down and knowing by how much will help inform further decisions.
On priority - I pushed it up to critical at the same time I pushed it's parent to critical since at the time I thought they'd probably need to go out together. That isn't the case so the drop in priority makes sense and I just hadn't revisited it.
Comment #32
martin107 commentedComment #33
wengerkRe-rolled.
About #29 triggering a silenced deprecation notice - or actually maybe an unsilenced one. I don't know how to achieve this properly - should I use
trigger_error, any help ?Comment #34
Aki Tendo commentedThat should do the trick.
Comment #35
wengerkFollow the suggestion of #34.
Comment #36
wengerkSeems the files crash during upload ....
Comment #37
jofitzRemoved Needs Reroll tag.
Comment #39
wengerkRerun on 8.7.x & everything still works fine.
Comment #40
wengerkComment #49
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.