Summary
TestMaskTextStaysCheapOnAPayloadFullOfSecrets (internal/security/mask_test.go:254) asserts a hard wall-clock bound on a 64KB payload:
for i := 0; b.Len() < 64*1024; i++ { ... } // 65,579 bytes
...
if elapsed > 2*time.Second {
t.Fatalf("masking a %d-byte payload took %s", len(text), elapsed)
}
It passes comfortably today and is not currently flaky. Filing it because it is the same shape that just cost us a red main, and it is one refactor away from converting into that failure.
Why now
#1174 added TestDetectionScansUntruncatedResponse with a ~75KB payload fed to security.Detector.Scan, bounded by waitForDetectionMetadata's 5s poll deadline. It passed locally and failed in both CI workflows, because:
Detector.Scan costs ~5.5 µs/byte, and the race detector multiplies that by ~24x (measured 114–137 µs/byte across 1K–75K payloads)
- CI runs
-race in unit-tests.yml and e2e-tests.yml; a plain local go test does not
- so the scan took ~9.5s against a 5s deadline
Fixed in #1207 by sizing the payload down. mask_test.go is the only other place in the repo where a multi-KB payload meets a hard deadline.
Current headroom (measured, -race, Apple M-series)
go test ./internal/security/ -race -run TestMaskTextStaysCheapOnAPayloadFullOfSecrets -count=3
masked 65579 bytes in 250.714041ms
masked 65579 bytes in 233.734208ms
masked 65579 bytes in 238.472417ms
≈ 3.8 µs/byte under -race — about 36x cheaper per byte than Scan, because MaskText/Redact is a single replacement sweep rather than patterns + file paths + high-entropy windows. That leaves roughly 8x headroom against the 2s assert, so a 2–3x slower GitHub runner is fine.
The risk
The margin depends entirely on masking never touching the Scan path. If anyone routes MaskText through Scan, or adds a per-value Scan to the mask sweep, the per-byte cost jumps ~36x and this test fails immediately on CI while still passing locally — with a wall-clock message that reads like a performance regression rather than a test-sizing problem.
A bare absolute wall-clock assertion on a shared CI runner is also inherently the fragile shape: it measures the runner as much as the code.
Suggested fix
Any of these, in rough order of preference:
- Shrink the payload (4–8KB) and keep the bound — the test is guarding against accidental O(n²), which a smaller payload still catches.
- Assert on shape rather than wall-clock: time two sizes and check the ratio is roughly linear, which is race- and runner-independent.
- Keep the payload but raise the bound and document the
-race multiplier, so a future reader knows what the number is protecting against.
Option 2 is the only one that actually survives someone changing the underlying cost, and it tests the real property ("masking is linear") instead of a proxy.
Related
Summary
TestMaskTextStaysCheapOnAPayloadFullOfSecrets(internal/security/mask_test.go:254) asserts a hard wall-clock bound on a 64KB payload:It passes comfortably today and is not currently flaky. Filing it because it is the same shape that just cost us a red
main, and it is one refactor away from converting into that failure.Why now
#1174 added
TestDetectionScansUntruncatedResponsewith a ~75KB payload fed tosecurity.Detector.Scan, bounded bywaitForDetectionMetadata's 5s poll deadline. It passed locally and failed in both CI workflows, because:Detector.Scancosts ~5.5 µs/byte, and the race detector multiplies that by ~24x (measured 114–137 µs/byte across 1K–75K payloads)-raceinunit-tests.ymlande2e-tests.yml; a plain localgo testdoes notFixed in #1207 by sizing the payload down.
mask_test.gois the only other place in the repo where a multi-KB payload meets a hard deadline.Current headroom (measured,
-race, Apple M-series)≈ 3.8 µs/byte under
-race— about 36x cheaper per byte thanScan, becauseMaskText/Redactis a single replacement sweep rather than patterns + file paths + high-entropy windows. That leaves roughly 8x headroom against the 2s assert, so a 2–3x slower GitHub runner is fine.The risk
The margin depends entirely on masking never touching the
Scanpath. If anyone routesMaskTextthroughScan, or adds a per-valueScanto the mask sweep, the per-byte cost jumps ~36x and this test fails immediately on CI while still passing locally — with a wall-clock message that reads like a performance regression rather than a test-sizing problem.A bare absolute wall-clock assertion on a shared CI runner is also inherently the fragile shape: it measures the runner as much as the code.
Suggested fix
Any of these, in rough order of preference:
-racemultiplier, so a future reader knows what the number is protecting against.Option 2 is the only one that actually survives someone changing the underlying cost, and it tests the real property ("masking is linear") instead of a proxy.
Related
internal/runtime