Skip to content

Tests: Test exception type in error tests - #22799

Open
NickSdot wants to merge 59 commits into
php:masterfrom
NickSdot:test-hardening
Open

Tests: Test exception type in error tests#22799
NickSdot wants to merge 59 commits into
php:masterfrom
NickSdot:test-hardening

Conversation

@NickSdot

@NickSdot NickSdot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Test files sweep to make exception assertions more robust, and slightly unify style.

Specifically:

  • adds thrown class to all exception assertions to protected against regressions
  • further established the already recommended single exception formatting
  • normalises files to end with a single empty line

Target format:

echo $e::class, ': ', $e->getMessage(), PHP_EOL; // + variations like line(), code(), etc.

Approach:
Rewrites are handled by this deterministic helper for conservative and safe, automated replacements. All exception assertion "flavours" from php-src were extracted, and the tests where they were found promoted to source fixtures. Rules were then ran against the fixtures, the results manually reviewed, and promoted to target fixtures. All replacement rules are tested against the source and target fixtures. The actual "fixing" works as follows:

  1. Scan PHPT files for exception-message output inside catch blocks.
  2. Run the original PHPT through run-tests.php; skipped or already failing tests are not rewritten.
  3. Rewrite the PHPT to the normalised exception-output shape.
  4. Run the rewritten PHPT through run-tests.php.
  5. If output changed as expected, update the expected section from the actual run output.
  6. Run the updated PHPT once more.
  7. Keep only rewrites that pass verification.

Reviewing

This PR is large, since we probably don't want to review this line by line, some provenance was added. When I change the tool, a workflow in the tool repo can be triggered. The workflow pulls the latest master, then applies the fixers, then pushed to the PR repo. So the easiest review flow is:

  1. Review the diff fixtures in tests/Fixtures/**/ran.diff
  2. Review the workflow
  3. Ensure the workflow Tool commit in the run summary matches the reviewed fixtures commit.
  4. Ensure this PR's HEAD matches Generated head in the run summary.

However, for those that want to review line by line as I did a few times, I strongly recommend using https://diffshub.com/php/php-src/pull/22799 to avoid the unusable GitHub diffs.

Modules & Commits

Generated by Reproduce php-src PR.
Tool commit: bfc35a00c83e.

Target Commit Files
ext/bcmath 598b281 49
ext/bz2 7532499 7
ext/calendar 51e9bc6 15
ext/curl 7380675 21
ext/date ea66bd3 24
ext/dba 105bd27 6
ext/dom d4ce195 194
ext/exif 75139df 4
ext/ffi b64b396 30
ext/fileinfo cc03baa 12
ext/filter c4b6b42 13
ext/ftp 657d8b8 13
ext/gd 50f0573 39
ext/gettext 719d589 7
ext/gmp a1f5019 65
ext/hash 22df71d 19
ext/iconv 15e816e 3
ext/intl b7d4c1d 67
ext/json 07caa07 8
ext/ldap 051a572 9
ext/libxml ef79af9 5
ext/odbc 29ace78 1
ext/opcache a1f6b12 114
ext/openssl f9ee3cc 40
ext/pcntl ea60ace 14
ext/pcre 4e866b6 10
ext/pdo 63599c2 3
ext/pdo_sqlite 9ad93ea 22
ext/pgsql 3e0a627 2
ext/phar 5757974 183
ext/posix 3f53300 9
ext/random c7353aa 21
ext/readline f821cdc 2
ext/reflection 1514239 103
ext/session e5baceb 18
ext/shmop bfa5fd9 3
ext/simplexml f830da2 10
ext/snmp ecddea3 3
ext/soap 9b0961b 17
ext/sockets acf8996 31
ext/sodium af88728 10
ext/spl eb41f63 171
ext/sqlite3 cb4f311 20
ext/standard 0617f2c 511
ext/sysvmsg 2d53860 4
ext/sysvsem b79f83f 1
ext/sysvshm 251c2e4 8
ext/tidy 42d5af8 11
ext/tokenizer 872f02f 5
ext/uri 08bc1bd 111
ext/xml 9d1b286 5
ext/xmlreader 4d7bef4 24
ext/xmlwriter 4b538aa 6
ext/zend_test b3f24bb 13
ext/zip 2fb49cb 17
ext/zlib c161bf2 19
Zend 621b6d5 629
tests 432f9cd 55
sapi/cli 2e1ce2e 1

Changelog:

  • 2026-07-20: added ext/intl and ext/phar
  • 2026-07-21: target format \PHP_EOL -> PHP_EOL

PoC, marked as draft for now, and in coordination with Tim for now only applied to ext/random and ext/uri.

@NickSdot

Copy link
Copy Markdown
Contributor Author

@LamentXU123 I noticed your like and since you own ext/intl and ext/phar I applied the fixers to it and pushed two new commits. Would love your feedback!

Aside: since I didn't built with all extensions ext/intl serves as a good example for non-provable rewrites. In my run listformatter_with_parameters_error.phpt was skipped.

@thg2k

thg2k commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Is the \PHP_EOF really necessary? I think it just is silly in the tests. Just PHP_EOF should be fine.

@NickSdot

Copy link
Copy Markdown
Contributor Author

Is the \PHP_EOF really necessary? I think it just is silly in the tests. Just PHP_EOF should be fine.

Nah. Picked it out of habit. No strong opinion; can adjust to whatever we decide.

@LamentXU123

Copy link
Copy Markdown
Member

I actually think this change is trivial. I don't have strong opinions on this (I am on the fence of this huge code churn) so might need to wait for other's opinion.

@LamentXU123

Copy link
Copy Markdown
Member

nit: any reasons for targeting 8.5?

@NickSdot

Copy link
Copy Markdown
Contributor Author

I actually think this change is trivial. I don't have strong opinions on this (I am on the fence of this huge code churn) so might need to wait for other's opinion.

Sometimes not avoidable to move things forward. :) Personally, I think it adds enough value to be justified. Flipping \PHP_EOL to PHP_EOL would decrease churn by a bit. Do you also think it's silly? If yes could pull the trigger on making it PHP_EOL.

nit: any reasons for targeting 8.5?

Nope. Could be anything. Which one you want?

@LamentXU123

Copy link
Copy Markdown
Member

Nope. Could be anything. Which one you want?

Should be targeting master. (hint: convert this to draft when you are changing the base to avoid accidentally request a review from everyone)

@NickSdot

Copy link
Copy Markdown
Contributor Author

Nope. Could be anything. Which one you want?

Should be targeting master. (hint: convert this to draft when you are changing the base to avoid accidentally request a review from everyone)

Given that you mentioned code churn, I am wondering if targeting master is the right call? Like, when someone diffs 8.6 against 8.5 this would all be extra in the diff. Why not 8.5 and then upmerge to master? Madee a full run over all tests, merging it up would have only 37 merge conflicts on a total of 2424 affected files. After the upmerge a separate master targeted run would only affect 83 new files. Moderate, no?

@NickSdot

Copy link
Copy Markdown
Contributor Author

Changed to PHP_EOL; 37 files less affected; still targets PHP 8.5.

@TimWolla

Copy link
Copy Markdown
Member

I am wondering if targeting master is the right call?

Yes. This is a refactoring, which is not acceptable in released branches.


To reduce churn, can the formatter also keep the type of quotes for the colon in cases where the general format is already as expected? The changes in ext/uri provide no value to improve the strength of the actual assertion. Phrased differently: If the change to the test code does not result in a change in the EXPECT section, then drop the change to the test code.

@NickSdot

Copy link
Copy Markdown
Contributor Author

I am wondering if targeting master is the right call?

Yes. This is a refactoring, which is not acceptable in released branches.

Will target master! (surprised that this applies to tests)

To reduce churn, can the formatter also keep the type of quotes for the colon in cases where the general format is already as expected? The changes in ext/uri provide no value to improve the strength of the actual assertion. Phrased differently: If the change to the test code does not result in a change in the EXPECT section, then drop the change to the test code.

I evaluated this before. Not worth the extra complexity and inconsistency, IMO. Why: your modules are already so clean that ext/uri is in fact the clear outlier -- 73/104 files are in your ext/uri, only 31 more files that would be affected by what you propose are in all other tests (as in: all phpt, not only in the four modules committed here). Would not start to make things inconsistent or introduce extra rules for that, personally. However, if changing these 104 files (out of 2,369 total) would be an absolute dealbreaker I of course can make one manual commit to revert them. :)

Though, there are other cases like where output is fixed in try/catch that not actually throw. These are risk free to fix, I did so, and I think we should. Why: contributor comes to an existing test file to add test, copies existing test, style is wrong, you review and flag it. You wasted time, contributor wasted time. Or it's missed and merged. Both avoidable. Having one consistency sweep will decrease this "risk". Even code owners have recent PRs that do not follow the regression-safe pattern. When -- after this here would be merged -- everyone sees everywhere the exact same pattern it will naturally be be better adapted. The same would of course be possible if we would make this part of the CI; but you didn't seem very bullish on that?

Assumed we would do what you say, here some stats: 545 total files less; 243 are one lines changes, 334 out of it are <= 2 line diffs, 411 are <= 5 line diffs.

NickSdot added 27 commits August 1, 2026 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment