use std::process::Command;
fn ilo() -> Command {
Command::new(env!("CARGO_BIN_EXE_ilo"))
}
fn run_args(args: &[&str]) -> String {
let out = ilo().args(args).output().expect("failed to run ilo");
assert!(
out.status.success(),
"ilo failed for {args:?}: stderr={}",
String::from_utf8_lossy(&out.stderr)
);
String::from_utf8_lossy(&out.stdout).trim().to_string()
}
fn write_src(name: &str, contents: &str) -> std::path::PathBuf {
let dir = std::env::temp_dir().join(format!("ilo_dot_var_idx_{name}"));
std::fs::create_dir_all(&dir).unwrap();
let p = dir.join("prog.ilo");
std::fs::write(&p, contents).unwrap();
p
}
const PARAM_SRC: &str = "pick xs:L n i:n>n;xs.i\n";
fn check_param(engine: &str) {
let p = write_src(
&format!("param_{}", engine.trim_start_matches('-')),
PARAM_SRC,
);
let s = run_args(&[p.to_str().unwrap(), engine, "pick", "[10,20,30]", "1"]);
assert_eq!(s, "20", "engine={engine}");
}
#[test]
fn param_index_tree() {
check_param("--run-tree");
}
#[test]
fn param_index_vm() {
check_param("--run-vm");
}
#[test]
#[cfg(feature = "cranelift")]
fn param_index_cranelift() {
check_param("--run-cranelift");
}
const RANGE_SRC: &str = "mysum xs:L n>n;s=0;@i 0..(len xs){v=xs.i;s=+s v};+s 0\n";
fn check_range(engine: &str) {
let p = write_src(
&format!("range_{}", engine.trim_start_matches('-')),
RANGE_SRC,
);
let s = run_args(&[p.to_str().unwrap(), engine, "mysum", "[10,20,30]"]);
assert_eq!(s, "60", "engine={engine}");
}
#[test]
fn range_index_tree() {
check_range("--run-tree");
}
#[test]
fn range_index_vm() {
check_range("--run-vm");
}
#[test]
#[cfg(feature = "cranelift")]
fn range_index_cranelift() {
check_range("--run-cranelift");
}
const LET_SRC: &str = "get-second xs:L n>n;i=1;xs.i\n";
fn check_let(engine: &str) {
let p = write_src(&format!("let_{}", engine.trim_start_matches('-')), LET_SRC);
let s = run_args(&[p.to_str().unwrap(), engine, "get-second", "[100,200,300]"]);
assert_eq!(s, "200", "engine={engine}");
}
#[test]
fn let_index_tree() {
check_let("--run-tree");
}
#[test]
fn let_index_vm() {
check_let("--run-vm");
}
#[test]
#[cfg(feature = "cranelift")]
fn let_index_cranelift() {
check_let("--run-cranelift");
}
const COLLISION_SRC: &str =
"type person{name:t;age:n}\n\ngreet name:t>t;p=person name:\"Alice\" age:30;p.name\n";
fn check_collision(engine: &str) {
let p = write_src(
&format!("collision_{}", engine.trim_start_matches('-')),
COLLISION_SRC,
);
let s = run_args(&[p.to_str().unwrap(), engine, "greet", "ignored"]);
assert_eq!(s, "Alice", "engine={engine}");
}
#[test]
fn collision_record_field_tree() {
check_collision("--run-tree");
}
#[test]
fn collision_record_field_vm() {
check_collision("--run-vm");
}
#[test]
#[cfg(feature = "cranelift")]
fn collision_record_field_cranelift() {
check_collision("--run-cranelift");
}
const NESTED_SRC: &str = "deep xss:L L n i:n j:n>n;row=xss.i;row.j\n";
#[test]
fn nested_chain_tree() {
let p = write_src("nested_tree", NESTED_SRC);
let s = run_args(&[
p.to_str().unwrap(),
"--run-tree",
"deep",
"[[1,2,3],[4,5,6],[7,8,9]]",
"1",
"2",
]);
assert_eq!(s, "6");
}
#[test]
fn nested_chain_vm() {
let p = write_src("nested_vm", NESTED_SRC);
let s = run_args(&[
p.to_str().unwrap(),
"--run-vm",
"deep",
"[[1,2,3],[4,5,6],[7,8,9]]",
"1",
"2",
]);
assert_eq!(s, "6");
}
#[test]
#[cfg(feature = "cranelift")]
fn nested_chain_cranelift() {
let p = write_src("nested_cl", NESTED_SRC);
let s = run_args(&[
p.to_str().unwrap(),
"--run-cranelift",
"deep",
"[[1,2,3],[4,5,6],[7,8,9]]",
"1",
"2",
]);
assert_eq!(s, "6");
}