Skip to content

Fix OCSP test flakiness on repeated in-process runs - #200

Merged
Xor-el merged 1 commit into
masterfrom
fix/ocsp-test-chain-isolation
Sep 10, 2026
Merged

Fix OCSP test flakiness on repeated in-process runs#200
Xor-el merged 1 commit into
masterfrom
fix/ocsp-test-chain-isolation

Conversation

@Xor-el

@Xor-el Xor-el commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Summary

TOcspTest passes on the first run but fails five tests on a second run in the
same process (as seen in the Delphi/DUnit GUI, running the suite twice without
closing the app):

  • TestSilentOcspLeavesOutcomeToCrls
  • TestPathAcceptsDespiteUnauthorisedOcspSigner
  • TestPathAcceptsDespiteStaleOcspResponse
  • TestPathAcceptsDespiteUnrelatedOcspResponse
  • TestDefaultRevocationCheckerRunsCrls

Root cause

A test-isolation bug, not a library defect. TOcspTest caches its generated
root -> intermediate -> end-entity chain and a single reference instant
(FChainUtcNow) in instance fields behind a if FRootCert <> nil then Exit
guard, and SetUp never clears them (there is no TearDown).

DUnit builds the test-case instances once and reuses them for the life of the
process, so the second run finds the first run's chain still cached and skips
rebuilding. The CRLs are pinned to FChainUtcNow (thisUpdate = -1 min,
nextUpdate = +10 min), and the certificates to a now-5s .. now+30min window,
but the path is validated against the live clock (PkixParameters.Date is never
set). Once the two runs are more than a few minutes apart, the cached CRLs'
nextUpdate is already in the past, so the "clean CRLs accept the path" cases
flip to rejection; once past 30 minutes the cached certificates expire too, so
validation fails at the intermediate first, which is why the default-checker
test reports blame index 1 instead of 0.

The FPC console runner never reproduced this because it runs each suite in a
fresh process (fresh instances).

Fix

Clear the cached chain fields in SetUp so EnsureChain rebuilds a fresh,
time-consistent chain on every run.

TOcspTest cached its generated certificate chain and reference instant in
instance fields behind a nil guard, and SetUp never cleared them. DUnit reuses
a test-case instance for the life of the process, so a second run reused the
first run's chain: its CRLs pin thisUpdate/nextUpdate to the original instant
(a ten-minute window) while the path is validated against the live clock, so
once the runs were more than a few minutes apart the cached CRLs were stale and
the "clean CRLs accept the path" cases flipped to rejection, with the blame
index shifting to the intermediate once the cached certificates also expired.

Clear the cached chain fields in SetUp so EnsureChain rebuilds a fresh,
time-consistent chain on every run.
@Xor-el
Xor-el merged commit 97486d9 into master Sep 10, 2026
15 checks passed
@Xor-el
Xor-el deleted the fix/ocsp-test-chain-isolation branch September 10, 2026 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant