Files
wifi-densepose/vendor/ruvector/crates/ruQu/tests/integration_tests.rs

536 lines
16 KiB
Rust

//! End-to-end integration tests for ruQu coherence gate
//!
//! Tests full fabric initialization, syndrome ingestion through gate decision,
//! and receipt generation with verification.
use ruqu::{
filters::{
EvidenceConfig, FilterConfig, FilterPipeline, ShiftConfig, StructuralConfig, Verdict,
},
prelude::*,
syndrome::{DetectorBitmap, SyndromeBuffer, SyndromeDelta, SyndromeRound},
tile::{
GateDecision, GateThresholds, PermitToken, ReceiptLog, SyndromeDelta as TileSyndromeDelta,
TileReport, TileZero, WorkerTile,
},
TILE_COUNT, WORKER_TILE_COUNT,
};
// ============================================================================
// Full Fabric Initialization Tests
// ============================================================================
#[test]
fn test_fabric_initialization_all_tiles() {
// Create all 255 worker tiles
let workers: Vec<WorkerTile> = (1..=255).map(WorkerTile::new).collect();
assert_eq!(workers.len(), WORKER_TILE_COUNT);
for (i, worker) in workers.iter().enumerate() {
assert_eq!(worker.tile_id, (i + 1) as u8);
assert_eq!(worker.tick, 0);
}
}
#[test]
fn test_fabric_initialization_with_tilezero() {
let thresholds = GateThresholds::default();
let tilezero = TileZero::new(thresholds);
// Verify default thresholds
assert!(tilezero.thresholds.structural_min_cut > 0.0);
assert!(tilezero.thresholds.shift_max > 0.0);
assert!(tilezero.thresholds.tau_deny > 0.0);
assert!(tilezero.thresholds.tau_permit > tilezero.thresholds.tau_deny);
assert!(tilezero.receipt_log.is_empty());
}
#[test]
fn test_fabric_tile_count_matches_constants() {
assert_eq!(TILE_COUNT, 256);
assert_eq!(WORKER_TILE_COUNT, 255);
}
// ============================================================================
// Syndrome Ingestion Through Gate Decision Tests
// ============================================================================
#[test]
fn test_syndrome_ingestion_single_round() {
let mut worker = WorkerTile::new(1);
// Ingest a syndrome
let delta = TileSyndromeDelta::new(0, 1, 50);
let report = worker.tick(&delta);
assert_eq!(report.tile_id, 1);
assert_eq!(report.tick, 1);
assert!(report.status & TileReport::STATUS_VALID != 0);
}
#[test]
fn test_syndrome_ingestion_multiple_rounds() {
let mut worker = WorkerTile::new(1);
// Process multiple syndrome rounds
for i in 0..100 {
let delta = TileSyndromeDelta::new(i as u16 % 64, (i as u16 + 1) % 64, (i % 256) as u16);
let report = worker.tick(&delta);
assert_eq!(report.tick, i + 1);
}
assert_eq!(worker.tick, 100);
}
#[test]
fn test_full_pipeline_syndrome_to_decision_safe() {
// Setup tiles
let thresholds = GateThresholds {
structural_min_cut: 2.0,
shift_max: 0.7,
tau_deny: 0.01,
tau_permit: 50.0,
permit_ttl_ns: 4_000_000,
};
let mut tilezero = TileZero::new(thresholds);
// Create workers and process syndromes
let mut workers: Vec<WorkerTile> = (1..=10).map(WorkerTile::new).collect();
// Build graph with good connectivity
for worker in &mut workers {
// Add edges to create a well-connected graph
worker.patch_graph.add_edge(0, 1, 100);
worker.patch_graph.add_edge(1, 2, 100);
worker.patch_graph.add_edge(2, 3, 100);
worker.patch_graph.add_edge(3, 0, 100);
worker.patch_graph.recompute_components();
}
// Process syndromes with low values (indicating stability)
for _ in 0..50 {
for worker in &mut workers {
let delta = TileSyndromeDelta::new(0, 1, 50); // Low syndrome value
worker.tick(&delta);
}
}
// Collect reports
let reports: Vec<TileReport> = workers
.iter()
.map(|w| {
let mut report = TileReport::new(w.tile_id);
report.local_cut = 10.0; // Good cut value
report.shift_score = 0.1; // Low shift
report.e_value = 200.0; // Strong evidence
report
})
.collect();
let decision = tilezero.merge_reports(reports);
assert_eq!(decision, GateDecision::Permit);
}
#[test]
fn test_full_pipeline_syndrome_to_decision_unsafe() {
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
// Create reports indicating structural problems
let reports: Vec<TileReport> = (1..=10)
.map(|i| {
let mut report = TileReport::new(i);
report.local_cut = 1.0; // Below threshold (5.0)
report.shift_score = 0.1;
report.e_value = 200.0;
report
})
.collect();
let decision = tilezero.merge_reports(reports);
assert_eq!(decision, GateDecision::Deny);
}
#[test]
fn test_full_pipeline_syndrome_to_decision_cautious() {
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
// Create reports with high shift but good structure
let reports: Vec<TileReport> = (1..=10)
.map(|i| {
let mut report = TileReport::new(i);
report.local_cut = 10.0;
report.shift_score = 0.8; // Above threshold (0.5)
report.e_value = 200.0;
report
})
.collect();
let decision = tilezero.merge_reports(reports);
assert_eq!(decision, GateDecision::Defer);
}
// ============================================================================
// GateDecision Variants Tests
// ============================================================================
#[test]
fn test_gate_decision_safe_variant() {
let decision = GateDecision::Permit;
assert!(decision.is_permit());
assert!(!decision.is_deny());
}
#[test]
fn test_gate_decision_cautious_variant() {
let decision = GateDecision::Defer;
assert!(!decision.is_permit());
assert!(!decision.is_deny());
}
#[test]
fn test_gate_decision_unsafe_variant() {
let decision = GateDecision::Deny;
assert!(!decision.is_permit());
assert!(decision.is_deny());
}
#[test]
fn test_gate_decision_all_variants_distinct() {
let permit = GateDecision::Permit;
let defer = GateDecision::Defer;
let deny = GateDecision::Deny;
assert_ne!(permit, defer);
assert_ne!(permit, deny);
assert_ne!(defer, deny);
}
// ============================================================================
// Receipt Generation and Verification Tests
// ============================================================================
#[test]
fn test_receipt_generation_on_decision() {
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
// Make a decision
let reports: Vec<TileReport> = (1..=5)
.map(|i| {
let mut report = TileReport::new(i);
report.local_cut = 10.0;
report.shift_score = 0.1;
report.e_value = 200.0;
report
})
.collect();
tilezero.merge_reports(reports);
// Verify receipt was created
assert_eq!(tilezero.receipt_log.len(), 1);
}
#[test]
fn test_receipt_chain_integrity() {
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
// Make multiple decisions
for _ in 0..10 {
let reports: Vec<TileReport> = (1..=3)
.map(|i| {
let mut report = TileReport::new(i);
report.local_cut = 10.0;
report.shift_score = 0.1;
report.e_value = 200.0;
report
})
.collect();
tilezero.merge_reports(reports);
}
// Verify chain
assert_eq!(tilezero.receipt_log.len(), 10);
// Check that entries are chainable by looking up sequences
for i in 0..10 {
let entry = tilezero.receipt_log.get(i as u64);
assert!(entry.is_some());
assert_eq!(entry.unwrap().sequence, i as u64);
}
}
#[test]
fn test_permit_token_issuance() {
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
// Create reports for permit
let reports: Vec<TileReport> = (1..=5)
.map(|i| {
let mut report = TileReport::new(i);
report.local_cut = 10.0;
report.shift_score = 0.1;
report.e_value = 200.0;
report
})
.collect();
let decision = tilezero.merge_reports(reports);
assert_eq!(decision, GateDecision::Permit);
let token = tilezero.issue_permit(&decision);
assert_eq!(token.decision, GateDecision::Permit);
assert!(token.ttl_ns > 0);
}
#[test]
fn test_permit_token_validity_window() {
let token = PermitToken {
decision: GateDecision::Permit,
sequence: 0,
timestamp: 1_000_000,
ttl_ns: 500_000,
witness_hash: [0u8; 32],
signature: [1u8; 64], // Non-zero placeholder
};
// Within validity window
assert!(token.is_valid(1_200_000));
assert!(token.is_valid(1_499_999));
// Outside validity window
assert!(!token.is_valid(1_500_001));
assert!(!token.is_valid(2_000_000));
}
// ============================================================================
// Integration with Filter Pipeline Tests
// ============================================================================
#[test]
fn test_filter_pipeline_integration_permit() {
let config = FilterConfig {
structural: StructuralConfig {
threshold: 1.0,
use_subpolynomial: false,
..Default::default()
},
shift: ShiftConfig {
threshold: 0.5,
..Default::default()
},
evidence: EvidenceConfig {
tau_permit: 5.0,
tau_deny: 0.2,
..Default::default()
},
};
let mut pipeline = FilterPipeline::new(config);
// Build strong graph
pipeline.structural_mut().insert_edge(1, 2, 2.0).unwrap();
pipeline.structural_mut().insert_edge(2, 3, 2.0).unwrap();
pipeline.structural_mut().insert_edge(3, 1, 2.0).unwrap();
// Add stable observations
for _ in 0..20 {
pipeline.shift_mut().update(0, 0.5);
}
// Add strong evidence
for _ in 0..5 {
pipeline.evidence_mut().update(2.0);
}
let state = ruqu::filters::SystemState::new(3);
let result = pipeline.evaluate(&state);
assert_eq!(result.verdict, Some(Verdict::Permit));
}
#[test]
fn test_filter_pipeline_integration_deny() {
let config = FilterConfig {
structural: StructuralConfig {
threshold: 5.0,
use_subpolynomial: false,
..Default::default()
},
..Default::default()
};
let mut pipeline = FilterPipeline::new(config);
// Build weak graph
pipeline.structural_mut().insert_edge(1, 2, 1.0).unwrap();
let state = ruqu::filters::SystemState::new(2);
let result = pipeline.evaluate(&state);
assert_eq!(result.verdict, Some(Verdict::Deny));
}
// ============================================================================
// End-to-End Workflow Tests
// ============================================================================
#[test]
fn test_complete_workflow_healthy_system() {
// 1. Initialize fabric
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
let mut workers: Vec<WorkerTile> = (1..=5).map(WorkerTile::new).collect();
// 2. Build graph structure in each worker
for worker in &mut workers {
worker.patch_graph.add_edge(0, 1, 200);
worker.patch_graph.add_edge(1, 2, 200);
worker.patch_graph.add_edge(2, 0, 200);
worker.patch_graph.recompute_components();
}
// 3. Simulate syndrome stream
for cycle in 0..50 {
for worker in &mut workers {
let delta = TileSyndromeDelta::new(
(cycle % 3) as u16,
((cycle + 1) % 3) as u16,
50, // Low syndrome value
);
worker.tick(&delta);
}
}
// 4. Collect reports and make decision
let reports: Vec<TileReport> = workers
.iter()
.map(|w| {
let mut report = TileReport::new(w.tile_id);
report.local_cut = w.local_cut_state.cut_value.max(10.0);
report.shift_score = 0.1;
report.e_value = 200.0;
report
})
.collect();
let decision = tilezero.merge_reports(reports);
// 5. Verify outcome
assert_eq!(decision, GateDecision::Permit);
assert_eq!(tilezero.receipt_log.len(), 1);
// 6. Issue and verify permit
let token = tilezero.issue_permit(&decision);
assert_eq!(token.decision, GateDecision::Permit);
}
#[test]
fn test_complete_workflow_degrading_system() {
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
// Simulate degradation over time
for cycle in 0..20 {
let cut_value = 10.0 - (cycle as f64 * 0.5); // Degrading cut
let reports: Vec<TileReport> = (1..=5)
.map(|i| {
let mut report = TileReport::new(i);
report.local_cut = cut_value;
report.shift_score = 0.1 + (cycle as f64 * 0.02);
report.e_value = 200.0 / (cycle as f64 + 1.0);
report
})
.collect();
let decision = tilezero.merge_reports(reports);
// Eventually should transition from Permit -> Defer -> Deny
if cut_value < thresholds.structural_min_cut {
assert_eq!(decision, GateDecision::Deny);
}
}
// Should have logged all decisions
assert_eq!(tilezero.receipt_log.len(), 20);
}
// ============================================================================
// Proptest Property-Based Tests
// ============================================================================
#[cfg(test)]
mod proptest_integration {
use super::*;
use proptest::prelude::*;
proptest! {
#![proptest_config(ProptestConfig::with_cases(100))]
#[test]
fn prop_decision_consistency(
cut_values in prop::collection::vec(0.0f64..20.0, 1..10),
shift_values in prop::collection::vec(0.0f64..1.0, 1..10),
e_values in prop::collection::vec(0.01f64..500.0, 1..10),
) {
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
let reports: Vec<TileReport> = cut_values
.iter()
.zip(shift_values.iter())
.zip(e_values.iter())
.enumerate()
.map(|(i, ((cut, shift), e_val))| {
let mut report = TileReport::new((i + 1) as u8);
report.local_cut = *cut;
report.shift_score = *shift;
report.e_value = *e_val;
report
})
.collect();
let decision = tilezero.merge_reports(reports.clone());
// Verify decision is consistent with filters
let min_cut: f64 = reports.iter().map(|r| r.local_cut).filter(|c| *c > 0.0).fold(f64::MAX, |a, b| a.min(b));
let max_shift: f64 = reports.iter().map(|r| r.shift_score).fold(0.0, |a, b| a.max(b));
if min_cut < thresholds.structural_min_cut {
prop_assert_eq!(decision, GateDecision::Deny);
} else if max_shift >= thresholds.shift_max {
prop_assert_eq!(decision, GateDecision::Defer);
}
}
#[test]
fn prop_receipt_log_always_grows(num_decisions in 1usize..50) {
let thresholds = GateThresholds::default();
let mut tilezero = TileZero::new(thresholds);
for _ in 0..num_decisions {
let reports: Vec<TileReport> = (1..=3)
.map(|i| {
let mut report = TileReport::new(i);
report.local_cut = 10.0;
report.shift_score = 0.1;
report.e_value = 200.0;
report
})
.collect();
tilezero.merge_reports(reports);
}
prop_assert_eq!(tilezero.receipt_log.len(), num_decisions);
}
}
}