What is tested, where, and what the tests do not cover. See the design notes for why things work the way they do.
Test matrix
| Scenario | Where |
|---|---|
| Counting through every sink shape; original call sites survive forwarding | crates/how-far/tests/interface.rs |
The Pulse contract on NoPulse: nested plans, validation, shared views, split_array, outcomes from results; PhaseSpec::validate_split and Child::inert for implementors | crates/how-far/tests/pulse.rs |
Stage reservations and handles: direct calls with different data/results, failure before ?, drop/unwind, temporary labels, moved plans, wrong-plan keys, repeated work, fork–join with distinct branch outputs and nested sequences, rejected observations and shared workers | crates/how-far-along/tests/direct_stages.rs |
FnPulse: checkpoint-only callbacks, lazy observation, reentrant observation, final paced cancellation, concurrent first-stop latching, no callback from Drop; shares accounting with the tree tests | crates/how-far-along/tests/redesign.rs |
References, boxes and Arcs of a pulse: generic code taking &NoPulse by value, an owned Box<dyn Pulse> defaulting to it, stops, reports, splits and shares forwarded | crates/how-far/tests/forwarding.rs |
Paced: never reaching a no-op pulse, exact counts per interval, stops seen at the next reach, pending units counted after an early return, saturation, call sites | crates/how-far/tests/paced.rs |
A hand-written Pulse shared by scoped threads; 'static threads through shared views | crates/how-far/tests/pulse_threads.rs |
StopOnly: an application's token reaching every nested phase, owned tokens shared with spawned work, borrowed tokens refusing to share | crates/how-far/tests/stop_only.rs |
Result handoffs: foreign error identity, complete_with and its classified twin keeping an early ? inside the handoff | crates/how-far/tests/results.rs |
| Shared views administering concurrently: no refused revisions or plans, no report lost to a racing split, bounded revision history | crates/how-far-along/tests/sharing.rs |
Stages libraries calling each other: success, nested stop, failure versus cancellation, stage finish errors, abandonment | crates/how-far/tests/composition.rs, crates/how-far-along/tests/pulse.rs |
| Sizes of everything a caller holds or passes, asserted at compile time | crates/how-far/tests/footprint.rs, crates/how-far-along/tests/footprint.rs |
| A library crate (codec) and a library that calls it (pipeline), driven by an application, all in separate crates | examples/how-far-app/tests/cross_crate.rs |
Scoped fork-join children, spawned 'static threads, cancellation crossing threads, an observer on another thread, a tree moved into a thread | examples/how-far-app/tests/threads.rs |
Rayon: a stage shared by 1–8 workers, nested parallelism, recursive join, scope, 'static spawn, the global pool | examples/how-far-app/tests/rayon_pools.rs |
'static ownership: codec contexts that own their stop, Arc and Box pulses, Tokio spawn_blocking with async cancellation, async tasks reporting | examples/how-far-app/tests/statics.rs |
| Diagnostics across crates, including checks inside a codec context credited to the right stage | examples/how-far-app/tests/diagnose.rs |
| Application-planned trees: serial → 30% parallel → serial, repeated joins, Rayon and manual threads sharing a counter, totals and revisions, overrun and overflow, every outcome, frozen and abandoned records, a report racing with the finish | crates/how-far-along/tests/phases.rs, crates/how-far-along/src/tree.rs |
| A codec-style pipeline with two parallel waves, a terminal renderer, and a Tokio request whose client disconnects | crates/how-far-really/tests/hosts.rs |
| Pollers: thread-affine callbacks, lazy shared snapshots, busy and recursive dispatch, panics, posted delivery, workers stopped by a callback | crates/how-far-along/tests/polling.rs |
| Profiling: per-task gaps, call-site counts, overlap and stragglers, cancellation latency, bounded retention, clock faults, report timing on and off, workers sharing a span | crates/how-far-really/tests/profiling.rs |
| Diagnostics: report gaps versus stop gaps, covering spans, stage-weight candidates, negligible stages, callbacks | crates/how-far-really/tests/diagnostics.rs |
| Metadata replacement concurrent with snapshots, under Miri with strict provenance | crates/how-far-along/src/sync.rs, crates/how-far-along/tests/phases.rs |
| A real Wasm timer boundary, JSPI suspension and cancellation, progress posted from a worker | dev/how-far-wasm/check.mjs |
A UI thread observing and cancelling a wasm-bindgen-rayon pool in Chromium and WebKit | dev/how-far-browser/browser.spec.mjs |
The how-far crates on Rust 1.88; no_std builds for Cortex-M (including callbacks with native-width counters) and wasm32; every feature combination; i686, aarch64 Linux and Windows, Intel macOS | CI |
No test suite proves every consumer's behavior. There is no built-in ETA model or executor; exported observations support them without claiming that durations are CPU time or that fractions are elapsed time.
Browser and Wasm guidance is in the design notes.
The root quickstart and
integration guide are compiled as application-crate
doctests, including custom error classification and the fork–join example. just check-integration runs it and the caller example. Display
smoothing contracts live in crates/how-far-along/tests/smooth.rs; uneven pace
and feature-gated grouping are covered by crates/how-far-really/tests/diagnostics.rs.
just check-docs runs workspace doctests and builds rustdoc with warnings
rejected. On 2026-10-12, the root README's exact dependency block and Rust
quickstart also compiled and ran in a separate consumer using Git revision
7b88ef7b, with no workspace path overrides.
Build and runtime cost
The reservation and fork measurements compare variable-based handoffs and fork branches with the retained closure runner. The earlier named-stage record belongs to the initial string-based API. Both describe the IR metric.
The callback default change records the measured cost and assembly verification for unconditional callbacks.
dev/bench-how-far-build.py, run in CI on Rust 1.88, permits no core Cargo
features, only the enough production dependency,
and no build script. It caps Stages::run, reserved-stage and fork-branch handoffs at 120 additional
unoptimized how-far LLVM IR lines per call site, tracker code at 25,000 and the how-far-really diagnostics crate at
35,000 with default features. Optional smoothing and stage suggestions are
outside those default-feature caps. The guard also requires branch-free optimized PulseTree::check and
may_stop bodies with callbacks always available. It also counts rustc's instructions, which unlike wall time do not
depend on machine load. dev/how-far-checkpoint-cost counts, with perf, what
each observer costs in each library scenario around the same
#[inline(never)] defilter.
The 2026-10-06 record has the build cost
at commit 2bcc73a: 79 / 18,382 / 29,703 IR lines on Rust 1.99, and 88 / 19,986
/ 31,228 on 1.88. After the allocation, counter and diagnostics changes that
record reports 79 / 19,309 / 31,088 on 1.99 and 88 / 20,484 / 32,808 on 1.88. The
record's overhead matrix, measured at cb49a7f5, crosses nine observers with
eight library scenarios: step into a
PulseTree costs 65 to 77 instructions per checkpoint, StopOnly 28 and an
FnPulse callback 106, while pacing keeps every observer except
DiagnosticPulse under 0.3% of a 256 KiB defilter. A second table, on x86-64
and aarch64, does the same for every enough stop policy and check pattern. It also records the zenpng
adoption tests.
Later cleanup measurements are recorded separately: pace, stage grouping, and smoothing. Treat each result as belonging to its recorded revision and command, rather than as a live counter.
Real-library adoption checks
Zenresize PR 16 covers u8 resampling,
optional post-processing, padded rows and cancellation. The pinned
zenpng adoption fixture covers RGB8 Fast
compression, byte parity, serial/parallel execution, padded input and nesting.
These test the same library-owned phases and caller-owned completion as the
synthetic examples. They do not extend either library's other entry points.
Run the fixture explicitly with just check-encoder <destination>; it is not
part of the how-far workspace CI matrix.