Skip to content

(12) test-clock - #1773

Draft
daniel-noland wants to merge 18 commits into
pr/daniel-noland/config-algebrafrom
pr/daniel-noland/driven-clock
Draft

(12) test-clock#1773
daniel-noland wants to merge 18 commits into
pr/daniel-noland/config-algebrafrom
pr/daniel-noland/driven-clock

Conversation

@daniel-noland

@daniel-noland daniel-noland commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@coderabbitai

coderabbitai Bot commented Aug 28, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.55900% with 98 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
dataplane/src/packet_processor/fuzz.rs 87.41% 43 Missing and 34 partials ⚠️
clock/src/virtual_time.rs 92.85% 9 Missing and 3 partials ⚠️
tracectl/src/stamp.rs 93.61% 1 Missing and 2 partials ⚠️
clock/src/lib.rs 94.59% 1 Missing and 1 partial ⚠️
stats/src/rate.rs 95.83% 2 Missing ⚠️
acl/tests/property_predicate.rs 98.03% 1 Missing ⚠️
net/src/headers/view.rs 95.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from fa0e8f2 to b164a0f Compare August 28, 2026 03:05
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 5843caa to 6f106ac Compare August 28, 2026 03:05
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from b164a0f to 3cd5687 Compare August 28, 2026 03:34
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 6f106ac to 320c6aa Compare August 28, 2026 03:34
@daniel-noland daniel-noland changed the title feat(clock): give a test one clock it drives, and fix what that exposed test-clock Aug 28, 2026
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 320c6aa to d3c348d Compare August 28, 2026 04:22
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch 2 times, most recently from 1ec0be0 to de8e45f Compare August 28, 2026 05:11
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch 2 times, most recently from be78275 to 4969a2f Compare August 28, 2026 05:28
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from de8e45f to bea6549 Compare August 28, 2026 05:32
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 4969a2f to 26e6361 Compare August 28, 2026 05:47
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from bea6549 to f850a96 Compare August 28, 2026 05:48
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 26e6361 to 3ee9131 Compare August 28, 2026 06:18
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from f850a96 to 9398527 Compare August 28, 2026 06:21
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 3ee9131 to fcd1d11 Compare August 28, 2026 06:40
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from 9398527 to d497a39 Compare August 28, 2026 06:40
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from fcd1d11 to b26928b Compare August 28, 2026 07:08
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from d497a39 to 3e43aea Compare August 28, 2026 07:08
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from b26928b to 84d66cc Compare August 28, 2026 07:31
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from 3e43aea to 610dcf1 Compare August 28, 2026 07:31
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 84d66cc to a842024 Compare August 28, 2026 07:43
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from 610dcf1 to 698f663 Compare August 28, 2026 07:43
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from a842024 to c50fd96 Compare August 28, 2026 09:14
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from 698f663 to 26b967b Compare August 28, 2026 09:14
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from c50fd96 to ccbfc9c Compare August 28, 2026 17:16
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from 26b967b to 8968292 Compare August 28, 2026 17:16
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from ccbfc9c to 33377c4 Compare August 28, 2026 17:33
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 2805790 to a05db9f Compare September 6, 2026 21:27
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from a997efa to bc5df63 Compare September 6, 2026 21:27
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from a05db9f to 87d41d2 Compare September 8, 2026 01:36
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from bc5df63 to 48c3982 Compare September 8, 2026 01:36
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 87d41d2 to 9d1fe29 Compare September 8, 2026 01:51
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from 48c3982 to d843b5a Compare September 8, 2026 01:52
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 9d1fe29 to 31bb5c2 Compare September 8, 2026 01:58
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from d843b5a to 431fd90 Compare September 8, 2026 01:58
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from 31bb5c2 to ede1da7 Compare September 8, 2026 02:22
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from 431fd90 to 7107d20 Compare September 8, 2026 02:22
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/config-algebra branch from ede1da7 to f80bd96 Compare September 8, 2026 02:49
@daniel-noland
daniel-noland force-pushed the pr/daniel-noland/driven-clock branch from 7107d20 to dee5488 Compare September 8, 2026 02:49
daniel-noland and others added 18 commits September 9, 2026 12:36
Tokio's paused clock belongs to one runtime. A worker without that
runtime silently reads wall time, so expiry assertions can compare two
timelines after a test advances time.

Introduce a shared `Paused` driver and refuse off-runtime reads while a
virtual clock is live. Scope the guard to the driver's lifetime so
ordinary readers remain valid afterward, and provide `wall_clock` so
the same properties can exercise real time. Move the NAT expiry suites
onto the shared driver.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A destructor may run after Tokio's thread-local runtime context is
gone. If virtual time has been paused, reading the clock there panics
inside `Drop` and aborts the process without identifying the test.

Add an opengrep rule that rejects clock reads from `fn drop`. Match the
method itself because the Rust parser does not reliably constrain a
pattern to `impl Drop`.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Logs used wall time while expiry code used virtual time, so events
could not be correlated with the deadlines a test observed.

Stamp test logs with an offset from the routed clock. Use a checked
read so logging cannot panic when a thread lacks the active clock;
mark those records `off-clock` instead.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The pipeline property never aged its flows, so it could not detect a
flow that expired too early. Advancing time had previously been
meaningless because waits and deadlines read different clocks.

Draw waits as part of the generated schedule and advance between
rounds, where the driver can move time without measuring thread
scheduling. Keep waits within the flow lifetime and require delivered
flows to retain their disposition. Limit strict clock enforcement to
process-isolated nextest runs until clock ownership follows threads.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Clock enforcement was process-wide: concurrent `cargo test` cases
could trip each other's guard, while a worker spawned by the active
test could forget its runtime and fall back to wall time.

Use standard thread spawn hooks to inherit the active runtime and clock
membership through the thread tree. Enter the inherited runtime for
each read and keep the handle thread-local so later tests cannot reuse
an earlier clock. Probe hook support at build time; older toolchains
retain the check on the driving thread. Threads created outside
`std::thread` still fail rather than reading the wrong clock.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bolero's synchronous case loop never yielded to the surrounding Tokio
test runtime. Flow timers therefore never ran, each retained its flow
table, and long fuzz runs grew until they exhausted memory. The same
properties also proved nothing about expiry.

Run each case through a driven runtime and poll spawned tasks before
moving on. This lets timer counts and memory settle instead of growing
with the corpus.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
None of the thirteen NAT properties could run under `cargo bolero`.
Their vacuity guards rejected Bolero's target-selection pass, and
their undriven timer runtime accumulated flow tables until the process
ran out of memory.

Bypass case assertions during target selection and drive the timer
runtime around every fuzz case.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
An empty `sanitize` setting still makes cargo-bolero use
AddressSanitizer. Treating it as no sanitizer allowed Rust and the
sysroot to use incompatible instrumentation, while the explicit
`NONE` setting was rejected even though it matched an uninstrumented
sysroot.

Resolve cargo-bolero's default before comparing the requested and
recorded sanitizer settings. Warn for the compatible legacy default
and reject explicit mismatches.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Eleven flow-info properties placed `check!()` inside a closure, so
Bolero registered them under `{{closure}}`. No command-line target name
could select them.

Put each check at its named test site and scope the paused clock to one
case so timer tasks settle between inputs.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three packages built only because workspace feature unification exposed
`bolero_engine::any`. A package-only fuzz build lacked the `std` feature
that provides it and failed to compile.

Request Bolero's `std` feature in each affected package instead of
relying on an unrelated workspace dependency.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Twenty-four header shards delegated `check!()` to one helper. Bolero
registered the helper name repeatedly, leaving every shard impossible
to select.

Place the registration at each shard's test entry point while retaining
the shared property body.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The remaining shared property helpers registered one target under the
helper name instead of the ACL, concurrency, config, and stats tests
that called them. Those advertised targets could never run.

Register `check!()` at each test entry point and adapt the config census
helper to the macro's early return. All 596 listed workspace targets are
now selectable.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
cargo-bolero sets `RUSTFLAGS`, causing Cargo to ignore the workspace
flags. Fuzz builds lost `tokio_unstable` and the registered cfg names.
Sanitizer coverage also instrumented non-Bolero test binaries that had
no runtime symbols, so package builds failed without a sanitizer.

Prepend the configured workspace flags and link the local no-main
libFuzzer runtime when available. This removes the cfg warnings and
allows every package to fuzz with `sanitize=NONE`.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Modeling fuzzing as a Cargo profile made it mutually exclusive with
coverage, although both are compiler instrumentation that should
compose with each other and with sanitizers. Instrumented containers
could also replace clean images because instrumentation is absent from
their version tags.

Represent instrumentation as a normalized set parallel to sanitizers,
retain a `checked` profile for compiler safety settings, and refuse
container builds that carry diagnostic instrumentation.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fuzz instrumentation broke the native-dependency sysroot. rdma-core's
build tools referenced sanitizer-coverage symbols without a runtime,
DPDK's ThinLTO discarded module constructors while retaining their
relocations, and the overlay could not see the selected instrumentation.

Allow unresolved symbols in throwaway rdma-core tools, disable LTO for
fuzz-instrumented C and C++, omit their fuzz link flags, and pass the
instrumentation set into the overlay.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Clock membership used a boolean even though one thread may hold nested
`Paused` drivers. Dropping the inner driver cleared the flag and let
off-runtime reads through for the rest of the outer driver's lifetime.

Count thread membership so the guard remains armed until the last
nested driver leaves. Update the module documentation to describe the
supported nesting behavior.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Daniel Noland <daniel@githedgehog.com>
Moving the shared fuzz registrations removed the last uses of
`RefUnwindSafe` from two integration tests, leaving warnings that fail
the all-targets Clippy run. Remove the stale imports.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Daniel Noland <daniel@githedgehog.com>
The process-wide fuzz runtime still used `std::sync::LazyLock` directly,
violating the workspace rule that shared synchronization goes through
the concurrency facade.

Route that runtime through the facade. Keep paused-clock bookkeeping on
`std::sync`: it belongs outside model-checker scheduling, and replacing
it makes virtual-time properties sleep in real time.

Signed-off-by: Daniel Noland <daniel@githedgehog.com>
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