Files
alkblobs/tests/conformance/factory.rs
T
glm-5.3-flash 327b952e4d feat(tests): the conformance suite's home — conventions, invariant backlog, harness skeleton (wave 1)
- tests/conformance/README.md: the convention doc — row naming (property-
  stated names, engine dimension is the column), the Contract stamp:
  format (the alkstore ADR-017 §4.2 convention adapted), the one-
  normative-owner-per-property rule, the factory contract (fresh
  isolated instance per open, idempotent teardown, safe over an
  abandoned instance), the SKIP posture (SQL-attached columns skip
  cleanly server-less; acceptance requires green against the server),
  the invariant backlog (the seven store-api.md §Invariants registered
  as the rows-to-grow table with pinning citations), and the mem-first
  column plan (mem is the contract-reference engine, ADR-011 §2)
- harness skeleton, compile-able with zero rows: StoreFactory (fresh
  + isolated + idempotent-teardown contract; the Store associated type
  is wave 2's binding point for the facade type), stamp.rs (the
  marker + convention anchor), backlog.rs (in-code registry with a
  traceability gate asserting INV-1..7 mirror §Invariants in order)
- no engine-specific code; no dependencies added

Verification: cargo test (33 passed across lib + 3 targets),
cargo clippy --all-targets -- -D warnings, cargo fmt --check
2026-10-11 18:44:04 +00:00

67 lines
3.1 KiB
Rust

//! The suite's factory contract (the alkstore `StoreFactory` pattern
//! adapted — docs/plans/implementation.md, decided point "Contract-
//! suite home").
//!
//! One shape, deliberately minimal: open a **fresh, isolated** store
//! instance per call (no state shared between rows or between
//! columns), with **idempotent teardown** — the full contract text is
//! the suite README §The factory contract. Engines implement this in
//! wave 2+'s column wiring; rows take factories, never stores.
//!
//! **The wave-2 binding.** The `Store` facade type arrives in wave 2
//! (store-api.md §What this is). This trait's `Store` associated type
//! is the skeleton's binding point for it: wave 2's first column (mem)
//! binds it to the real facade, and if binding reveals a shape
//! correction — most plausibly the associated type collapsing to the
//! concrete facade type across all factories — that is wave 2's to
//! make and record here and in the README.
//!
//! The SKIP posture is a factory-owner responsibility (README §SKIP
//! posture): SQL-attached factories probe their server before rows
//! run; a unreachable server skips the column cleanly, while the
//! engine wave's acceptance requires green against the server.
#![allow(dead_code)]
use std::future::Future;
use alkblobs::Error;
/// Vends fresh, isolated store instances to the suite's rows.
///
/// Implementers — the engine columns' wiring — yield an instance of
/// the `Store` facade over an isolated backing store (fresh temp
/// directory, pool, file, or schema per call, so a property's rows
/// never outlive their run into another's) plus a teardown disposing
/// of the backing store. Implementations must be `Send + Sync` so one
/// factory instance can be shared across row runs.
///
/// Rows call [`StoreFactory::open`], drive their assertions, and call
/// [`StoreFactory::teardown`] before returning; a failing assertion
/// panics the row (no teardown on that path), which is why teardown is
/// required to be idempotent and safe against an abandoned instance.
pub trait StoreFactory: Send + Sync {
/// The store instance type this factory vends — the wave-2 `Store`
/// facade's binding point (see the module docs).
type Store: Send;
/// The column's identity for reporting — which configuration rows
/// ran against (the constructor-mode vocabulary of ADR-011 §4,
/// once wave 2 names it). Rows never branch on it; the suite's
/// reporting and the SKIP posture's per-column bookkeeping do.
fn name(&self) -> &'static str;
/// Vend a fresh, isolated store instance. A failure here is an
/// environment failure (e.g. the SKIP posture's unreachable
/// server), not a row failure.
fn open(&self) -> impl Future<Output = Result<Self::Store, Error>> + Send;
/// Tear down the backing store behind this factory instance.
///
/// Idempotent per instance. The factory owns what teardown means —
/// deleting the temp directory, dropping the schema, closing the
/// pool — and owns the isolated-ness guarantee: no two `open`
/// calls ever share state.
fn teardown(&self) -> impl Future<Output = Result<(), Error>> + Send;
}