//! Comprehensive integration tests for all 24 vendor-integrated WASM edge modules. //! //! ADR-041 Category 7: Tests cover initialization, basic operation, and edge cases //! for each module. At least 3 tests per module = 72+ tests total. //! //! Run with: //! cd v2 //! cargo test -p wifi-densepose-wasm-edge --features std -- --nocapture // ============================================================================ // Imports // ============================================================================ // Signal Intelligence use wifi_densepose_wasm_edge::sig_coherence_gate::{CoherenceGate, GateDecision}; use wifi_densepose_wasm_edge::sig_flash_attention::FlashAttention; use wifi_densepose_wasm_edge::sig_temporal_compress::TemporalCompressor; use wifi_densepose_wasm_edge::sig_sparse_recovery::{ SparseRecovery, EVENT_RECOVERY_COMPLETE, EVENT_DROPOUT_RATE, }; use wifi_densepose_wasm_edge::sig_mincut_person_match::PersonMatcher; use wifi_densepose_wasm_edge::sig_optimal_transport::{ OptimalTransportDetector, }; // Adaptive Learning use wifi_densepose_wasm_edge::lrn_dtw_gesture_learn::GestureLearner; use wifi_densepose_wasm_edge::lrn_anomaly_attractor::{ AttractorDetector, AttractorType, EVENT_BASIN_DEPARTURE, }; use wifi_densepose_wasm_edge::lrn_meta_adapt::MetaAdapter; use wifi_densepose_wasm_edge::lrn_ewc_lifelong::EwcLifelong; // Spatial Reasoning use wifi_densepose_wasm_edge::spt_pagerank_influence::PageRankInfluence; use wifi_densepose_wasm_edge::spt_micro_hnsw::{MicroHnsw, EVENT_NEAREST_MATCH_ID}; use wifi_densepose_wasm_edge::spt_spiking_tracker::{SpikingTracker, EVENT_SPIKE_RATE}; // Temporal Analysis use wifi_densepose_wasm_edge::tmp_pattern_sequence::PatternSequenceAnalyzer; use wifi_densepose_wasm_edge::tmp_temporal_logic_guard::{ TemporalLogicGuard, FrameInput, RuleState, }; use wifi_densepose_wasm_edge::tmp_goap_autonomy::GoapPlanner; // AI Security use wifi_densepose_wasm_edge::ais_prompt_shield::{PromptShield, EVENT_REPLAY_ATTACK}; use wifi_densepose_wasm_edge::ais_behavioral_profiler::{ BehavioralProfiler, EVENT_BEHAVIOR_ANOMALY, }; // Quantum-Inspired use wifi_densepose_wasm_edge::qnt_quantum_coherence::QuantumCoherenceMonitor; use wifi_densepose_wasm_edge::qnt_interference_search::{InterferenceSearch, Hypothesis}; // Autonomous Systems use wifi_densepose_wasm_edge::aut_psycho_symbolic::{ PsychoSymbolicEngine, EVENT_INFERENCE_RESULT, EVENT_RULE_FIRED, }; use wifi_densepose_wasm_edge::aut_self_healing_mesh::{ SelfHealingMesh, EVENT_COVERAGE_SCORE, EVENT_NODE_DEGRADED, }; // Exotic / Research use wifi_densepose_wasm_edge::exo_time_crystal::{TimeCrystalDetector, EVENT_CRYSTAL_DETECTED}; use wifi_densepose_wasm_edge::exo_hyperbolic_space::{ HyperbolicEmbedder, EVENT_HIERARCHY_LEVEL, EVENT_LOCATION_LABEL, }; // ============================================================================ // Test Data Generators // ============================================================================ /// Generate coherent phases (all subcarriers aligned). fn coherent_phases(n: usize, value: f32) -> Vec { vec![value; n] } /// Generate incoherent phases (spread across range). fn incoherent_phases(n: usize) -> Vec { (0..n) .map(|i| -3.14159 + (i as f32) * (6.28318 / n as f32)) .collect() } /// Generate sine wave amplitudes. fn sine_amplitudes(n: usize, amplitude: f32, period: usize) -> Vec { (0..n) .map(|i| { let t = (i as f32) * 2.0 * 3.14159 / (period as f32); amplitude * (1.0 + libm::sinf(t)) * 0.5 + 0.1 }) .collect() } /// Generate uniform amplitudes. fn uniform_amplitudes(n: usize, value: f32) -> Vec { vec![value; n] } /// Generate ramp amplitudes. fn ramp_amplitudes(n: usize, start: f32, end: f32) -> Vec { (0..n) .map(|i| start + (end - start) * (i as f32) / (n as f32 - 1.0)) .collect() } /// Generate variance pattern for multi-person tracking. fn person_variance_pattern(n: usize, pattern_id: usize) -> Vec { (0..n) .map(|i| { let base = (pattern_id as f32 + 1.0) * 0.3; base + 0.1 * libm::sinf(i as f32 * (pattern_id as f32 + 1.0) * 0.5) }) .collect() } /// Generate a normal FrameInput for temporal logic guard. fn normal_frame_input() -> FrameInput { FrameInput { presence: 1, n_persons: 1, motion_energy: 0.05, coherence: 0.8, breathing_bpm: 16.0, heartrate_bpm: 72.0, fall_alert: false, intrusion_alert: false, person_id_active: true, vital_signs_active: true, seizure_detected: false, normal_gait: true, } } // ============================================================================ // 1. Signal Intelligence -- sig_coherence_gate (3 tests) // ============================================================================ #[test] fn sig_coherence_gate_init() { let gate = CoherenceGate::new(); assert_eq!(gate.frame_count(), 0); assert_eq!(gate.gate(), GateDecision::Accept); } #[test] fn sig_coherence_gate_accepts_coherent_signal() { let mut gate = CoherenceGate::new(); let phases = coherent_phases(16, 0.5); for _ in 0..50 { gate.process_frame(&phases); } assert_eq!(gate.gate(), GateDecision::Accept); assert!( gate.coherence() > 0.7, "coherent signal should yield high coherence, got {}", gate.coherence() ); } #[test] fn sig_coherence_gate_coherence_drops_with_noisy_deltas() { let mut gate = CoherenceGate::new(); // Feed coherent signal (same phases each frame => zero deltas => coherence=1). let phases = coherent_phases(16, 0.5); for _ in 0..30 { gate.process_frame(&phases); } let coh_before = gate.coherence(); // Feed phases that CHANGE between frames to produce incoherent deltas. // Alternate between two different phase sets so the phase delta is spread. let phases_a: Vec = (0..16).map(|i| (i as f32) * 0.3).collect(); let phases_b: Vec = (0..16).map(|i| (i as f32) * -0.5 + 1.0).collect(); for frame in 0..100 { if frame % 2 == 0 { gate.process_frame(&phases_a); } else { gate.process_frame(&phases_b); } } let coh_after = gate.coherence(); // With non-uniform phase deltas, coherence should drop. assert!( coh_after < coh_before, "noisy phase deltas should lower coherence: before={}, after={}", coh_before, coh_after ); } // ============================================================================ // 2. Signal Intelligence -- sig_flash_attention (3 tests) // ============================================================================ #[test] fn sig_flash_attention_init() { let fa = FlashAttention::new(); assert_eq!(fa.frame_count(), 0); } #[test] fn sig_flash_attention_produces_weights() { let mut fa = FlashAttention::new(); let phases = coherent_phases(32, 0.3); let amps = sine_amplitudes(32, 5.0, 8); fa.process_frame(&phases, &s); fa.process_frame(&phases, &s); let w = fa.weights(); let sum: f32 = w.iter().sum(); assert!( (sum - 1.0).abs() < 0.1, "attention weights should sum to ~1.0, got {}", sum ); } #[test] fn sig_flash_attention_focused_activity() { let mut fa = FlashAttention::new(); let phases_a = coherent_phases(32, 0.1); let amps_a = uniform_amplitudes(32, 1.0); fa.process_frame(&phases_a, &s_a); let mut phases_b = coherent_phases(32, 0.1); for i in 0..4 { phases_b[i] = 1.5; } let amps_b = uniform_amplitudes(32, 1.0); for _ in 0..20 { fa.process_frame(&phases_b, &s_b); } let entropy = fa.entropy(); assert!( entropy < 2.5, "focused activity should lower entropy, got {}", entropy ); } // ============================================================================ // 3. Signal Intelligence -- sig_temporal_compress (3 tests) // ============================================================================ #[test] fn sig_temporal_compress_init() { let tc = TemporalCompressor::new(); assert_eq!(tc.total_written(), 0); assert_eq!(tc.occupied(), 0); } #[test] fn sig_temporal_compress_stores_frames() { let mut tc = TemporalCompressor::new(); let phases = coherent_phases(8, 0.5); let amps = uniform_amplitudes(8, 3.0); for i in 0..100u32 { tc.push_frame(&phases, &s, i); } assert!(tc.occupied() > 0, "should have stored frames"); assert_eq!(tc.total_written(), 100); } #[test] fn sig_temporal_compress_compression_ratio() { let mut tc = TemporalCompressor::new(); let phases = coherent_phases(8, 0.5); let amps = uniform_amplitudes(8, 3.0); for i in 0..200u32 { tc.push_frame(&phases, &s, i); } let ratio = tc.compression_ratio(); assert!( ratio > 1.0, "compression ratio should exceed 1.0, got {}", ratio ); } // ============================================================================ // 4. Signal Intelligence -- sig_sparse_recovery (3 tests) // ============================================================================ #[test] fn sig_sparse_recovery_init() { let sr = SparseRecovery::new(); assert!(!sr.is_initialized()); assert_eq!(sr.dropout_rate(), 0.0); } #[test] fn sig_sparse_recovery_no_dropout_passthrough() { let mut sr = SparseRecovery::new(); for _ in 0..20 { let mut amps: Vec = ramp_amplitudes(16, 1.0, 5.0); sr.process_frame(&mut amps); } assert!(sr.is_initialized()); assert!( sr.dropout_rate() < 0.15, "no dropout should yield low rate, got {}", sr.dropout_rate() ); } #[test] fn sig_sparse_recovery_handles_dropout() { let mut sr = SparseRecovery::new(); for _ in 0..20 { let mut amps = ramp_amplitudes(16, 1.0, 5.0); sr.process_frame(&mut amps); } let mut amps_dropout = ramp_amplitudes(16, 1.0, 5.0); for i in 0..6 { amps_dropout[i] = 0.0; } let events = sr.process_frame(&mut amps_dropout); let has_dropout = events.iter().any(|&(t, _)| t == EVENT_DROPOUT_RATE); let has_recovery = events.iter().any(|&(t, _)| t == EVENT_RECOVERY_COMPLETE); assert!( has_dropout || has_recovery || sr.dropout_rate() > 0.2, "should detect or recover from dropout" ); } // ============================================================================ // 5. Signal Intelligence -- sig_mincut_person_match (3 tests) // ============================================================================ #[test] fn sig_mincut_person_match_init() { let pm = PersonMatcher::new(); assert_eq!(pm.active_persons(), 0); assert_eq!(pm.total_swaps(), 0); } #[test] fn sig_mincut_person_match_tracks_one_person() { let mut pm = PersonMatcher::new(); let amps = uniform_amplitudes(16, 1.0); let vars = person_variance_pattern(16, 0); for _ in 0..20 { pm.process_frame(&s, &vars, 1); } assert_eq!(pm.active_persons(), 1); } #[test] fn sig_mincut_person_match_too_few_subcarriers() { let mut pm = PersonMatcher::new(); let amps = [1.0f32; 4]; let vars = [0.5f32; 4]; let events = pm.process_frame(&s, &vars, 1); assert!(events.is_empty(), "too few subcarriers should return empty"); } // ============================================================================ // 6. Signal Intelligence -- sig_optimal_transport (3 tests) // ============================================================================ #[test] fn sig_optimal_transport_init() { let ot = OptimalTransportDetector::new(); assert_eq!(ot.frame_count(), 0); assert_eq!(ot.distance(), 0.0); } #[test] fn sig_optimal_transport_identical_zero_distance() { let mut ot = OptimalTransportDetector::new(); let amps = ramp_amplitudes(16, 1.0, 8.0); ot.process_frame(&s); ot.process_frame(&s); assert!( ot.distance() < 0.01, "identical frames should produce ~0 distance, got {}", ot.distance() ); } #[test] fn sig_optimal_transport_distance_increases_with_shift() { let mut ot = OptimalTransportDetector::new(); // Establish baseline with ramp amplitudes. let a = ramp_amplitudes(16, 1.0, 8.0); ot.process_frame(&a); ot.process_frame(&a); let d_same = ot.distance(); // Now shift to very different distribution. let b = ramp_amplitudes(16, 50.0, 100.0); ot.process_frame(&b); let d_shifted = ot.distance(); assert!( d_shifted > d_same, "shifted distribution should increase distance: same={}, shifted={}", d_same, d_shifted ); } // ============================================================================ // 7. Adaptive Learning -- lrn_dtw_gesture_learn (3 tests) // ============================================================================ #[test] fn lrn_dtw_gesture_learn_init() { let gl = GestureLearner::new(); assert_eq!(gl.template_count(), 0); } #[test] fn lrn_dtw_gesture_learn_stillness_detection() { let mut gl = GestureLearner::new(); let phases = coherent_phases(8, 0.1); for _ in 0..100 { gl.process_frame(&phases, 0.01); } assert_eq!(gl.template_count(), 0); } #[test] fn lrn_dtw_gesture_learn_processes_motion() { let mut gl = GestureLearner::new(); let phases = coherent_phases(8, 0.1); for cycle in 0..3 { for _ in 0..70 { gl.process_frame(&phases, 0.01); } for i in 0..30 { let mut p = coherent_phases(8, 0.1); p[0] = 0.1 + (i as f32) * 0.1; gl.process_frame(&p, 0.5 + cycle as f32 * 0.01); } } assert!(true, "gesture learner processed motion cycles without error"); } // ============================================================================ // 8. Adaptive Learning -- lrn_anomaly_attractor (3 tests) // ============================================================================ #[test] fn lrn_anomaly_attractor_init() { let det = AttractorDetector::new(); assert!(!det.is_initialized()); assert_eq!(det.attractor_type(), AttractorType::Unknown); } #[test] fn lrn_anomaly_attractor_learns_stable_room() { let mut det = AttractorDetector::new(); // Need tiny perturbations for Lyapunov computation (constant data gives // zero deltas and lyapunov_count stays 0, blocking initialization). for i in 0..220 { let tiny = (i as f32) * 1e-5; let phases = [0.1 + tiny; 8]; let amps = [1.0 + tiny; 8]; det.process_frame(&phases, &s, tiny); } assert!(det.is_initialized(), "should complete learning after 200+ frames"); let at = det.attractor_type(); assert!(at != AttractorType::Unknown, "should classify attractor after learning"); } #[test] fn lrn_anomaly_attractor_detects_departure() { let mut det = AttractorDetector::new(); // Learn with tiny perturbations. for i in 0..220 { let tiny = (i as f32) * 1e-5; let phases = [0.1 + tiny; 8]; let amps = [1.0 + tiny; 8]; det.process_frame(&phases, &s, tiny); } assert!(det.is_initialized()); // Inject a large departure. let wild_phases = [5.0f32; 8]; let wild_amps = [50.0f32; 8]; let events = det.process_frame(&wild_phases, &wild_amps, 10.0); let has_departure = events.iter().any(|&(id, _)| id == EVENT_BASIN_DEPARTURE); assert!(has_departure, "large deviation should trigger basin departure"); } // ============================================================================ // 9. Adaptive Learning -- lrn_meta_adapt (3 tests) // ============================================================================ #[test] fn lrn_meta_adapt_init() { let ma = MetaAdapter::new(); assert_eq!(ma.iteration_count(), 0); assert_eq!(ma.success_count(), 0); assert_eq!(ma.meta_level(), 0); } #[test] fn lrn_meta_adapt_default_params() { let ma = MetaAdapter::new(); assert!((ma.get_param(0) - 0.05).abs() < 0.01); assert!((ma.get_param(1) - 0.10).abs() < 0.01); assert!((ma.get_param(2) - 0.70).abs() < 0.01); assert_eq!(ma.get_param(99), 0.0); } #[test] fn lrn_meta_adapt_optimization_cycle() { let mut ma = MetaAdapter::new(); for _ in 0..10 { ma.report_true_positive(); ma.on_timer(); } for _ in 0..10 { ma.report_true_positive(); ma.on_timer(); } assert_eq!(ma.iteration_count(), 1, "should complete one optimization iteration"); } // ============================================================================ // 10. Adaptive Learning -- lrn_ewc_lifelong (3 tests) // ============================================================================ #[test] fn lrn_ewc_lifelong_init() { let ewc = EwcLifelong::new(); assert_eq!(ewc.task_count(), 0); assert!(!ewc.has_prior_task()); assert_eq!(ewc.frame_count(), 0); } #[test] fn lrn_ewc_lifelong_learns_and_predicts() { let mut ewc = EwcLifelong::new(); let features = [0.5f32, 0.3, 0.8, 0.1, 0.6, 0.2, 0.9, 0.4]; let target_zone = 2; for _ in 0..200 { ewc.process_frame(&features, target_zone); } assert!( ewc.last_loss() < 1.0, "loss should decrease after training, got {}", ewc.last_loss() ); let p1 = ewc.predict(&features); let p2 = ewc.predict(&features); assert_eq!(p1, p2, "predict should be deterministic"); assert!(p1 < 4, "predicted zone should be 0-3"); } #[test] fn lrn_ewc_lifelong_penalty_zero_without_prior() { let mut ewc = EwcLifelong::new(); let features = [1.0f32; 8]; ewc.process_frame(&features, 0); assert!(!ewc.has_prior_task()); assert!( ewc.last_penalty() < 1e-8, "EWC penalty should be 0 without prior task, got {}", ewc.last_penalty() ); } // ============================================================================ // 11. Spatial Reasoning -- spt_pagerank_influence (3 tests) // ============================================================================ #[test] fn spt_pagerank_influence_init() { let pr = PageRankInfluence::new(); assert_eq!(pr.dominant_person(), 0); } #[test] fn spt_pagerank_influence_single_person() { let mut pr = PageRankInfluence::new(); let phases = coherent_phases(32, 0.5); for _ in 0..20 { pr.process_frame(&phases, 1); } let dom = pr.dominant_person(); assert!(dom < 4, "dominant person should be valid index"); } #[test] fn spt_pagerank_influence_multi_person() { let mut pr = PageRankInfluence::new(); let mut phases = coherent_phases(32, 0.1); for i in 0..8 { phases[i] = 2.0 + (i as f32) * 0.5; } for _ in 0..30 { pr.process_frame(&phases, 4); } let rank0 = pr.rank(0); assert!(rank0 > 0.0, "person 0 should have nonzero rank"); } // ============================================================================ // 12. Spatial Reasoning -- spt_micro_hnsw (3 tests) // ============================================================================ #[test] fn spt_micro_hnsw_init() { let hnsw = MicroHnsw::new(); assert_eq!(hnsw.size(), 0); } #[test] fn spt_micro_hnsw_insert_and_search() { let mut hnsw = MicroHnsw::new(); let v1 = [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; let v2 = [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; hnsw.insert(&v1, 10); hnsw.insert(&v2, 20); assert_eq!(hnsw.size(), 2); // search() returns (node_index, distance), not (label, distance). // Use process_frame to get label via event emission, or just verify index. let query = [0.9, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; let (node_idx, dist) = hnsw.search(&query); assert_eq!(node_idx, 0, "should match node 0 (closest to v1)"); assert!(dist < 1.0, "distance should be small"); // Verify label via process_frame event or last_label. hnsw.process_frame(&query); assert_eq!(hnsw.last_label(), 10, "label should be 10 for closest match"); } #[test] fn spt_micro_hnsw_process_frame_emits_events() { let mut hnsw = MicroHnsw::new(); let v1 = [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; hnsw.insert(&v1, 42); let query = [1.0, 0.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; let events = hnsw.process_frame(&query); let has_match = events.iter().any(|&(t, _)| t == EVENT_NEAREST_MATCH_ID); assert!(has_match, "process_frame should emit match events"); } // ============================================================================ // 13. Spatial Reasoning -- spt_spiking_tracker (3 tests) // ============================================================================ #[test] fn spt_spiking_tracker_init() { let st = SpikingTracker::new(); assert_eq!(st.current_zone(), -1); assert!(!st.is_tracking()); } #[test] fn spt_spiking_tracker_activates_zone() { let mut st = SpikingTracker::new(); // Alternate between two frame states so the input spiking neurons see // large phase changes only in the zone-0 subcarriers (0..7). let prev = [0.0f32; 32]; let mut active = [0.0f32; 32]; for i in 0..8 { active[i] = 2.0; // Strong activity in zone 0 subcarriers. } for frame in 0..60 { if frame % 2 == 0 { st.process_frame(&active, &prev); } else { st.process_frame(&prev, &active); } } // Zone 0 should have tracking activity. let current = st.current_zone(); let is_tracking = st.is_tracking(); // At minimum, the tracker should process without panic and produce zone rates. let r0 = st.zone_spike_rate(0); assert!( r0 > 0.0 || is_tracking, "zone 0 should show activity or tracker should be active: r0={}, zone={}, tracking={}", r0, current, is_tracking ); } #[test] fn spt_spiking_tracker_no_activity_no_track() { let mut st = SpikingTracker::new(); let phases = [0.0f32; 32]; let prev = [0.0f32; 32]; st.process_frame(&phases, &prev); assert!(!st.is_tracking()); let events = st.process_frame(&phases, &prev); let has_spike_rate = events.iter().any(|&(t, _)| t == EVENT_SPIKE_RATE); assert!(has_spike_rate, "should emit spike rate even without tracking"); } // ============================================================================ // 14. Temporal Analysis -- tmp_pattern_sequence (3 tests) // ============================================================================ #[test] fn tmp_pattern_sequence_init() { let psa = PatternSequenceAnalyzer::new(); assert_eq!(psa.pattern_count(), 0); assert_eq!(psa.current_minute(), 0); } #[test] fn tmp_pattern_sequence_records_events() { let mut psa = PatternSequenceAnalyzer::new(); for min in 0..120 { for _ in 0..20 { psa.on_frame(1, 0.3, min); } } assert!(psa.current_minute() <= 120); } #[test] fn tmp_pattern_sequence_on_timer() { let mut psa = PatternSequenceAnalyzer::new(); for min in 0..60 { for _ in 0..20 { psa.on_frame(1, 0.5, min); } } let events = psa.on_timer(); assert!(events.len() <= 4, "events should be bounded"); } // ============================================================================ // 15. Temporal Analysis -- tmp_temporal_logic_guard (3 tests) // ============================================================================ #[test] fn tmp_temporal_logic_guard_init() { let guard = TemporalLogicGuard::new(); assert_eq!(guard.satisfied_count(), 8); assert_eq!(guard.frame_index(), 0); } #[test] fn tmp_temporal_logic_guard_normal_all_satisfied() { let mut guard = TemporalLogicGuard::new(); let input = normal_frame_input(); for _ in 0..100 { guard.on_frame(&input); } assert_eq!(guard.satisfied_count(), 8, "normal input should satisfy all 8 rules"); } #[test] fn tmp_temporal_logic_guard_detects_violation() { let mut guard = TemporalLogicGuard::new(); let mut input = FrameInput::default(); input.presence = 0; input.fall_alert = true; // Drop result to avoid borrow conflict with guard. let _ = guard.on_frame(&input); assert_eq!(guard.rule_state(0), RuleState::Violated); assert_eq!(guard.violation_count(0), 1); } // ============================================================================ // 16. Temporal Analysis -- tmp_goap_autonomy (3 tests) // ============================================================================ #[test] fn tmp_goap_autonomy_init() { let planner = GoapPlanner::new(); assert_eq!(planner.world_state(), 0); assert_eq!(planner.current_goal(), 0xFF); assert_eq!(planner.plan_len(), 0); } #[test] fn tmp_goap_autonomy_world_state_update() { let mut planner = GoapPlanner::new(); planner.update_world(1, 0.5, 2, 0.8, 0.1, true, false); assert!(planner.has_property(0), "should have presence"); assert!(planner.has_property(1), "should have motion"); assert!(planner.has_property(6), "should have vitals"); } #[test] fn tmp_goap_autonomy_plans_and_executes() { let mut planner = GoapPlanner::new(); planner.set_goal_priority(5, 0.99); planner.update_world(0, 0.0, 0, 0.3, 0.0, false, false); for _ in 0..60 { planner.on_timer(); } let _events = planner.on_timer(); // plan_step() returns u8; verify planning occurred let _ = planner.plan_step(); } // ============================================================================ // 17. AI Security -- ais_prompt_shield (3 tests) // ============================================================================ #[test] fn ais_prompt_shield_init() { let ps = PromptShield::new(); assert_eq!(ps.frame_count(), 0); assert!(!ps.is_calibrated()); } #[test] fn ais_prompt_shield_calibrates() { let mut ps = PromptShield::new(); for i in 0..100u32 { ps.process_frame(&[(i as f32) * 0.01; 16], &[1.0; 16]); } assert!(ps.is_calibrated(), "should be calibrated after 100 frames"); } #[test] fn ais_prompt_shield_detects_replay() { let mut ps = PromptShield::new(); for i in 0..100u32 { ps.process_frame(&[(i as f32) * 0.02; 16], &[1.0; 16]); } assert!(ps.is_calibrated()); let rp = [99.0f32; 16]; let ra = [2.5f32; 16]; ps.process_frame(&rp, &ra); let events = ps.process_frame(&rp, &ra); let replay_detected = events.iter().any(|&(t, _)| t == EVENT_REPLAY_ATTACK); assert!(replay_detected, "should detect replay attack"); } // ============================================================================ // 18. AI Security -- ais_behavioral_profiler (3 tests) // ============================================================================ #[test] fn ais_behavioral_profiler_init() { let bp = BehavioralProfiler::new(); assert_eq!(bp.frame_count(), 0); assert!(!bp.is_mature()); assert_eq!(bp.total_anomalies(), 0); } #[test] fn ais_behavioral_profiler_matures() { let mut bp = BehavioralProfiler::new(); for _ in 0..1000 { bp.process_frame(true, 0.5, 1); } assert!(bp.is_mature(), "should mature after 1000 frames"); } #[test] fn ais_behavioral_profiler_detects_anomaly() { let mut bp = BehavioralProfiler::new(); // Vary behavior across observation windows so Welford stats build non-zero // variance. Each observation window is 200 frames; we need 5 cycles. for i in 0..1000u32 { let window_id = i / 200; let pres = window_id % 2 != 0; let mot = 0.1 + (window_id as f32) * 0.05; let per = (window_id % 3) as u8; bp.process_frame(pres, mot, per); } assert!(bp.is_mature()); // Inject dramatically different behavior. let mut found = false; for _ in 0..4000 { let ev = bp.process_frame(true, 10.0, 5); if ev.iter().any(|&(t, _)| t == EVENT_BEHAVIOR_ANOMALY) { found = true; } } assert!(found, "dramatic behavior change should trigger anomaly"); } // ============================================================================ // 19. Quantum-Inspired -- qnt_quantum_coherence (3 tests) // ============================================================================ #[test] fn qnt_quantum_coherence_init() { let mon = QuantumCoherenceMonitor::new(); assert_eq!(mon.frame_count(), 0); } #[test] fn qnt_quantum_coherence_uniform_high_coherence() { let mut mon = QuantumCoherenceMonitor::new(); let phases = coherent_phases(16, 0.0); for _ in 0..21 { mon.process_frame(&phases); } let coh = mon.coherence(); assert!( (coh - 1.0).abs() < 0.1, "zero phases should give coherence ~1.0, got {}", coh ); } #[test] fn qnt_quantum_coherence_spread_low_coherence() { let mut mon = QuantumCoherenceMonitor::new(); let phases = incoherent_phases(32); for _ in 0..51 { mon.process_frame(&phases); } let coh = mon.coherence(); assert!(coh < 0.5, "spread phases should yield low coherence, got {}", coh); } // ============================================================================ // 20. Quantum-Inspired -- qnt_interference_search (3 tests) // ============================================================================ #[test] fn qnt_interference_search_init_uniform() { let search = InterferenceSearch::new(); assert_eq!(search.iterations(), 0); assert!(!search.is_converged()); let expected = 1.0 / 16.0; let p = search.probability(Hypothesis::Empty); assert!( (p - expected).abs() < 0.01, "initial probability should be ~{}, got {}", expected, p ); } #[test] fn qnt_interference_search_empty_room_converges() { let mut search = InterferenceSearch::new(); for _ in 0..100 { search.process_frame(0, 0.0, 0); } assert_eq!(search.winner(), Hypothesis::Empty); // The Grover-inspired diffusion amplifies the oracle-matching hypothesis. // With 16 hypotheses the initial probability is 1/16 = 0.0625, so any // amplification above that confirms the oracle is working. assert!( search.winner_probability() > 0.1, "should amplify Empty hypothesis above initial 0.0625, got {}", search.winner_probability() ); } #[test] fn qnt_interference_search_normalization_preserved() { let mut search = InterferenceSearch::new(); for _ in 0..50 { search.process_frame(1, 0.5, 1); } let total_prob = search.probability(Hypothesis::Empty) + search.probability(Hypothesis::PersonZoneA) + search.probability(Hypothesis::PersonZoneB) + search.probability(Hypothesis::PersonZoneC) + search.probability(Hypothesis::PersonZoneD) + search.probability(Hypothesis::TwoPersons) + search.probability(Hypothesis::ThreePersons) + search.probability(Hypothesis::MovingLeft) + search.probability(Hypothesis::MovingRight) + search.probability(Hypothesis::Sitting) + search.probability(Hypothesis::Standing) + search.probability(Hypothesis::Falling) + search.probability(Hypothesis::Exercising) + search.probability(Hypothesis::Sleeping) + search.probability(Hypothesis::Cooking) + search.probability(Hypothesis::Working); assert!( (total_prob - 1.0).abs() < 0.05, "total probability should be ~1.0, got {}", total_prob ); } // ============================================================================ // 21. Autonomous Systems -- aut_psycho_symbolic (3 tests) // ============================================================================ #[test] fn aut_psycho_symbolic_init() { let engine = PsychoSymbolicEngine::new(); assert_eq!(engine.frame_count(), 0); assert_eq!(engine.fired_rules(), 0); } #[test] fn aut_psycho_symbolic_empty_room() { let mut engine = PsychoSymbolicEngine::new(); engine.set_coherence(0.8); let events = engine.process_frame(0.0, 2.0, 0.0, 0.0, 0.0, 1.0); let result = events.iter().find(|e| e.0 == EVENT_INFERENCE_RESULT); assert!(result.is_some(), "should produce inference for empty room"); assert_eq!(result.unwrap().1 as u8, 15); } #[test] fn aut_psycho_symbolic_fires_rules() { let mut engine = PsychoSymbolicEngine::new(); engine.set_coherence(0.8); let events = engine.process_frame(1.0, 10.0, 15.0, 70.0, 1.0, 1.0); let rule_fired_count = events.iter().filter(|e| e.0 == EVENT_RULE_FIRED).count(); assert!(rule_fired_count >= 1, "should fire at least one rule"); } // ============================================================================ // 22. Autonomous Systems -- aut_self_healing_mesh (3 tests) // ============================================================================ #[test] fn aut_self_healing_mesh_init() { let mesh = SelfHealingMesh::new(); assert_eq!(mesh.frame_count(), 0); assert_eq!(mesh.active_nodes(), 0); assert!(!mesh.is_healing()); } #[test] fn aut_self_healing_mesh_healthy_nodes() { let mut mesh = SelfHealingMesh::new(); let qualities = [0.9, 0.85, 0.88, 0.92]; let events = mesh.process_frame(&qualities); let cov_ev = events.iter().find(|e| e.0 == EVENT_COVERAGE_SCORE); assert!(cov_ev.is_some(), "should emit coverage score event"); assert!( cov_ev.unwrap().1 > 0.8, "healthy mesh should have high coverage, got {}", cov_ev.unwrap().1 ); assert!(!mesh.is_healing(), "healthy mesh should not be healing"); } #[test] fn aut_self_healing_mesh_detects_degradation() { let mut mesh = SelfHealingMesh::new(); let fragile_qualities = [0.9, 0.05, 0.85, 0.88]; for _ in 0..20 { mesh.process_frame(&fragile_qualities); } let events = mesh.process_frame(&fragile_qualities); let has_degraded = events.iter().any(|e| e.0 == EVENT_NODE_DEGRADED); assert!( mesh.is_healing() || has_degraded, "fragile mesh should trigger healing or node degraded event" ); } // ============================================================================ // 23. Exotic -- exo_time_crystal (3 tests) // ============================================================================ #[test] fn exo_time_crystal_init() { let tc = TimeCrystalDetector::new(); assert_eq!(tc.frame_count(), 0); assert_eq!(tc.multiplier(), 0); assert_eq!(tc.coordination_index(), 0); } #[test] fn exo_time_crystal_constant_no_detection() { let mut tc = TimeCrystalDetector::new(); for _ in 0..256 { let events = tc.process_frame(1.0); for ev in events { assert_ne!(ev.0, EVENT_CRYSTAL_DETECTED, "constant signal should not detect crystal"); } } } #[test] fn exo_time_crystal_periodic_autocorrelation() { let mut tc = TimeCrystalDetector::new(); for frame in 0..256 { let val = if (frame % 10) < 5 { 1.0 } else { 0.0 }; tc.process_frame(val); } let acorr = tc.autocorrelation()[9]; assert!( acorr > 0.5, "periodic signal should produce strong autocorrelation at period lag, got {}", acorr ); } // ============================================================================ // 24. Exotic -- exo_hyperbolic_space (3 tests) // ============================================================================ #[test] fn exo_hyperbolic_space_init() { let he = HyperbolicEmbedder::new(); assert_eq!(he.frame_count(), 0); assert_eq!(he.label(), 0); } #[test] fn exo_hyperbolic_space_emits_three_events() { let mut he = HyperbolicEmbedder::new(); let amps = uniform_amplitudes(32, 10.0); let events = he.process_frame(&s); assert_eq!(events.len(), 3, "should emit hierarchy, radius, label events"); assert_eq!(events[0].0, EVENT_HIERARCHY_LEVEL); assert_eq!(events[2].0, EVENT_LOCATION_LABEL); } #[test] fn exo_hyperbolic_space_label_in_range() { let mut he = HyperbolicEmbedder::new(); let amps = uniform_amplitudes(32, 10.0); for _ in 0..20 { let events = he.process_frame(&s); if events.len() == 3 { let label = events[2].1 as u8; assert!(label < 16, "label {} should be < 16", label); } } } // ============================================================================ // Cross-module integration tests (bonus) // ============================================================================ #[test] fn cross_module_coherence_gate_feeds_attractor() { let mut gate = CoherenceGate::new(); let mut attractor = AttractorDetector::new(); // Use tiny perturbations so attractor's Lyapunov count accumulates. for i in 0..220 { let tiny = (i as f32) * 1e-5; let phases: Vec = (0..16).map(|_| 0.3 + tiny).collect(); let amps: Vec = (0..8).map(|_| 1.0 + tiny).collect(); gate.process_frame(&phases); let coh = gate.coherence(); attractor.process_frame(&phases[..8], &s, coh); } assert!(attractor.is_initialized(), "attractor should learn from gate-fed data"); } #[test] fn cross_module_shield_and_coherence() { let mut shield = PromptShield::new(); let mut qc = QuantumCoherenceMonitor::new(); for i in 0..100u32 { let phases = coherent_phases(16, (i as f32) * 0.01); let amps = uniform_amplitudes(16, 1.0); shield.process_frame(&phases, &s); qc.process_frame(&phases); } assert!(shield.is_calibrated()); assert_eq!(qc.frame_count(), 100); } #[test] fn cross_module_all_modules_construct() { let _cg = CoherenceGate::new(); let _fa = FlashAttention::new(); let _tc = TemporalCompressor::new(); let _sr = SparseRecovery::new(); let _pm = PersonMatcher::new(); let _ot = OptimalTransportDetector::new(); let _gl = GestureLearner::new(); let _ad = AttractorDetector::new(); let _ma = MetaAdapter::new(); let _ewc = EwcLifelong::new(); let _pr = PageRankInfluence::new(); let _hnsw = MicroHnsw::new(); let _st = SpikingTracker::new(); let _psa = PatternSequenceAnalyzer::new(); let _tlg = TemporalLogicGuard::new(); let _gp = GoapPlanner::new(); let _ps = PromptShield::new(); let _bp = BehavioralProfiler::new(); let _qcm = QuantumCoherenceMonitor::new(); let _is = InterferenceSearch::new(); let _pse = PsychoSymbolicEngine::new(); let _shm = SelfHealingMesh::new(); let _tcd = TimeCrystalDetector::new(); let _he = HyperbolicEmbedder::new(); assert!(true, "all 24 vendor modules constructed successfully"); }