test: cover the infrastructure branches nothing reached - #859
Merged
blaipr merged 1 commit intoAug 23, 2026
Conversation
Error paths and secondary branches in four widely-used infrastructure classes, none of
which had a test: the router's error handling, Util's reflection helpers, the two
constants Functions.php computes at load time, and Crypt's ASCII key branch.
Router: the routing-miss catch is asserted to be distinct from the generic Throwable
catch (an onError spy that stays uncalled), that a responder exception reaches a
registered error handler with the router, message, class and throwable, and that it is
rethrown when none is registered.
Functions.php: MODULES_PATH and LOG_FILE are computed from APP_PATH at load time, and
the suite's own bootstrap has already required the file before any test runs — so the
constants cannot be recomputed in-process and the file cannot be re-required (that
fatals on the function redeclarations). Each test spawns a child with a fresh APP_ROOT
and asserts the exact computed value, which is also how initModule()'s non-array return
is covered.
Two branches are left uncovered deliberately, both established by measurement rather
than assumed:
- Version::checkVersion()'s 32-bit arm, behind `PHP_INT_SIZE > 4`. PHP_INT_SIZE is 8 on
every 64-bit build, so the branch is unreachable here; covering it would mean running
the suite on a 32-bit PHP.
- Crypt::makeSecuredKey()'s catch. No password content reaches it — empty, embedded NUL,
five megabytes, invalid UTF-8 were all tried — because the password is reduced to a
fixed-length digest before it meets the library's primitives. Only a broken runtime
(no openssl, exhausted CSPRNG) throws there.
- Functions.php's `if (!defined('MODULES_PATH'))` guard in initModule() is dead: the
constant is defined unconditionally as the first executable line of the same file.
The ASCII arm of Crypt::unlockSecuredKey() is covered through reflection because both
of its callers hard-code the other value. That is worth knowing rather than hiding: it
is currently dead in the call graph, and the test pins what it returns if a caller ever
uses it — the returned text is itself a usable key.
blaipr
deleted the
test/cover-the-infrastructure-branches-nothing-reached
branch
August 23, 2026 22:01
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Error paths and secondary branches in four widely-used infrastructure classes, none of
which had a test: the router's error handling, Util's reflection helpers, the two
constants Functions.php computes at load time, and Crypt's ASCII key branch.
Router: the routing-miss catch is asserted to be distinct from the generic Throwable
catch (an onError spy that stays uncalled), that a responder exception reaches a
registered error handler with the router, message, class and throwable, and that it is
rethrown when none is registered.
Functions.php: MODULES_PATH and LOG_FILE are computed from APP_PATH at load time, and
the suite's own bootstrap has already required the file before any test runs — so the
constants cannot be recomputed in-process and the file cannot be re-required (that
fatals on the function redeclarations). Each test spawns a child with a fresh APP_ROOT
and asserts the exact computed value, which is also how initModule()'s non-array return
is covered.
Two branches are left uncovered deliberately, both established by measurement rather
than assumed:
PHP_INT_SIZE > 4. PHP_INT_SIZE is 8 onevery 64-bit build, so the branch is unreachable here; covering it would mean running
the suite on a 32-bit PHP.
five megabytes, invalid UTF-8 were all tried — because the password is reduced to a
fixed-length digest before it meets the library's primitives. Only a broken runtime
(no openssl, exhausted CSPRNG) throws there.
if (!defined('MODULES_PATH'))guard in initModule() is dead: theconstant is defined unconditionally as the first executable line of the same file.
The ASCII arm of Crypt::unlockSecuredKey() is covered through reflection because both
of its callers hard-code the other value. That is worth knowing rather than hiding: it
is currently dead in the call graph, and the test pins what it returns if a caller ever
uses it — the returned text is itself a usable key.