Skip to main content

mock_nexus/
lib.rs

1//! Mock Nexus raw-storage server with a failure-scenario table.
2//!
3//! Implements just enough HTTP/1.1 (std only) to exercise the nexus-raw transport contract.
4//! `GET`/`HEAD`/`PUT` with `Content-Length` or chunked bodies, `DELETE` with 204/404.
5//! Percent-encoded paths stored verbatim.
6//! One request per connection, `Connection: close` on every response.
7//! GET honors resumable downloads: a single open `Range: bytes=N-` is answered with `206` and `Content-Range`, out-of-range starts get `416`.
8//! Any other `Range` form is ignored.
9//! A [`Scenario`] selects a failure mode: truncated PUT and GET bodies, connection resets, held uploads, missing `Content-Length`, slow links, drifted documents, flaky 503s, 503s with a `Retry-After` pause, rate-limit 429s with `Retry-After`, redirects, and Basic-auth gating.
10//!
11//! Rust conformance tests use the library API directly.
12//! The `mock-nexus` binary exposes the same scenarios to shell- and Python-driven tests:
13//!
14//! ```text
15//! let server = mock_nexus::MockNexus::start(mock_nexus::Scenario::Atomic)?;
16//! let url = format!("{}1.14.0/version.json", server.base_url());
17//! ```
18//!
19//! Presets are named points in a behavior space; a [`Spec`] composes the space itself:
20//! layers stack (`Spec::atomic().with_auth(..).with_flaky(3)`), and `MockNexus::start_spec`
21//! runs a composed instance. A composed instance never enters the contract tables:
22//! presets and their drift guards are the contract, specs are code-level composition.
23//!
24//! A group repository is a separate deployment kind, not a scenario:
25//! [`MockNexus::start_group`] aggregates two or more running members, forwarding reads in member order and refusing writes.
26//! On a group handle the store mutators ([`MockNexus::insert`], [`MockNexus::enable_drift`]) are no-ops: a group stores nothing.
27//!
28//! The client-facing contract page `docs/reference/invariants.md` is rendered from [`SCENARIO_DOCS`].
29//! A drift test in the `invariants` module fails when a scenario change does not regenerate it.
30
31mod base64;
32mod group;
33mod handle;
34mod http;
35mod invariants;
36mod scenario;
37mod server;
38mod service_api;
39mod spec;
40mod storage;
41mod store;
42mod support;
43#[cfg(test)]
44mod tests;
45
46pub use handle::MockNexus;
47pub use invariants::{render_invariants_markdown, ScenarioDoc, SCENARIO_DOCS};
48pub use scenario::{Scenario, SCENARIOS};
49pub use server::Drip;
50pub use spec::Spec;
51pub use store::{Outcome, ReqLog};