Repository navigation
test(session): count only sessions that garbage collection cannot remove - #34
Merged
Merged
Conversation
FpmSessionTest::testStatelessRoutesNeverTouchTheSession failed once with "108 is identical to 109": it compares count(*) of the whole sessions table before and after requests, and its last request starts a session, which runs the session garbage collection with a probability of 1/100. That deletes every expired row, including rows earlier tests left behind, so the count drops although the code under test changed nothing. AuthenticationTest and AuditTrailTest compare the same global count around requests that start a session (logins) and share the defect. SessionRows fixes a horizon (now + 600 s) when a test takes its snapshot and counts only rows that expire at or after it: garbage collection cannot delete them during the test, and every row written in the test (expiry now + 1800 s) is still counted, so a session stored by the code under test still fails the assertion.
knittingcode
added a commit
that referenced
this pull request
Oct 25, 2026
knittingcode
added a commit
that referenced
this pull request
Oct 25, 2026
knittingcode
added a commit
that referenced
this pull request
Oct 26, 2026
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.
Summary
Makes three integration tests independent of session garbage collection.
FpmSessionTest::testStatelessRoutesNeverTouchTheSessionfailed once locally withFailed asserting that 108 is identical to 109and passed on rerun.AuthenticationTest(3 tests) andAuditTrailTest(1 test) have the same defect. Only test code changes.Motivation and technical context
The tests compared
SELECT count(*) FROM sessions(the whole table) before and after some requests. Every request that starts a session runs the session garbage collection with probability 1/100 (gc_probability: 1,gc_divisor: 100inconfig/packages/session.yaml). Garbage collection deletes every row whose expiry (sess_lifetime) has passed, including rows that earlier tests left behind. If it ran during a test, the count dropped by one even though the code under test wrote and deleted nothing.FpmSessionTest, the last request (GET /api/_test/session, "reading an empty session starts it") starts a session, so garbage collection can run there.AuthenticationTestandAuditTrailTest, the login requests start sessions.Implementation
tests/Support/Session/SessionRows.snapshot()sets a horizon of now + 600 s, andcount()counts only rows withsess_lifetime >= horizon:FpmSessionTestandSessionAndCacheConfigurationTest. A route that wrongly stores a session therefore still fails the assertion.sessionCount(). Assertions and messages are unchanged.Testing performed
All runs used a disposable Compose test stack (
compose.test.yaml, projectflowcrm-b4fpm, removed afterwards).gc_probability: 100and an expired row planted before the first count. The old test failed at the last assertion (FpmSessionTest.php:95) withFailed asserting that 1 is identical to 2.This is the same off-by-one as the original 108 vs 109.--filteron the five names), 5 runs in a row:OK (5 tests, 110 assertions)each time.Failed asserting that 2 is identical to 1.(line 92), so the assertion still catches a stored session.OK (274 tests, 2379 assertions).FpmSessionTestalone, 3 runs:OK (17 tests, 228 assertions)each time.OK (145 tests, 416 assertions).[OK] No errors.Found 0 of 172 files that can be fixed.Errors 0.OK (23 tests, 24 assertions).d844b90passed (Repository guard and Dev environment).Security considerations
Only test code changes. The tests still fail when a stateless route, a failed login, a 401 or a login whose audit event fails stores a session (mutation check above). No assertion was removed or loosened beyond excluding rows that garbage collection may delete during the test.
Interaction with other PRs
git merge-treeshows one conflict, in theuseblock ofAuditTrailTest.php. feat(organizations): membership administration API (FND-010C) #19 drops theTestUserimport (it moved the audit helpers into theFailingAudittrait), and this PR addsSessionRows.use App\Tests\Support\Session\SessionRows;and dropTestUser.sessionCount()calls become$rows->count()as in this PR.Known limitations
gc_maxlifetimebelow 600 s,SessionAndCacheConfigurationTestfails first.