feat(tests): the conformance suite's local column — the dual-tier dispatch-coverage shape green (wave 2)
- tests/conformance/local_column.rs: the first dual-tier column, run against the kv = mem + large = local factory (ADR-012 §6.3) — fresh temp-root store per open, per-instance tracked roots, idempotent teardown safe against abandoned/panicking rows (structural tests included); never skips (mem-gated — the dual-tier constructor rides feature mem until wave 3 provides an ungated kv engine) - the reference INV row set (rows.rs) mirrored against the dual-tier factory at a column-declared tuned threshold (1024), so the shared matrix and race fixtures exercise both tiers' bodies (INV-7) - dispatch rows grown: pure-function routing across put paths and re-puts with an on-disk placement oracle (tier residency is facade-invisible; with kv = mem the medium is the oracle), threshold boundary legs at the tuned and shipped-default thresholds with the constructor-tuned re-route leg, and fall-through per op with both-tier miss shapes (ADR-003/ADR-012 §6.1/§6.3/§6.5) - local-specific rows: on-disk stage-hygiene exact counts over both put paths (the real stage form, INV-3), pread windows over committed files with slice digests verified independently (ADR-006/ADR-010), virgin-store no-ops on a fresh root, and exact sweep counts over a both-tiers pool (INV-4/INV-5's both-tiers form) - rows.rs shared fixtures made pub(crate); README records the column's row inventory (§Columns beyond the reference set), the declared- threshold posture, and the new current state - stat-as-stat rides the mirrored INV-6 row's over-threshold legs; the Drop-cancellation hygiene form stays per-engine (recorded) Verification: cargo test (default) green; cargo test --features mem green (97 lib + 37 conformance + 4 git-interop); cargo test --all-features green; clippy --all-targets -D warnings green in both feature shapes (default + all-features); cargo fmt --check green; cargo doc --no-deps shows only the pre-existing warning class
This commit is contained in:
1 parent
f86e20a217
commit
45c456989f
5 files changed
+1560
-43
No files matched your search
+73
-12
@@ -185,6 +185,49 @@ families' first shapes (the `SweeperLock` abort) complete the three
|
||||
`GcAbortCause` variants within the single-node exact-count family
|
||||
(ADR-013 §2's lease, its in-process ADR-012 §5 form).
|
||||
|
||||
## Columns beyond the reference set (INV-7's mirror + extension)
|
||||
|
||||
The constructor-mode rows of the reference set run wherever the mode
|
||||
they name is constructible (README §The reference row set). A
|
||||
multi-tier column mirrors the set and grows **its own rows** for what
|
||||
its configuration carries that the reference set's single-tier host
|
||||
did not: the dispatch-coverage shape (ADR-012 §6.3 — both tiers
|
||||
load-bearing) and the engine's tier-specific properties. Those rows
|
||||
are still conformance rows — ADR-stamped, named for the property,
|
||||
traced — but they take the **column's concrete factory** instead of
|
||||
the `StoreFactory` trait: they observe the backing medium, which an
|
||||
engine-uniform row (unable to branch on any engine, and unable to see
|
||||
any tier's residency through the facade) cannot. Tier placement is
|
||||
facade-invisible by design; with `kv = mem`, the medium itself is the
|
||||
oracle — the mem kv tier never touches the factory's disk, so a
|
||||
committed file outside the staging area under the column's temp root
|
||||
is exactly one large-tier entry, and its absence beside a served read
|
||||
is exactly a kv-tier entry.
|
||||
|
||||
**The local column's own rows** (tests/conformance/local_column.rs,
|
||||
the dispatch-coverage and local-specific families):
|
||||
|
||||
| Row | Traces to |
|
||||
|---|---|
|
||||
| `routing_is_a_pure_function_of_length_across_put_paths_and_re_puts` | ADR-003 §Dispatch policy (purity/no-migration); ADR-012 §6.3; INV-7 facade-contract row |
|
||||
| `threshold_boundary_lengths_route_deterministically` | ADR-003 §Dispatch policy (at/below/above the threshold; constructor-tuned re-route); ADR-012 §6.3 |
|
||||
| `kv_tier_misses_fall_through_to_the_large_tier_per_op` | ADR-012 §6.1 (fall-through per op); ADR-012 §6.5 ruling 5 (miss shapes); ADR-006 |
|
||||
| `stage_hygiene_exact_counts_on_disk_over_both_put_paths` | INV-3's stage form (exact counts on disk); ADR-010 §1; ADR-003 |
|
||||
| `pread_windows_read_committed_files_mid_slices_and_eof_clamped` | store-api.md §Read path; ADR-010 §1 (streaming cursor); ADR-006 |
|
||||
| `virgin_store_reads_are_no_ops_on_a_fresh_root` | store-api.md §Error model (virgin-store semantics); ADR-012 §6.5 |
|
||||
| `sweep_counts_stay_exact_over_both_tiers` | INV-4/INV-5's both-tiers form (exact counts + list correctness through outcomes); ADR-005; ADR-012 §1/§6.3/§6.7 |
|
||||
|
||||
**The dual-tier threshold is declared configuration, not a
|
||||
behavioral probe.** The kv-only reference row discovers its factory's
|
||||
threshold by probing (rejections read nothing — free). A dual-tier
|
||||
store never rejects a length, and tier residency is facade-invisible,
|
||||
so there is nothing to probe: the dispatch rows take the threshold
|
||||
the column's factory declares (the same value its constructor took —
|
||||
configuration, like the mem column's kv-only threshold). The mem-only
|
||||
and kv-only mode rows do not mirror onto the dual-tier factories (the
|
||||
precondition `mode()` shapes they assert are not this column's mode);
|
||||
the dispatch rows are the dual-tier mode's facade-contract coverage.
|
||||
|
||||
## Column plan
|
||||
|
||||
**mem is the contract-reference engine** (ADR-011 §2): wave 2 lands
|
||||
@@ -197,15 +240,33 @@ and first run in wave 6.
|
||||
|
||||
## Current state
|
||||
|
||||
The harness is green on the **mem column** (wave 2): the factory
|
||||
binding is the concrete `alkblobs::Store` facade (see §The factory
|
||||
contract — the binding demonstrator remains in `binding.rs`), the
|
||||
reference row set is landed (§The reference row set — `rows.rs`,
|
||||
every row ADR-stamped and traced to the backlog), the column's
|
||||
factories (`mem-only`, the reference; `kv-only(mem)` at a
|
||||
column-declared threshold) vend fresh isolated stores with idempotent
|
||||
teardown (`mem_column.rs`, the structural factory-contract tests
|
||||
included), and mem never skips. The column runs under feature `mem`
|
||||
(`cargo test --features mem`); the row set compiles ungated so the
|
||||
reference rows stay type-checked in default builds. The local column
|
||||
grows next.
|
||||
The harness is green on **two columns** (wave 2). The **mem column**
|
||||
is the contract-reference column: the factory binding is the concrete
|
||||
`alkblobs::Store` facade (see §The factory contract — the binding
|
||||
demonstrator remains in `binding.rs`), the reference row set is landed
|
||||
(§The reference row set — `rows.rs`, every row ADR-stamped and traced
|
||||
to the backlog), the column's factories (`mem-only`, the reference;
|
||||
`kv-only(mem)` at a column-declared threshold) vend fresh isolated
|
||||
stores with idempotent teardown (`mem_column.rs`, the structural
|
||||
factory-contract tests included), and mem never skips.
|
||||
|
||||
The **local column** (the suite's first dual-tier column, the
|
||||
dispatch-coverage shape ADR-012 §6.3 names) mirrors the reference INV
|
||||
rows against its `kv = mem` + `large = local` factory at a
|
||||
column-declared tuned threshold — the shared matrix and race fixtures
|
||||
cross it, so both tiers' bodies are exercised — and grows the
|
||||
dispatch-coverage rows (pure-function routing with an on-disk
|
||||
placement oracle, fall-through per op, threshold boundaries at both
|
||||
the tuned and the shipped-default threshold) plus the local-specific
|
||||
rows (on-disk stage hygiene exact counts, pread windows, virgin-store
|
||||
no-ops, the both-tiers sweep shape) — §Columns beyond the reference
|
||||
set is the recorded inventory. Its factory instances each track and
|
||||
remove their own temp roots (idempotent teardown, panicking-row-safe;
|
||||
each runner owns its instance so concurrent rows never share roots).
|
||||
mem-only/kv-only modes and the local column never skip, but the local
|
||||
column is feature-gated on `mem`: the `dual_tier_mem_local`
|
||||
constructor rides feature `mem` because mem is the only constructible
|
||||
kv engine until wave 3 (the gate is the kv pairing's, not the local
|
||||
engine's, which is ungated in `src/`) — the column runs under `cargo
|
||||
test --features mem`, with the reference row set compiling ungated so
|
||||
it stays type-checked in default builds.
|
||||
File diff suppressed because it is too large.
Load diff
@@ -15,11 +15,17 @@
|
||||
//! skip-free reference shape) proves the contract implementable
|
||||
//! against the real type.
|
||||
//!
|
||||
//! The rows landed with wave 2's mem column: [`rows`] holds the
|
||||
//! reference row set (INV-1…6 plus the two constructor-mode rows,
|
||||
//! ADR-stamped, traced to [`backlog`]) and [`mem_column`] is the
|
||||
//! contract-reference column ([`README`](./README.md) §The reference
|
||||
//! row set is the recorded inventory other columns mirror).
|
||||
//! The reference rows landed with wave 2's mem column: [`rows`] holds
|
||||
//! the reference row set (INV-1…6 plus the two constructor-mode rows,
|
||||
//! ADR-stamped, traced to [`backlog`]); the columns' records live in
|
||||
//! their module docs ([`README`](./README.md) §The reference row set
|
||||
//! is the recorded inventory other columns mirror).
|
||||
//!
|
||||
//! The columns: [`mem_column`] — the contract-reference column;
|
||||
//! [`local_column`] — the suite's first dual-tier column (the
|
||||
//! `kv = mem` + `large = local` dispatch-coverage shape ADR-012 §6.3
|
||||
//! names), which mirrors the reference set and grows the
|
||||
//! dispatch-coverage and local-specific rows.
|
||||
//!
|
||||
//! Items beyond the tests below are the later columns' surface, hence
|
||||
//! the scoped `#![allow(dead_code)]` — it shrinks as columns land.
|
||||
@@ -31,6 +37,8 @@ mod backlog;
|
||||
mod binding;
|
||||
mod factory;
|
||||
#[cfg(feature = "mem")]
|
||||
mod local_column;
|
||||
#[cfg(feature = "mem")]
|
||||
mod mem_column;
|
||||
mod rows;
|
||||
mod stamp;
|
||||
|
||||
+22
-17
@@ -52,24 +52,25 @@ use alkblobs::{
|
||||
///
|
||||
/// A set-backed liveness source — the live-shared seam's test shape:
|
||||
/// the store consults the same set the row mutates, so answers are
|
||||
/// live-shared, never registration snapshots.
|
||||
/// live-shared, never registration snapshots. `pub(crate)`: the
|
||||
/// suite's other columns reuse these fixtures.
|
||||
#[derive(Default)]
|
||||
struct SetSource {
|
||||
pub(crate) struct SetSource {
|
||||
live: Mutex<BTreeSet<Key>>,
|
||||
}
|
||||
|
||||
impl SetSource {
|
||||
fn register(store: &Store) -> Arc<SetSource> {
|
||||
pub(crate) fn register(store: &Store) -> Arc<SetSource> {
|
||||
let source = Arc::new(SetSource::default());
|
||||
store.register_liveness_source(source.clone());
|
||||
source
|
||||
}
|
||||
|
||||
fn add(&self, key: Key) {
|
||||
pub(crate) fn add(&self, key: Key) {
|
||||
self.live.lock().insert(key);
|
||||
}
|
||||
|
||||
fn remove(&self, key: &Key) {
|
||||
pub(crate) fn remove(&self, key: &Key) {
|
||||
self.live.lock().remove(key);
|
||||
}
|
||||
}
|
||||
@@ -87,16 +88,16 @@ impl LivenessSource for SetSource {
|
||||
/// A set-backed protect callback; `None` models the failed-to-answer
|
||||
/// case (abort-as-data on the safe side).
|
||||
#[derive(Default)]
|
||||
struct SetProtect {
|
||||
pub(crate) struct SetProtect {
|
||||
set: Mutex<Option<Vec<Key>>>,
|
||||
}
|
||||
|
||||
impl SetProtect {
|
||||
fn set_keys(&self, keys: Vec<Key>) {
|
||||
pub(crate) fn set_keys(&self, keys: Vec<Key>) {
|
||||
*self.set.lock() = Some(keys);
|
||||
}
|
||||
|
||||
fn fail(&self) {
|
||||
pub(crate) fn fail(&self) {
|
||||
*self.set.lock() = None;
|
||||
}
|
||||
}
|
||||
@@ -129,15 +130,15 @@ impl ProtectCallback for LatchProtect {
|
||||
/// A stream cut at controlled chunk boundaries (`sizes`, in order;
|
||||
/// tail data falls out whole) — makes multi-read loops, mid-stream
|
||||
/// overflow, and staged continuation observable past the put loop's
|
||||
/// own chunking.
|
||||
struct Chunked {
|
||||
/// own chunking. `pub(crate)`: the suite's other columns reuse it.
|
||||
pub(crate) struct Chunked {
|
||||
data: Vec<u8>,
|
||||
cursor: usize,
|
||||
sizes: std::collections::VecDeque<usize>,
|
||||
}
|
||||
|
||||
impl Chunked {
|
||||
fn new(data: &[u8], sizes: &[usize]) -> Chunked {
|
||||
pub(crate) fn new(data: &[u8], sizes: &[usize]) -> Chunked {
|
||||
Chunked {
|
||||
data: data.to_vec(),
|
||||
cursor: 0,
|
||||
@@ -177,15 +178,15 @@ impl AsyncRead for Chunked {
|
||||
|
||||
/// A stream that delivers `fail_after` bytes then errors mid-stream —
|
||||
/// the non-restartable source's failure (the failure-discard path's
|
||||
/// injectable shape).
|
||||
struct Failing {
|
||||
/// injectable shape). `pub(crate)`: the suite's other columns reuse it.
|
||||
pub(crate) struct Failing {
|
||||
data: Vec<u8>,
|
||||
cursor: usize,
|
||||
fail_after: usize,
|
||||
}
|
||||
|
||||
impl Failing {
|
||||
fn new(data: &[u8], fail_after: usize) -> Failing {
|
||||
pub(crate) fn new(data: &[u8], fail_after: usize) -> Failing {
|
||||
Failing {
|
||||
data: data.to_vec(),
|
||||
cursor: 0,
|
||||
@@ -247,14 +248,18 @@ fn matrix() -> Vec<Vec<u8>> {
|
||||
]
|
||||
}
|
||||
|
||||
fn patterned(len: usize, modulus: u32) -> Vec<u8> {
|
||||
/// A content-shape generator: `len` bytes cycling against `modulus` —
|
||||
/// deterministic, size-tunable content. `pub(crate)`: the suite's
|
||||
/// other columns reuse it.
|
||||
pub(crate) fn patterned(len: usize, modulus: u32) -> Vec<u8> {
|
||||
(0..len as u32).map(|i| (i % modulus) as u8).collect()
|
||||
}
|
||||
|
||||
/// One leg of the exact-count sweep assertions: a completed report's
|
||||
/// counts are exact over the staged set (`candidates_staged ==
|
||||
/// deleted + cancelled_by_arbitration`).
|
||||
fn assert_exact_counts(report: &alkblobs::SweepReport) {
|
||||
/// deleted + cancelled_by_arbitration`). `pub(crate)`: the suite's
|
||||
/// other columns reuse it.
|
||||
pub(crate) fn assert_exact_counts(report: &alkblobs::SweepReport) {
|
||||
assert_eq!(
|
||||
report.candidates_staged,
|
||||
report.deleted + report.cancelled_by_arbitration,
|
||||
|
||||
Reference in new issue
Block a user