#41 Fix flaky TestSealOpenRoundtrip (deterministic) #42

Merged
JMR-dev merged 1 commits from ticket-41-flaky-crypto-test into main 2026-07-02 21:37:38 +00:00
JMR-dev commented 2026-07-02 21:32:48 +00:00 (Migrated from github.com)

Problem

internal/crypto/crypto_test.go TestSealOpenRoundtrip included a 1-byte plaintext case ("x") and asserted the plaintext byte was absent from the whole sealed frame:

if len(pt) > 0 && bytes.Contains(sealed, pt) {
    t.Errorf("sealed frame contains the plaintext verbatim (len %d)", len(pt))
}

For a 1-byte plaintext this scans the entire ~36-byte frame, ~29 bytes of which are random (12-byte nonce + 1-byte ciphertext + 16-byte tag). The chance at least one random byte equals 'x' is 1 - (255/256)^29 ≈ 10.7%, so the test failed ~11% of runs. Because it lives on main, ~11% of every CI run could fail spuriously.

Reproduced before the fix (-run TestSealOpenRoundtrip -count=200): repeated crypto_test.go:50: sealed frame contains the plaintext verbatim (len 1).

Fix (test-only)

Replace the probabilistic per-byte frame scan with a deterministic check that the sealed frame is never the bare plaintext — it always prepends a 7-byte header + 12-byte nonce and appends a 16-byte GCM tag, so it differs in both length and content:

if bytes.Equal(sealed, pt) {
    t.Errorf("sealed frame equals the plaintext (len %d)", len(pt))
}
  • The round-trip Open(Seal(x)) == x assertion is unchanged.
  • Verbatim-leak coverage already lives deterministically in TestNoPlaintextLeak (multi-byte marker where a chance match is negligible), so it is not duplicated here.
  • No production code changed — only internal/crypto/crypto_test.go (13 insertions, 2 deletions).

Evidence

$ go test ./internal/crypto/... -count=50
ok  	github.com/JMR-dev/LibreMail-Bug-Report-Ingest/internal/crypto	0.353s

# full package, -count=50 -v: TestSealOpenRoundtrip PASS count: 50

$ go test ./internal/crypto/ -run TestSealOpenRoundtrip -count=500   # was ~11% flaky
ok  	github.com/JMR-dev/LibreMail-Bug-Report-Ingest/internal/crypto	0.360s

$ go vet ./...        # clean (exit 0)
$ go test ./...       # all packages ok

Closes #41

## Problem `internal/crypto/crypto_test.go` `TestSealOpenRoundtrip` included a **1-byte** plaintext case (`"x"`) and asserted the plaintext byte was absent from the whole sealed frame: ```go if len(pt) > 0 && bytes.Contains(sealed, pt) { t.Errorf("sealed frame contains the plaintext verbatim (len %d)", len(pt)) } ``` For a 1-byte plaintext this scans the entire ~36-byte frame, ~29 bytes of which are random (12-byte nonce + 1-byte ciphertext + 16-byte tag). The chance at least one random byte equals `'x'` is `1 - (255/256)^29 ≈ 10.7%`, so the test failed **~11%** of runs. Because it lives on `main`, ~11% of every CI run could fail spuriously. Reproduced before the fix (`-run TestSealOpenRoundtrip -count=200`): repeated `crypto_test.go:50: sealed frame contains the plaintext verbatim (len 1)`. ## Fix (test-only) Replace the probabilistic per-byte frame scan with a **deterministic** check that the sealed frame is never the bare plaintext — it always prepends a 7-byte header + 12-byte nonce and appends a 16-byte GCM tag, so it differs in both length and content: ```go if bytes.Equal(sealed, pt) { t.Errorf("sealed frame equals the plaintext (len %d)", len(pt)) } ``` - The round-trip `Open(Seal(x)) == x` assertion is unchanged. - Verbatim-leak coverage already lives deterministically in `TestNoPlaintextLeak` (multi-byte marker where a chance match is negligible), so it is not duplicated here. - **No production code changed** — only `internal/crypto/crypto_test.go` (13 insertions, 2 deletions). ## Evidence ``` $ go test ./internal/crypto/... -count=50 ok github.com/JMR-dev/LibreMail-Bug-Report-Ingest/internal/crypto 0.353s # full package, -count=50 -v: TestSealOpenRoundtrip PASS count: 50 $ go test ./internal/crypto/ -run TestSealOpenRoundtrip -count=500 # was ~11% flaky ok github.com/JMR-dev/LibreMail-Bug-Report-Ingest/internal/crypto 0.360s $ go vet ./... # clean (exit 0) $ go test ./... # all packages ok ``` Closes #41
Sign in to join this conversation.