use std::collections::HashMap;
use steeldb::index::InfonIndex;
use steeldb::{Postings, RoarPostings, TokenStore};
#[test]
fn layer4_linter() {
let l = steeldb::linter::Linter::from_tokens(
["org/toyota","org/honda","artifact/battery_cell","powertrain/electric","powertrain/diesel"].into_iter().map(String::from));
let r = l.lint("(and org/toyota (evidence artifact/battery_cel :min-bel 0.8) powertrain/*)");
eprintln!("L4 LINTER: ok={} errors={:?} repaired={:?}", r.ok, r.errors.iter().map(|e| e.message.clone()).collect::<Vec<_>>(), r.repaired);
assert!(!r.ok);
assert_eq!(r.errors[0].suggestions[0], "artifact/battery_cell");
}
#[test]
fn layer5_ds_polarity() {
let mut ix: InfonIndex<RoarPostings> = InfonIndex::from_postings(HashMap::new(), 5);
ix.add_infon_polar(0,"hazard/thermal",1.0);
ix.add_infon_polar(1,"hazard/thermal",0.5);
ix.add_infon_polar(2,"hazard/thermal",-0.5);
ix.add_infon_polar(3,"hazard/thermal",-1.0);
let scope = ix.universe();
let mass = ix.signed_mass("hazard/thermal", &scope);
let (bel,pl) = ix.belief_interval("hazard/thermal", &scope);
eprintln!("L5 DS: signed_mass={mass:.2} belief=[{bel:.2}, {pl:.2}]");
assert!((mass-0.0).abs()<1e-9);
assert!((bel-0.2).abs()<1e-9 && (pl-0.8).abs()<1e-9);
assert_eq!(ix.evidence_set("hazard/thermal",0.8).len(), 1);
}
#[test]
fn layer6_ikl() {
let raw = HashMap::from([("country/japan".to_string(),vec![0u32,1]),("country/usa".to_string(),vec![2,3]),("powertrain/electric".to_string(),vec![1,2])]);
let ix: InfonIndex<RoarPostings> = InfonIndex::from_postings(raw, 4);
let hit = steeldb::evaluate(&ix, "(and country/japan powertrain/electric)");
let notq = steeldb::evaluate(&ix, "(and powertrain/electric (not country/japan))");
eprintln!("L6 IKL: (and japan electric)={} (electric AND-NOT japan)={}", hit.len(), notq.len());
assert_eq!(hit.len(),1); assert_eq!(notq.len(),1);
}
#[test]
fn layer7_programs() {
let raw = HashMap::from([("country/japan".to_string(),vec![0u32,1]),("country/usa".to_string(),vec![2,3,4]),("powertrain/electric".to_string(),vec![1,2,4]),("powertrain/diesel".to_string(),vec![0,3])]);
let ix: InfonIndex<RoarPostings> = InfonIndex::from_postings(raw, 5);
let ct = steeldb::programs::crosstab(&ix, "*", "country", "powertrain", 6);
eprintln!("L7 PROGRAMS crosstab:\n{}", serde_json::to_string_pretty(&ct).unwrap());
assert_eq!(ct["row_facet"], "country");
}
#[cfg(feature="onnx")]
#[test]
fn layer1_tagger() {
use steeldb::text::SpoTagger;
let ml = std::path::PathBuf::from("models/step0_bundle_ml");
if !ml.join("spo.onnx").exists() { eprintln!("L1: no models"); return; }
let mut t = SpoTagger::load(&ml).unwrap();
for s in ["Toyota supplies a battery cell under SAE J1100 specs in Q3 2026.","Hyundai recalled 82,000 electric SUVs over a coolant fault in Korea."] {
let spans = t.tag(s).unwrap();
eprintln!("L1 TAGGER | {s}\n {}", spans.iter().map(|x| format!("{}:{:?}",x.kind,x.text.trim())).collect::<Vec<_>>().join(" "));
}
}
#[cfg(feature="onnx")]
#[test]
fn layer3_projection() {
use steeldb::projectors::TextEngine;
let ml = std::path::PathBuf::from("models/step0_bundle_ml");
let splade = std::path::PathBuf::from("models/splade");
if !ml.join("spo.onnx").exists() { eprintln!("L3: no models"); return; }
let sp = if splade.join("splade.onnx").exists() { Some(splade.as_path()) } else { None };
let mut eng = TextEngine::load(&ml, sp).unwrap();
let (tokens, numbers) = eng.project_sentence("Toyota supplies a battery cell under SAE J1100 specs in Q3 2026.");
eprintln!("L3 PROJECTION tokens:\n {}\n numbers: {:?}", tokens.join(" "), numbers);
assert!(!tokens.is_empty());
}