Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
This commit is contained in:
665
crates/cognitum-gate-tilezero/tests_disabled/replay_tests.rs
Normal file
665
crates/cognitum-gate-tilezero/tests_disabled/replay_tests.rs
Normal file
@@ -0,0 +1,665 @@
|
||||
//! Comprehensive tests for deterministic replay
|
||||
//!
|
||||
//! Tests cover:
|
||||
//! - Replay engine creation and configuration
|
||||
//! - Checkpoint management
|
||||
//! - Decision replay and verification
|
||||
//! - Security tests (ensuring determinism)
|
||||
|
||||
use cognitum_gate_tilezero::replay::{
|
||||
ReplayDifference, ReplayEngine, ReplayError, ReplayResult, SequenceVerification,
|
||||
StateSnapshot, TileSnapshot,
|
||||
};
|
||||
use cognitum_gate_tilezero::receipt::{
|
||||
EvidentialWitness, PredictiveWitness, StructuralWitness, TimestampProof, WitnessReceipt,
|
||||
WitnessSummary,
|
||||
};
|
||||
use cognitum_gate_tilezero::permit::PermitToken;
|
||||
use cognitum_gate_tilezero::GateDecision;
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn create_test_receipt(
|
||||
sequence: u64,
|
||||
decision: GateDecision,
|
||||
witness: WitnessSummary,
|
||||
) -> WitnessReceipt {
|
||||
WitnessReceipt {
|
||||
sequence,
|
||||
token: PermitToken {
|
||||
decision,
|
||||
action_id: format!("action-{}", sequence),
|
||||
timestamp: 1000000000 + sequence * 1000,
|
||||
ttl_ns: 60_000_000_000,
|
||||
witness_hash: [0u8; 32],
|
||||
sequence,
|
||||
signature: [0u8; 64],
|
||||
},
|
||||
previous_hash: [0u8; 32],
|
||||
witness_summary: witness,
|
||||
timestamp_proof: TimestampProof {
|
||||
timestamp: 1000000000 + sequence * 1000,
|
||||
previous_receipt_hash: [0u8; 32],
|
||||
merkle_root: [0u8; 32],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn create_permit_witness() -> WitnessSummary {
|
||||
WitnessSummary {
|
||||
structural: StructuralWitness {
|
||||
cut_value: 10.0,
|
||||
partition: "stable".to_string(),
|
||||
critical_edges: 2,
|
||||
boundary: vec![],
|
||||
},
|
||||
predictive: PredictiveWitness {
|
||||
set_size: 5,
|
||||
coverage: 0.9,
|
||||
},
|
||||
evidential: EvidentialWitness {
|
||||
e_value: 150.0,
|
||||
verdict: "accept".to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn create_defer_witness() -> WitnessSummary {
|
||||
WitnessSummary {
|
||||
structural: StructuralWitness {
|
||||
cut_value: 10.0,
|
||||
partition: "stable".to_string(),
|
||||
critical_edges: 5,
|
||||
boundary: vec![],
|
||||
},
|
||||
predictive: PredictiveWitness {
|
||||
set_size: 25, // Large set size -> defer
|
||||
coverage: 0.9,
|
||||
},
|
||||
evidential: EvidentialWitness {
|
||||
e_value: 50.0,
|
||||
verdict: "continue".to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn create_deny_witness() -> WitnessSummary {
|
||||
WitnessSummary {
|
||||
structural: StructuralWitness {
|
||||
cut_value: 2.0,
|
||||
partition: "fragile".to_string(), // Fragile -> deny
|
||||
critical_edges: 10,
|
||||
boundary: vec![],
|
||||
},
|
||||
predictive: PredictiveWitness {
|
||||
set_size: 5,
|
||||
coverage: 0.9,
|
||||
},
|
||||
evidential: EvidentialWitness {
|
||||
e_value: 0.001,
|
||||
verdict: "reject".to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod engine_creation {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_default_engine() {
|
||||
let engine = ReplayEngine::default();
|
||||
assert_eq!(engine.checkpoint_count(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_engine_with_interval() {
|
||||
let engine = ReplayEngine::new(50);
|
||||
assert_eq!(engine.checkpoint_count(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod checkpoint_management {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_save_checkpoint() {
|
||||
let mut engine = ReplayEngine::new(10);
|
||||
|
||||
let snapshot = StateSnapshot {
|
||||
sequence: 0,
|
||||
timestamp: 1000,
|
||||
global_min_cut: 10.0,
|
||||
aggregate_e_value: 100.0,
|
||||
min_coherence: 256,
|
||||
tile_states: HashMap::new(),
|
||||
};
|
||||
|
||||
engine.save_checkpoint(0, snapshot);
|
||||
assert_eq!(engine.checkpoint_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_checkpoint_at_interval() {
|
||||
let mut engine = ReplayEngine::new(10);
|
||||
|
||||
// Checkpoint at 0, 10, 20 should be saved
|
||||
for seq in [0, 5, 10, 15, 20] {
|
||||
let snapshot = StateSnapshot {
|
||||
sequence: seq,
|
||||
timestamp: 1000 + seq,
|
||||
global_min_cut: 10.0,
|
||||
aggregate_e_value: 100.0,
|
||||
min_coherence: 256,
|
||||
tile_states: HashMap::new(),
|
||||
};
|
||||
engine.save_checkpoint(seq, snapshot);
|
||||
}
|
||||
|
||||
// Only 0, 10, 20 should be saved (multiples of 10)
|
||||
assert_eq!(engine.checkpoint_count(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find_nearest_checkpoint() {
|
||||
let mut engine = ReplayEngine::new(10);
|
||||
|
||||
for seq in [0, 10, 20] {
|
||||
let snapshot = StateSnapshot {
|
||||
sequence: seq,
|
||||
timestamp: 1000 + seq,
|
||||
global_min_cut: seq as f64,
|
||||
aggregate_e_value: 100.0,
|
||||
min_coherence: 256,
|
||||
tile_states: HashMap::new(),
|
||||
};
|
||||
engine.save_checkpoint(seq, snapshot);
|
||||
}
|
||||
|
||||
// Find nearest for 15 -> should be 10
|
||||
let (found_seq, snapshot) = engine.find_nearest_checkpoint(15).unwrap();
|
||||
assert_eq!(found_seq, 10);
|
||||
assert_eq!(snapshot.global_min_cut, 10.0);
|
||||
|
||||
// Find nearest for 25 -> should be 20
|
||||
let (found_seq, _) = engine.find_nearest_checkpoint(25).unwrap();
|
||||
assert_eq!(found_seq, 20);
|
||||
|
||||
// Find nearest for 5 -> should be 0
|
||||
let (found_seq, _) = engine.find_nearest_checkpoint(5).unwrap();
|
||||
assert_eq!(found_seq, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_checkpoint_found() {
|
||||
let engine = ReplayEngine::new(10);
|
||||
assert!(engine.find_nearest_checkpoint(5).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_prune_checkpoints() {
|
||||
let mut engine = ReplayEngine::new(10);
|
||||
|
||||
for seq in [0, 10, 20, 30, 40, 50] {
|
||||
let snapshot = StateSnapshot {
|
||||
sequence: seq,
|
||||
timestamp: 1000 + seq,
|
||||
global_min_cut: 10.0,
|
||||
aggregate_e_value: 100.0,
|
||||
min_coherence: 256,
|
||||
tile_states: HashMap::new(),
|
||||
};
|
||||
engine.save_checkpoint(seq, snapshot);
|
||||
}
|
||||
|
||||
assert_eq!(engine.checkpoint_count(), 6);
|
||||
|
||||
engine.prune_before(30);
|
||||
|
||||
assert_eq!(engine.checkpoint_count(), 3); // 30, 40, 50 remain
|
||||
assert!(engine.find_nearest_checkpoint(20).is_none());
|
||||
assert!(engine.find_nearest_checkpoint(30).is_some());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod decision_replay {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_replay_permit() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let receipt = create_test_receipt(0, GateDecision::Permit, create_permit_witness());
|
||||
|
||||
let result = engine.replay(&receipt);
|
||||
|
||||
assert!(result.matched);
|
||||
assert_eq!(result.decision, GateDecision::Permit);
|
||||
assert_eq!(result.original_decision, GateDecision::Permit);
|
||||
assert!(result.differences.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replay_defer() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let receipt = create_test_receipt(0, GateDecision::Defer, create_defer_witness());
|
||||
|
||||
let result = engine.replay(&receipt);
|
||||
|
||||
assert!(result.matched);
|
||||
assert_eq!(result.decision, GateDecision::Defer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replay_deny() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let receipt = create_test_receipt(0, GateDecision::Deny, create_deny_witness());
|
||||
|
||||
let result = engine.replay(&receipt);
|
||||
|
||||
assert!(result.matched);
|
||||
assert_eq!(result.decision, GateDecision::Deny);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replay_mismatch() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
|
||||
// Create a receipt where the decision doesn't match the witness
|
||||
// Witness indicates DENY (fragile partition), but token says PERMIT
|
||||
let receipt = create_test_receipt(0, GateDecision::Permit, create_deny_witness());
|
||||
|
||||
let result = engine.replay(&receipt);
|
||||
|
||||
assert!(!result.matched);
|
||||
assert_eq!(result.decision, GateDecision::Deny); // Reconstructed from witness
|
||||
assert_eq!(result.original_decision, GateDecision::Permit); // From token
|
||||
assert!(!result.differences.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replay_preserves_snapshot() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let witness = create_permit_witness();
|
||||
let receipt = create_test_receipt(0, GateDecision::Permit, witness.clone());
|
||||
|
||||
let result = engine.replay(&receipt);
|
||||
|
||||
assert_eq!(result.state_snapshot.structural.cut_value, witness.structural.cut_value);
|
||||
assert_eq!(result.state_snapshot.evidential.e_value, witness.evidential.e_value);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod sequence_verification {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_verify_empty_sequence() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let verification = engine.verify_sequence(&[]);
|
||||
|
||||
assert_eq!(verification.total_receipts, 0);
|
||||
assert!(verification.all_matched);
|
||||
assert_eq!(verification.mismatch_count(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_single_receipt() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let receipts = vec![create_test_receipt(0, GateDecision::Permit, create_permit_witness())];
|
||||
|
||||
let verification = engine.verify_sequence(&receipts);
|
||||
|
||||
assert_eq!(verification.total_receipts, 1);
|
||||
assert!(verification.all_matched);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_multiple_receipts() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let receipts = vec![
|
||||
create_test_receipt(0, GateDecision::Permit, create_permit_witness()),
|
||||
create_test_receipt(1, GateDecision::Defer, create_defer_witness()),
|
||||
create_test_receipt(2, GateDecision::Deny, create_deny_witness()),
|
||||
];
|
||||
|
||||
let verification = engine.verify_sequence(&receipts);
|
||||
|
||||
assert_eq!(verification.total_receipts, 3);
|
||||
assert!(verification.all_matched);
|
||||
assert_eq!(verification.mismatch_count(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_with_mismatches() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let receipts = vec![
|
||||
create_test_receipt(0, GateDecision::Permit, create_permit_witness()),
|
||||
create_test_receipt(1, GateDecision::Permit, create_deny_witness()), // Mismatch!
|
||||
create_test_receipt(2, GateDecision::Deny, create_deny_witness()),
|
||||
];
|
||||
|
||||
let verification = engine.verify_sequence(&receipts);
|
||||
|
||||
assert_eq!(verification.total_receipts, 3);
|
||||
assert!(!verification.all_matched);
|
||||
assert_eq!(verification.mismatch_count(), 1);
|
||||
|
||||
let mismatches: Vec<_> = verification.mismatches().collect();
|
||||
assert_eq!(mismatches.len(), 1);
|
||||
assert_eq!(mismatches[0].0, 1); // Sequence 1 mismatched
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mismatches_iterator() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let receipts = vec![
|
||||
create_test_receipt(0, GateDecision::Permit, create_deny_witness()), // Mismatch
|
||||
create_test_receipt(1, GateDecision::Permit, create_permit_witness()),
|
||||
create_test_receipt(2, GateDecision::Defer, create_deny_witness()), // Mismatch
|
||||
];
|
||||
|
||||
let verification = engine.verify_sequence(&receipts);
|
||||
let mismatches: Vec<_> = verification.mismatches().collect();
|
||||
|
||||
assert_eq!(mismatches.len(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod checkpoint_export_import {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_export_checkpoint() {
|
||||
let mut engine = ReplayEngine::new(10);
|
||||
|
||||
let snapshot = StateSnapshot {
|
||||
sequence: 0,
|
||||
timestamp: 1000,
|
||||
global_min_cut: 15.0,
|
||||
aggregate_e_value: 200.0,
|
||||
min_coherence: 512,
|
||||
tile_states: HashMap::new(),
|
||||
};
|
||||
|
||||
engine.save_checkpoint(0, snapshot);
|
||||
|
||||
let exported = engine.export_checkpoint(0);
|
||||
assert!(exported.is_some());
|
||||
|
||||
let data = exported.unwrap();
|
||||
assert!(!data.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_export_nonexistent() {
|
||||
let engine = ReplayEngine::new(10);
|
||||
assert!(engine.export_checkpoint(0).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_checkpoint() {
|
||||
let mut engine1 = ReplayEngine::new(10);
|
||||
|
||||
let snapshot = StateSnapshot {
|
||||
sequence: 0,
|
||||
timestamp: 1000,
|
||||
global_min_cut: 25.0,
|
||||
aggregate_e_value: 300.0,
|
||||
min_coherence: 768,
|
||||
tile_states: HashMap::new(),
|
||||
};
|
||||
|
||||
engine1.save_checkpoint(0, snapshot);
|
||||
let exported = engine1.export_checkpoint(0).unwrap();
|
||||
|
||||
let mut engine2 = ReplayEngine::new(10);
|
||||
assert!(engine2.import_checkpoint(0, &exported).is_ok());
|
||||
assert_eq!(engine2.checkpoint_count(), 1);
|
||||
|
||||
let (_, imported) = engine2.find_nearest_checkpoint(0).unwrap();
|
||||
assert_eq!(imported.global_min_cut, 25.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_import_invalid_data() {
|
||||
let mut engine = ReplayEngine::new(10);
|
||||
let result = engine.import_checkpoint(0, b"invalid json");
|
||||
assert!(matches!(result, Err(ReplayError::InvalidCheckpoint)));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tile_snapshot {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_tile_snapshot_in_state() {
|
||||
let mut tile_states = HashMap::new();
|
||||
tile_states.insert(
|
||||
1,
|
||||
TileSnapshot {
|
||||
tile_id: 1,
|
||||
coherence: 256,
|
||||
e_value: 10.0,
|
||||
boundary_edges: 5,
|
||||
},
|
||||
);
|
||||
tile_states.insert(
|
||||
2,
|
||||
TileSnapshot {
|
||||
tile_id: 2,
|
||||
coherence: 512,
|
||||
e_value: 20.0,
|
||||
boundary_edges: 3,
|
||||
},
|
||||
);
|
||||
|
||||
let snapshot = StateSnapshot {
|
||||
sequence: 0,
|
||||
timestamp: 1000,
|
||||
global_min_cut: 10.0,
|
||||
aggregate_e_value: 100.0,
|
||||
min_coherence: 256,
|
||||
tile_states,
|
||||
};
|
||||
|
||||
assert_eq!(snapshot.tile_states.len(), 2);
|
||||
assert_eq!(snapshot.tile_states.get(&1).unwrap().coherence, 256);
|
||||
assert_eq!(snapshot.tile_states.get(&2).unwrap().e_value, 20.0);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod replay_difference {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_difference_structure() {
|
||||
let diff = ReplayDifference {
|
||||
field: "decision".to_string(),
|
||||
original: "permit".to_string(),
|
||||
replayed: "deny".to_string(),
|
||||
};
|
||||
|
||||
assert_eq!(diff.field, "decision");
|
||||
assert_eq!(diff.original, "permit");
|
||||
assert_eq!(diff.replayed, "deny");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod determinism {
|
||||
use super::*;
|
||||
|
||||
/// Test that replaying the same receipt always produces the same result
|
||||
#[test]
|
||||
fn test_replay_deterministic() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let receipt = create_test_receipt(0, GateDecision::Permit, create_permit_witness());
|
||||
|
||||
let result1 = engine.replay(&receipt);
|
||||
let result2 = engine.replay(&receipt);
|
||||
|
||||
assert_eq!(result1.decision, result2.decision);
|
||||
assert_eq!(result1.matched, result2.matched);
|
||||
assert_eq!(result1.differences.len(), result2.differences.len());
|
||||
}
|
||||
|
||||
/// Test that different engines produce same results
|
||||
#[test]
|
||||
fn test_cross_engine_determinism() {
|
||||
let engine1 = ReplayEngine::new(100);
|
||||
let engine2 = ReplayEngine::new(50); // Different checkpoint interval
|
||||
|
||||
let receipt = create_test_receipt(0, GateDecision::Defer, create_defer_witness());
|
||||
|
||||
let result1 = engine1.replay(&receipt);
|
||||
let result2 = engine2.replay(&receipt);
|
||||
|
||||
assert_eq!(result1.decision, result2.decision);
|
||||
assert_eq!(result1.matched, result2.matched);
|
||||
}
|
||||
|
||||
/// Test sequence verification is deterministic
|
||||
#[test]
|
||||
fn test_sequence_verification_deterministic() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let receipts = vec![
|
||||
create_test_receipt(0, GateDecision::Permit, create_permit_witness()),
|
||||
create_test_receipt(1, GateDecision::Deny, create_deny_witness()),
|
||||
];
|
||||
|
||||
let v1 = engine.verify_sequence(&receipts);
|
||||
let v2 = engine.verify_sequence(&receipts);
|
||||
|
||||
assert_eq!(v1.total_receipts, v2.total_receipts);
|
||||
assert_eq!(v1.all_matched, v2.all_matched);
|
||||
assert_eq!(v1.mismatch_count(), v2.mismatch_count());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod security_tests {
|
||||
use super::*;
|
||||
|
||||
/// Test that modified witness produces different replay result
|
||||
#[test]
|
||||
fn test_witness_tampering_detected() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
|
||||
let original = create_test_receipt(0, GateDecision::Permit, create_permit_witness());
|
||||
let original_result = engine.replay(&original);
|
||||
|
||||
// Create tampered receipt with modified witness
|
||||
let mut tampered_witness = create_permit_witness();
|
||||
tampered_witness.structural.partition = "fragile".to_string();
|
||||
let tampered = create_test_receipt(0, GateDecision::Permit, tampered_witness);
|
||||
let tampered_result = engine.replay(&tampered);
|
||||
|
||||
// Tampered one should fail replay
|
||||
assert!(original_result.matched);
|
||||
assert!(!tampered_result.matched);
|
||||
}
|
||||
|
||||
/// Test audit trail completeness
|
||||
#[test]
|
||||
fn test_audit_trail() {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let mut receipts = Vec::new();
|
||||
|
||||
// Build a sequence of decisions
|
||||
for i in 0..10 {
|
||||
let witness = if i % 3 == 0 {
|
||||
create_permit_witness()
|
||||
} else if i % 3 == 1 {
|
||||
create_defer_witness()
|
||||
} else {
|
||||
create_deny_witness()
|
||||
};
|
||||
|
||||
let decision = if i % 3 == 0 {
|
||||
GateDecision::Permit
|
||||
} else if i % 3 == 1 {
|
||||
GateDecision::Defer
|
||||
} else {
|
||||
GateDecision::Deny
|
||||
};
|
||||
|
||||
receipts.push(create_test_receipt(i, decision, witness));
|
||||
}
|
||||
|
||||
let verification = engine.verify_sequence(&receipts);
|
||||
|
||||
// All should match since we built them consistently
|
||||
assert!(verification.all_matched);
|
||||
assert_eq!(verification.total_receipts, 10);
|
||||
}
|
||||
}
|
||||
|
||||
// Property-based tests
|
||||
#[cfg(test)]
|
||||
mod property_tests {
|
||||
use super::*;
|
||||
use proptest::prelude::*;
|
||||
|
||||
proptest! {
|
||||
#[test]
|
||||
fn prop_replay_always_produces_result(sequence in 0u64..1000) {
|
||||
let engine = ReplayEngine::new(100);
|
||||
let receipt = create_test_receipt(
|
||||
sequence,
|
||||
GateDecision::Permit,
|
||||
create_permit_witness()
|
||||
);
|
||||
|
||||
let result = engine.replay(&receipt);
|
||||
// Should always produce a valid result
|
||||
assert!(result.decision == GateDecision::Permit ||
|
||||
result.decision == GateDecision::Defer ||
|
||||
result.decision == GateDecision::Deny);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prop_checkpoint_interval_works(interval in 1u64..100) {
|
||||
let mut engine = ReplayEngine::new(interval);
|
||||
|
||||
for seq in 0..interval * 3 {
|
||||
let snapshot = StateSnapshot {
|
||||
sequence: seq,
|
||||
timestamp: 1000 + seq,
|
||||
global_min_cut: 10.0,
|
||||
aggregate_e_value: 100.0,
|
||||
min_coherence: 256,
|
||||
tile_states: HashMap::new(),
|
||||
};
|
||||
engine.save_checkpoint(seq, snapshot);
|
||||
}
|
||||
|
||||
// Should have saved at least 3 checkpoints
|
||||
assert!(engine.checkpoint_count() >= 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prop_matching_decisions_have_empty_differences(seq in 0u64..100) {
|
||||
let engine = ReplayEngine::new(100);
|
||||
|
||||
// Create receipts where decision matches witness
|
||||
let receipts = vec![
|
||||
(GateDecision::Permit, create_permit_witness()),
|
||||
(GateDecision::Defer, create_defer_witness()),
|
||||
(GateDecision::Deny, create_deny_witness()),
|
||||
];
|
||||
|
||||
for (decision, witness) in receipts {
|
||||
let receipt = create_test_receipt(seq, decision, witness);
|
||||
let result = engine.replay(&receipt);
|
||||
if result.matched {
|
||||
assert!(result.differences.is_empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user