use std::process::Command;
use std::sync::atomic::{AtomicU64, Ordering};
fn ilo() -> Command {
Command::new(env!("CARGO_BIN_EXE_ilo"))
}
fn run_inline(engine: &str, src: &str, entry: &str) -> String {
static COUNTER: AtomicU64 = AtomicU64::new(0);
let seq = COUNTER.fetch_add(1, Ordering::SeqCst);
let path = std::env::temp_dir().join(format!("ilo_mget_or_{}_{}.ilo", std::process::id(), seq));
std::fs::write(&path, src).unwrap();
let out = ilo()
.args([path.to_str().unwrap(), engine, entry])
.output()
.expect("failed to run ilo");
assert!(
out.status.success(),
"ilo {engine} failed for `{src}`: stderr={}",
String::from_utf8_lossy(&out.stderr)
);
String::from_utf8_lossy(&out.stdout).trim().to_string()
}
fn run_inline_expect_err(engine: &str, src: &str) -> String {
static COUNTER: AtomicU64 = AtomicU64::new(0);
let seq = COUNTER.fetch_add(1, Ordering::SeqCst);
let path = std::env::temp_dir().join(format!(
"ilo_mget_or_err_{}_{}.ilo",
std::process::id(),
seq
));
std::fs::write(&path, src).unwrap();
let out = ilo()
.args([path.to_str().unwrap(), engine])
.output()
.expect("failed to run ilo");
assert!(
!out.status.success(),
"expected failure but ilo {engine} succeeded for `{src}`"
);
String::from_utf8_lossy(&out.stderr).to_string()
}
fn check(engine: &str) {
assert_eq!(
run_inline(engine, r#"f>n;m=mset mmap "k" 5;mget-or m "k" 0"#, "f"),
"5",
"mget-or text-key hit [{engine}]"
);
assert_eq!(
run_inline(engine, r#"f>n;m=mmap;mget-or m "missing" 99"#, "f"),
"99",
"mget-or text-key miss [{engine}]"
);
assert_eq!(
run_inline(engine, r#"f>t;m=mmap;mget-or m "k" "fallback""#, "f"),
"fallback",
"mget-or text-val miss [{engine}]"
);
assert_eq!(
run_inline(
engine,
r#"f>t;m=mset mmap 7 "seven";mget-or m 7 "default""#,
"f"
),
"seven",
"mget-or num-key hit [{engine}]"
);
assert_eq!(
run_inline(
engine,
r#"f>t;m=mset mmap 7 "seven";mget-or m 8 "default""#,
"f"
),
"default",
"mget-or num-key miss [{engine}]"
);
}
#[test]
fn mget_or_vm() {
check("--run-vm");
}
#[cfg(feature = "cranelift")]
#[test]
fn mget_or_cranelift() {
check("--jit");
}
#[test]
fn mget_or_default_type_mismatch_rejected() {
let src = r#"f>n;m=mset mmap "k" 5;mget-or m "k" "x""#;
let stderr = run_inline_expect_err("--run-vm", src);
assert!(
stderr.contains("ILO-T013"),
"expected ILO-T013 for mget-or default type mismatch, got: {stderr}"
);
assert!(
stderr.contains("mget-or"),
"expected message to mention mget-or, got: {stderr}"
);
}