test(server): make an empty log capture unrepresentable - #123
Merged
Conversation
capture_logs returned a bare String, so a future test could write
assert!(!logs.contains("secret")) against silence and go green. That
is the I12 failure mode #92/#96 closed only by convention.
Return a Captured newtype with no Deref and no contains. The text is
reachable only after the capture is shown non-empty (assert_logged,
assert_not_contains, or as_str). A Drop guard clears the thread-local
slot if f panics.
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.
What
capture_logsnow returns aCapturednewtype instead of a bareString.There is no
Deref<Target = str>and no publiccontains. The capturedtext is reachable only through a path that has already established the
capture is non-empty:
assert_logged,Captured::assert_not_contains,or
as_str(which panics on empty).The I12 call sites in
config.rsandhttp_auth.rsmigrate off rawlogs.contains(...). ADropguard clears the thread-local captureslot if
fpanics, so thedebug_assert!on entry is no longer theonly defence against residue.
Why
A negative assertion over an empty capture is vacuously true and looks
identical to a passing I12 check. #96 closed that at the then-existing
call sites by convention (
assert_captured/assert_loggedfirst).#105 then added new I12 negatives that went back to raw
contains,guarded only by a comment. The next test cannot express the vacuous
form at all.
Touches I12 only as test evidence: the production invariant is
unchanged, and the I12 negatives are stricter (silence now fails
closed as "captured nothing").
Verification
All five AGENTS.md commands, independently, on this tree:
cargo fmt --checkcargo clippy --workspace --all-targets -- -D warningscargo clippy -p bugwarden --features gen --all-targets -- -D warningscargo test --workspace --all-targets --locked(all passed)cargo deny check(advisories/bans/licenses/sources ok)Adversarial review before opening:
captured.contains("secret")does not compile (E0599, no methodnamed
containsonCaptured; probe reverted).token (
assert_not_contains_fails_when_the_needle_is_present;config.rs/http_auth.rsuse that same method onhush-key/WRITE/READ).captured nothing: the subscriber saw no events; missing needle iscaptured logs lack ….Closes #97.