use std::path::PathBuf;
use serde_json::Value;
use sqlitegraph::bench_meta::BenchRun;
use sqlitegraph::bench_regression::{BenchGate, BenchGateConfig, BenchOutcome};
const SQLITE_3X_THRESHOLD_500: u64 = 75_000_000;
const V13_BASELINE_500: u64 = 255_290_000;
const SQLITE_BASELINE_MS_500: f64 = 24.978;
#[test]
fn test_chain_traversal_within_3x_sqlite_baseline() {
let current_runs = load_criterion_results()
.expect("Failed to load Criterion results. Run: cargo bench --bench bfs");
println!("\n=== Chain Traversal Performance Gate (IO-12) ===");
println!("3x SQLite Target Thresholds:");
println!(
" Chain BFS (500): {}ms (3x SQLite target: {:.3}ms)",
SQLITE_3X_THRESHOLD_500 as f64 / 1_000_000.0,
SQLITE_BASELINE_MS_500 * 3.0
);
println!();
let gate = BenchGate::new(BenchGateConfig {
thresholds: vec![("bfs_chain/native/500".into(), SQLITE_3X_THRESHOLD_500)],
baseline: vec![],
tolerance: 0.05, });
let outcome = gate.evaluate(¤t_runs);
for run in ¤t_runs {
let ratio_ms = run.mean_ns as f64 / 1_000_000.0;
let ratio_to_sqlite = ratio_ms / SQLITE_BASELINE_MS_500;
println!(
" {}: {:.2}ms ({:.2}x SQLite baseline {:.3}ms) - {}",
run.name,
ratio_ms,
ratio_to_sqlite,
SQLITE_BASELINE_MS_500,
if run.mean_ns <= SQLITE_3X_THRESHOLD_500 {
"PASS"
} else {
"FAIL"
}
);
}
assert_eq!(
outcome,
BenchOutcome::Pass,
"Chain traversal exceeds 3x SQLite baseline. Outcome: {:?}",
outcome
);
}
#[test]
fn test_chain_traversal_regression_check() {
let current_runs = load_criterion_results()
.expect("Failed to load Criterion results. Run: cargo bench --bench bfs");
println!("\n=== Chain Traversal Regression Check vs v1.3 ===");
println!("v1.3 Baseline (before sequential I/O optimization):");
println!(
" Chain BFS (500): {:.2}ms",
V13_BASELINE_500 as f64 / 1_000_000.0
);
println!();
for run in ¤t_runs {
let improvement = if run.mean_ns < V13_BASELINE_500 {
((V13_BASELINE_500 as f64 - run.mean_ns as f64) / V13_BASELINE_500 as f64) * 100.0
} else {
-((run.mean_ns as f64 - V13_BASELINE_500 as f64) / V13_BASELINE_500 as f64) * 100.0
};
println!(
" {}: Current {:.2}ms vs v1.3 Baseline {:.2}ms ({:.1}% {})",
run.name,
run.mean_ns as f64 / 1_000_000.0,
V13_BASELINE_500 as f64 / 1_000_000.0,
improvement.abs(),
if improvement >= 0.0 {
"improvement"
} else {
"regression"
}
);
}
assert!(true, "Regression check completed");
}
fn load_criterion_results() -> Result<Vec<BenchRun>, String> {
let criterion_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../target/criterion");
let mut results = Vec::new();
let path_500 = criterion_dir.join("bfs_chain/native/500/new/estimates.json");
match load_estimate_json(&path_500) {
Ok(value) => {
let mean_ns = extract_point_estimate(&value)?;
results.push(BenchRun {
name: "bfs_chain/native/500".to_string(),
mean_ns,
samples: 20, });
}
Err(e) => {
return Err(format!(
"Failed to load {}: {}. Run: cargo bench --bench bfs",
path_500.display(),
e
));
}
}
Ok(results)
}
fn load_estimate_json(path: &PathBuf) -> Result<Value, String> {
let content = std::fs::read_to_string(path)
.map_err(|e| format!("Failed to read {}: {}", path.display(), e))?;
serde_json::from_str(&content)
.map_err(|e| format!("Failed to parse JSON from {}: {}", path.display(), e))
}
fn extract_point_estimate(value: &Value) -> Result<u64, String> {
value
.get("mean")
.and_then(|m| m.get("point_estimate"))
.and_then(|p| p.as_f64())
.map(|v| v as u64)
.ok_or_else(|| "Invalid estimate.json format".into())
}