Skip to main content

trellis_testing/
oracle.rs

1use std::fmt::Debug;
2
3/// Application-owned full-recompute oracle for a Trellis graph wrapper.
4pub trait FullRecomputeOracle<G> {
5    /// Canonical application inputs used by full recompute.
6    type CanonicalInputs;
7    /// Comparable state observed from full recompute and incremental graph state.
8    type ExpectedState: Clone + Debug + PartialEq;
9
10    /// Computes expected state from canonical application truth.
11    fn recompute(inputs: &Self::CanonicalInputs) -> Self::ExpectedState;
12
13    /// Observes the equivalent state from the incremental graph or wrapper.
14    fn observe_incremental(graph: &G, inputs: &Self::CanonicalInputs) -> Self::ExpectedState;
15}
16
17/// Successful oracle comparison.
18#[derive(Clone, Debug, Eq, PartialEq)]
19pub struct OracleCheck<S> {
20    /// State produced by full recompute.
21    pub expected: S,
22    /// State observed from the incremental graph.
23    pub actual: S,
24}
25
26/// Full-recompute oracle mismatch.
27#[derive(Clone, Debug, Eq, PartialEq)]
28pub struct OracleMismatch<S> {
29    /// State produced by full recompute.
30    pub expected: S,
31    /// State observed from the incremental graph.
32    pub actual: S,
33}
34
35/// Asserts that incremental observation equals application full recompute.
36pub fn assert_incremental_equals_full<G, O>(
37    graph: &G,
38    inputs: &O::CanonicalInputs,
39) -> Result<OracleCheck<O::ExpectedState>, OracleMismatch<O::ExpectedState>>
40where
41    O: FullRecomputeOracle<G>,
42{
43    let expected = O::recompute(inputs);
44    let actual = O::observe_incremental(graph, inputs);
45    if expected == actual {
46        Ok(OracleCheck { expected, actual })
47    } else {
48        Err(OracleMismatch { expected, actual })
49    }
50}