use std::process::Command;
fn ilo() -> Command {
Command::new(env!("CARGO_BIN_EXE_ilo"))
}
fn run_file(engine: &str, src: &str, entry: &str) -> String {
use std::sync::atomic::{AtomicU64, Ordering};
static COUNTER: AtomicU64 = AtomicU64::new(0);
let seq = COUNTER.fetch_add(1, Ordering::SeqCst);
let path = std::env::temp_dir().join(format!(
"ilo_mget_default_{}_{}.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()
}
const LITERAL_HIT: &str = r#"f>n;m=mset mmap "k" 5;mget m "k" ?? 0"#;
const LITERAL_MISS: &str = r#"f>n;m=mmap;mget m "missing" ?? 99"#;
const VARKEY_HIT: &str = r#"f>n;m=mset mmap "k" 5;k="k";mget m k ?? 0"#;
const VARKEY_MISS: &str = r#"f>n;em=mmap;k="x";mget em k ?? 0"#;
const TEXT_HIT: &str = r#"f>t;m=mset mmap "k" "hi";mget m "k" ?? "default""#;
const TEXT_MISS: &str = r#"f>t;m=mmap;mget m "absent" ?? "default""#;
const PATHKEY_HIT: &str = r#"f>n;m=mset mmap "k" 5;ks=["k"];mget m ks.0 ?? 0"#;
const CALLKEY_HIT: &str = r#"f>n;m=mset mmap "5" 7;mget m str 5 ?? 0"#;
const PARENKEY_HIT: &str = r#"f>n;m=mset mmap "5" 7;mget m (str 5) ?? 0"#;
const CHAIN_FIRST_HIT: &str = r#"f>n;m=mset mmap "a" 1;mget m "a" ?? mget m "b" ?? 99"#;
const CHAIN_SECOND_HIT: &str = r#"f>n;m=mset mmap "b" 2;mget m "a" ?? mget m "b" ?? 99"#;
const CHAIN_BOTH_MISS: &str = r#"f>n;m=mmap;mget m "a" ?? mget m "b" ?? 99"#;
const CHAIN_NO_DEFAULT_HIT: &str = r#"f>O n;m=mset mmap "a" 1;mget m "a" ?? mget m "b""#;
const CHAIN_NO_DEFAULT_MISS: &str = r#"f>O n;m=mset mmap "b" 2;mget m "a" ?? mget m "b""#;
const CHAIN_AT_FIRST_HIT: &str = r#"f>n;xs=[10 20 30];at xs 0 ?? at xs 1 ?? 0"#;
const CHAIN_AT_SECOND_HIT: &str = r#"f>n;xs=[10 20 30];at xs 1 ?? at xs 2 ?? 0"#;
fn check_all(engine: &str) {
assert_eq!(
run_file(engine, LITERAL_HIT, "f"),
"5",
"literal hit engine={engine}"
);
assert_eq!(
run_file(engine, LITERAL_MISS, "f"),
"99",
"literal miss engine={engine}"
);
assert_eq!(
run_file(engine, VARKEY_HIT, "f"),
"5",
"varkey hit engine={engine}"
);
assert_eq!(
run_file(engine, VARKEY_MISS, "f"),
"0",
"varkey miss engine={engine}"
);
assert_eq!(
run_file(engine, TEXT_HIT, "f"),
"hi",
"text hit engine={engine}"
);
assert_eq!(
run_file(engine, TEXT_MISS, "f"),
"default",
"text miss engine={engine}"
);
assert_eq!(
run_file(engine, PATHKEY_HIT, "f"),
"5",
"pathkey hit engine={engine}"
);
assert_eq!(
run_file(engine, CALLKEY_HIT, "f"),
"7",
"callkey hit engine={engine}"
);
assert_eq!(
run_file(engine, PARENKEY_HIT, "f"),
"7",
"parenkey hit engine={engine}"
);
assert_eq!(
run_file(engine, CHAIN_FIRST_HIT, "f"),
"1",
"chain first hit engine={engine}"
);
assert_eq!(
run_file(engine, CHAIN_SECOND_HIT, "f"),
"2",
"chain second hit engine={engine}"
);
assert_eq!(
run_file(engine, CHAIN_BOTH_MISS, "f"),
"99",
"chain both miss engine={engine}"
);
assert_eq!(
run_file(engine, CHAIN_NO_DEFAULT_HIT, "f"),
"1",
"chain no-default hit engine={engine}"
);
assert_eq!(
run_file(engine, CHAIN_NO_DEFAULT_MISS, "f"),
"2",
"chain no-default miss engine={engine}"
);
assert_eq!(
run_file(engine, CHAIN_AT_FIRST_HIT, "f"),
"10",
"chain at first hit engine={engine}"
);
assert_eq!(
run_file(engine, CHAIN_AT_SECOND_HIT, "f"),
"20",
"chain at second hit engine={engine}"
);
}
#[test]
fn mget_default_tree() {
check_all("--run-tree");
}
#[test]
fn mget_default_vm() {
check_all("--run-vm");
}
#[test]
#[cfg(feature = "cranelift")]
fn mget_default_cranelift() {
check_all("--run-cranelift");
}