Expand description
A conformance kit for Resolver implementations (feature testkit).
A resolver is read-only, so the kit never writes through it. Instead it hands out
Fixtures (key documents, descriptors, receipts, and the versions of stored cells), the
caller loads them into the resolver under test however that resolver is filled (maps, a
database, files), and the kit then verifies receipts through it and looks things up in
it. Each check returns a Report of what failed; Kit::check runs all of them.
use datumesh_core::testkit::{Fixtures, Kit};
use datumesh_core::MapResolver;
fn load(fx: &Fixtures) -> MapResolver {
let mut m = MapResolver::new();
for (fn_hash, bytes) in &fx.descriptors {
m.insert_descriptor(fn_hash.as_str(), bytes.as_slice());
}
for (hash, bytes) in &fx.receipts {
m.insert_receipt(hash.as_str(), bytes.as_slice());
}
// MapResolver keeps one value per cell: the versions come in tx order, so the
// latest one stays. A time-aware resolver loads them all.
for v in &fx.versions {
m.insert_value(v.cell_id.as_str(), v.value.clone());
}
m
}
if let Err(report) = Kit::new().run(load) {
panic!("{report}");
}The checks:
check_lazy_calls: through aRecordingwrapper,verifyasks the resolver only for what step 7 reaches: the descriptor once; the inputs in order up to the first that fails;evaluateonce, after 7.1-7.5, with the receipt’s cell andasof; and nothing at all when the receipt fails before step 7.check_unavailable: an unknownfn_hashisE_FN_UNAVAILABLE, an input receipt it does not have isE_INPUT_UNAVAILABLE(first or second input), a function it cannot evaluate isE_EVAL_UNAVAILABLE(ok, levelsigned), and looking up unknown or malformed hashes (empty, uppercase, too long, non-hex, NUL, SQL or path syntax, non-ASCII) givesNonewithout panicking.check_bytes:descriptorandreceiptreturn exactly the bytes loaded (all fixture bytes are canonical JSON, so a resolver that canonicalises what it is given still passes).check_asof:evaluatereceives the receipt’sasof, and stored cells recompute. WithKit::time_aware, a cell with versions at several times gives the value of its latest version withtx <= asof(inclusive at eachtx,Nonebefore the first), both throughverifyand through directevaluatecalls.
The kit expects a resolver to evaluate only what the fixtures give it: the versions of
stored cells. Computed cells (convert, language expr) are not evaluable, so receipts
of them end at E_EVAL_UNAVAILABLE. A panic in the resolver propagates to the caller.
The fixtures come from the specification’s vectors (revision spec-0.3.0; the files
used are unchanged since spec-0.2.1), in canonical form, plus receipts signed for the
kit with the vectors’ seeds (feature sign): a second
fx_rate cell (EUR/CHF) with versions at two times, and a convert receipt whose first
input is not loaded. They are embedded in the crate (src/testkit/data.rs), generated and
checked against spec/ by the crate’s test tests/testkit_data.rs.
Structs§
- Fixtures
- What the resolver under test is loaded with. All bytes are canonical JSON (JCS).
- Kit
- The resolver test kit: the fixtures and the checks. See the module documentation.
- Recording
- A
Resolverthat forwards to another and records each call, in order. - Report
- The failures of a check, one line each:
<check>: <case>: <what>, where<check>islazy_calls,unavailable,bytes,asof(orsetup, if the embedded fixtures could not be read, which the crate’s tests rule out). - Version
- A version of a stored cell: from
txon, the cell’s value is that of the receipt.