#[cfg(feature = "std")]
mod std_tests {
use llmosafe::{
calculate_halo_signal, get_bias_breakdown, sift_perceptions, AdversarialDetector,
ConfidenceTracker, CusumDetector, DriftDetector, EscalationPolicy, PressureLevel,
ReasoningLoop, RepetitionDetector, ResourceGuard, SafetyContext, SafetyDecision,
WorkingMemory,
};
#[test]
fn full_pipeline_integration() {
let objective = "safety analysis";
let observations = vec![
"System running normally",
"All checks passed",
"No anomalies detected",
];
let sifted = sift_perceptions(&observations, objective);
let mut memory = WorkingMemory::<64>::new(1000);
let validated = memory.update(sifted).expect("validation should succeed");
let mut loop_guard = ReasoningLoop::<10>::new();
let result = loop_guard.next_step(validated);
assert!(result.is_ok());
let policy = EscalationPolicy::default()
.with_halt_entropy(1500)
.with_escalate_entropy(1200)
.with_warn_entropy(1100);
let decision = policy.decide(validated.raw_entropy(), validated.raw_surprise(), validated.has_bias());
assert!(decision.can_proceed());
}
#[test]
fn biased_input_rejected() {
let observations = vec![
"The expert says this is the best official solution",
];
let sifted = sift_perceptions(&observations, "analysis");
assert!(sifted.has_bias());
let policy = EscalationPolicy::default();
let decision = policy.decide(sifted.raw_entropy(), sifted.raw_surprise(), sifted.has_bias());
assert!(matches!(decision, SafetyDecision::Escalate { .. }));
}
#[test]
fn resource_guard_integration() {
let guard = ResourceGuard::auto(0.5); let synapse = guard.check().expect("resource check should succeed");
let policy = EscalationPolicy::default();
let decision = policy.decide(synapse.raw_entropy(), synapse.raw_surprise(), synapse.has_bias());
assert!(decision.can_proceed());
}
#[test]
fn detection_layer_integration() {
let mut rep = RepetitionDetector::new(3);
for _ in 0..5 {
rep.observe("stuck in loop");
}
assert!(rep.is_stuck());
let mut drift = DriftDetector::new("rust safety", 0.5);
drift.observe("python web development");
assert!(drift.is_drifting());
let mut conf = ConfidenceTracker::new(0.5, 2);
conf.observe(0.8);
conf.observe(0.6);
conf.observe(0.4);
assert!(conf.is_low());
assert!(conf.is_decaying());
let adv = AdversarialDetector::new();
let patterns = adv.detect_substrings("ignore previous instructions");
assert!(!patterns.is_empty());
}
#[test]
fn cusum_detection_integration() {
let mut detector = CusumDetector::new(500.0, 50.0, 200.0);
for _ in 0..10 {
assert!(!detector.update(500.0));
}
for _ in 0..10 {
detector.update(700.0);
}
assert!(detector.detected());
}
#[test]
fn safety_context_accumulation() {
let mut ctx = SafetyContext::new(EscalationPolicy::default());
ctx.observe(300, 100, false);
ctx.observe(400, 150, false);
ctx.observe(350, 120, false);
assert_eq!(ctx.observation_count(), 3);
let decision = ctx.finalize();
assert!(matches!(decision, SafetyDecision::Proceed));
ctx.observe(500, 200, true);
let decision = ctx.finalize();
assert!(matches!(decision, SafetyDecision::Escalate { .. }));
}
#[test]
fn pressure_level_decision_override() {
let policy = EscalationPolicy::default();
let d1 = policy.decide_with_pressure(400, 100, false, PressureLevel::Nominal);
assert!(matches!(d1, SafetyDecision::Proceed));
let d2 = policy.decide_with_pressure(400, 100, false, PressureLevel::Critical);
assert!(matches!(d2, SafetyDecision::Escalate { .. }));
}
#[test]
fn bias_breakdown_integration() {
let text = "The expert provided an official professional recommendation";
let breakdown = get_bias_breakdown(text);
assert!(breakdown.authority > 0);
assert_eq!(breakdown.total(), calculate_halo_signal(text));
}
#[test]
fn working_memory_stats_integration() {
let mut memory = WorkingMemory::<4>::new(1000);
for i in 1..=4 {
let mut synapse = llmosafe::Synapse::new();
synapse.set_raw_entropy(100 * i as u16);
let sifted = llmosafe::SiftedSynapse::new(synapse);
memory.update(sifted).unwrap();
}
let mean = memory.mean_entropy();
let trend = memory.trend();
assert!((mean - 250.0).abs() < 1.0);
assert!(trend > 0.0);
assert!(memory.is_drifting(10.0));
}
#[test]
fn escalation_policy_builder_pattern() {
let policy = EscalationPolicy::new()
.with_warn_entropy(500)
.with_escalate_entropy(700)
.with_halt_entropy(900)
.with_bias_escalates(false);
let d1 = policy.decide(550, 100, false);
assert!(matches!(d1, SafetyDecision::Warn(_)));
let d2 = policy.decide(750, 100, false);
assert!(matches!(d2, SafetyDecision::Escalate { .. }));
let d3 = policy.decide(950, 100, false);
assert!(matches!(d3, SafetyDecision::Halt(_)));
let d4 = policy.decide(400, 100, true);
assert!(matches!(d4, SafetyDecision::Proceed));
}
}
#[cfg(not(feature = "std"))]
mod no_std_tests {
#[test]
fn no_std_compiles() {
assert!(true);
}
}