use flux_verify_api::compiler;
use flux_verify_api::engine::vm::FluxVm;
use flux_verify_api::provenance::merkle;
use axum::Router;
use std::sync::Arc;
use tokio::sync::Mutex;
fn test_app() -> Router {
use flux_verify_api::api::routes::{self, AppState};
use flux_verify_api::config::Config;
let state = Arc::new(Mutex::new(AppState::new(Config::from_env())));
routes::router().with_state(state)
}
#[test]
fn test_sonar_50khz_disproven() {
let problem = compiler::parse_claim(
"A 50kHz sonar at 200m depth can detect a 10dB target at 5km",
"sonar",
)
.expect("should parse");
assert_eq!(problem.domain, "sonar");
assert_eq!(problem.variables.len(), 4);
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let (verdict, confidence, counterexample) = vm.evaluate(&trace, &problem);
assert_eq!(verdict, "DISPROVEN");
assert!(confidence > 0.9);
assert!(counterexample.is_some());
let ce = counterexample.unwrap();
assert!(ce["signal_excess_db"].as_f64().unwrap() < 0.0);
}
#[test]
fn test_sonar_1khz_proven() {
let problem = compiler::parse_claim(
"A 1kHz sonar at 100m depth can detect a 10dB target at 2km",
"sonar",
)
.expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let (verdict, _confidence, counterexample) = vm.evaluate(&trace, &problem);
assert_eq!(verdict, "PROVEN");
assert!(counterexample.is_none());
}
#[test]
fn test_sonar_trace_has_physics() {
let problem = compiler::parse_claim(
"A 10kHz sonar at 50m depth can detect a 15dB target at 1km",
"sonar",
)
.expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let opcodes: Vec<&str> = trace.iter().map(|e| e.opcode.as_str()).collect();
assert!(opcodes.contains(&"LOAD"), "trace should have LOAD ops");
assert!(opcodes.contains(&"SONAR_SVP"), "trace should have SONAR_SVP");
assert!(opcodes.contains(&"SONAR_ABSORPTION"), "trace should have SONAR_ABSORPTION");
assert!(opcodes.contains(&"SONAR_TL"), "trace should have SONAR_TL");
assert!(opcodes.contains(&"ASSERT_GT"), "trace should have ASSERT_GT");
}
#[test]
fn test_sonar_mackenzie_velocity() {
let problem = compiler::parse_claim(
"A 5kHz sonar at 200m depth can detect a 10dB target at 3km",
"sonar",
)
.expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let svp = trace.iter().find(|e| e.opcode == "SONAR_SVP").expect("should have SVP");
let sv = svp.result.unwrap();
assert!(sv > 1450.0 && sv < 1550.0, "Sound velocity {} should be ~1480-1520", sv);
}
#[test]
fn test_thermal_in_range() {
let problem = compiler::parse_claim(
"temperature 45°C is within safe range of 20°C to 80°C",
"thermal",
)
.expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let (verdict, _confidence, counterexample) = vm.evaluate(&trace, &problem);
assert_eq!(verdict, "PROVEN");
assert!(counterexample.is_none());
}
#[test]
fn test_thermal_out_of_range() {
let problem = compiler::parse_claim(
"temperature 95°C is within safe range of 20°C to 80°C",
"thermal",
)
.expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let (verdict, _confidence, counterexample) = vm.evaluate(&trace, &problem);
assert_eq!(verdict, "DISPROVEN");
assert!(counterexample.is_some());
}
#[test]
fn test_generic_gt_proven() {
let problem = compiler::parse_claim("10 is greater than 5", "generic").expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let (verdict, _, _) = vm.evaluate(&trace, &problem);
assert_eq!(verdict, "PROVEN");
}
#[test]
fn test_generic_lt_disproven() {
let problem = compiler::parse_claim("10 is less than 5", "generic").expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let (verdict, _, _) = vm.evaluate(&trace, &problem);
assert_eq!(verdict, "DISPROVEN");
}
#[test]
fn test_generic_operator_direct() {
let problem = compiler::parse_claim("100 > 50", "generic").expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let (verdict, _, _) = vm.evaluate(&trace, &problem);
assert_eq!(verdict, "PROVEN");
}
#[test]
fn test_merkle_deterministic() {
let problem = compiler::parse_claim(
"A 10kHz sonar at 100m depth can detect a 10dB target at 2km",
"sonar",
)
.expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm1 = FluxVm::new();
let trace1 = vm1.execute(&bytecodes);
let mut vm2 = FluxVm::new();
let trace2 = vm2.execute(&bytecodes);
let hash1 = merkle::hash_trace(&trace1);
let hash2 = merkle::hash_trace(&trace2);
assert_eq!(hash1, hash2, "Same inputs should produce same hash");
}
#[test]
fn test_merkle_different_claims() {
let problem1 = compiler::parse_claim(
"A 10kHz sonar at 100m depth can detect a 10dB target at 2km",
"sonar",
)
.expect("should parse");
let problem2 = compiler::parse_claim(
"A 50kHz sonar at 200m depth can detect a 10dB target at 5km",
"sonar",
)
.expect("should parse");
let bc1 = compiler::compile(&problem1);
let bc2 = compiler::compile(&problem2);
let mut vm1 = FluxVm::new();
let mut vm2 = FluxVm::new();
let t1 = vm1.execute(&bc1);
let t2 = vm2.execute(&bc2);
assert_ne!(merkle::hash_trace(&t1), merkle::hash_trace(&t2));
}
#[test]
fn test_proof_hash_format() {
let problem = compiler::parse_claim(
"A 5kHz sonar at 50m depth can detect a 10dB target at 1km",
"sonar",
)
.expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let hash = merkle::hash_trace(&trace);
assert_eq!(hash.len(), 64);
assert!(hash.chars().all(|c| c.is_ascii_hexdigit()));
}
#[test]
fn test_unknown_domain() {
let result = compiler::parse_claim("test", "quantum");
assert!(result.is_err());
assert!(result.unwrap_err().contains("Unknown domain"));
}
#[test]
fn test_sonar_counterexample_fields() {
let problem = compiler::parse_claim(
"A 50kHz sonar at 200m depth can detect a 10dB target at 5km",
"sonar",
)
.expect("should parse");
let bytecodes = compiler::compile(&problem);
let mut vm = FluxVm::new();
let trace = vm.execute(&bytecodes);
let (_, _, ce) = vm.evaluate(&trace, &problem);
let ce = ce.unwrap();
assert!(ce.get("depth_m").is_some());
assert!(ce.get("frequency_hz").is_some());
assert!(ce.get("range_m").is_some());
assert!(ce.get("sound_velocity_ms").is_some());
assert!(ce.get("transmission_loss_db").is_some());
assert!(ce.get("signal_excess_db").is_some());
}