use std::process::Command;
fn ilo() -> Command {
Command::new(env!("CARGO_BIN_EXE_ilo"))
}
fn write_src(name: &str, src: &str) -> std::path::PathBuf {
use std::sync::atomic::{AtomicU64, Ordering};
static COUNTER: AtomicU64 = AtomicU64::new(0);
let n = COUNTER.fetch_add(1, Ordering::Relaxed);
let mut path = std::env::temp_dir();
path.push(format!("ilo_mpairs_{name}_{}_{n}.ilo", std::process::id()));
std::fs::write(&path, src).expect("write src");
path
}
fn run_ok(engine: &str, src: &str, entry: &str) -> String {
let path = write_src(entry, src);
let mut cmd = ilo();
cmd.arg(&path).arg(engine).arg(entry);
let out = cmd.output().expect("failed to run ilo");
let _ = std::fs::remove_file(&path);
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_all(src: &str, entry: &str, expected: &str) {
let engines: &[&str] = if cfg!(feature = "cranelift") {
&["--run-vm", "--jit"]
} else {
&["--run-vm"]
};
for engine in engines {
let actual = run_ok(engine, src, entry);
assert_eq!(
actual, expected,
"engine {engine} produced {actual:?}, expected {expected:?} for src `{src}`"
);
}
}
const MPAIRS_BASIC: &str =
"f>L (L _)\n m = mset (mset (mset mmap \"b\" 2) \"a\" 1) \"c\" 3\n mpairs m\n";
#[test]
fn mpairs_basic_sorted_pairs() {
run_all(MPAIRS_BASIC, "f", "[[a, 1], [b, 2], [c, 3]]");
}
const MPAIRS_INVARIANT: &str =
"f>L (L _)\n m = mset (mset (mset (mset mmap \"q\" 4) \"a\" 1) \"m\" 3) \"b\" 2\n mpairs m\n";
#[test]
fn mpairs_invariant_matches_mkeys_mvals_output() {
run_all(MPAIRS_INVARIANT, "f", "[[a, 1], [b, 2], [m, 3], [q, 4]]");
}
const MPAIRS_ZIP_EQUIV: &str = "f>L (L _)\n m = mset (mset (mset (mset mmap \"q\" 4) \"a\" 1) \"m\" 3) \"b\" 2\n zip (mkeys m) (mvals m)\n";
#[test]
fn mpairs_invariant_zip_form_matches() {
run_all(MPAIRS_ZIP_EQUIV, "f", "[[a, 1], [b, 2], [m, 3], [q, 4]]");
}
const MPAIRS_EMPTY: &str = "f>L (L _)\n mpairs mmap\n";
#[test]
fn mpairs_empty_map() {
run_all(MPAIRS_EMPTY, "f", "[]");
}
const MPAIRS_SINGLE: &str = "f>L (L _)\n mpairs (mset mmap \"k\" 42)\n";
#[test]
fn mpairs_single_entry() {
run_all(MPAIRS_SINGLE, "f", "[[k, 42]]");
}
const MPAIRS_NUMERIC_KEYS: &str =
"f>L (L _)\n m = mset (mset (mset mmap 10 \"a\") 2 \"b\") 5 \"c\"\n mpairs m\n";
#[test]
fn mpairs_numeric_keys_sort_numerically() {
run_all(MPAIRS_NUMERIC_KEYS, "f", "[[2, b], [5, c], [10, a]]");
}
const MPAIRS_AFTER_MDEL: &str =
"f>L (L _)\n m = mset (mset (mset mmap \"a\" 1) \"b\" 2) \"c\" 3\n mpairs (mdel m \"b\")\n";
#[test]
fn mpairs_after_mdel_drops_entry() {
run_all(MPAIRS_AFTER_MDEL, "f", "[[a, 1], [c, 3]]");
}