use std::process::Command;
fn ilo() -> Command {
Command::new(env!("CARGO_BIN_EXE_ilo"))
}
fn run(engine: &str, src: &str, entry: &str) -> String {
let out = ilo()
.args([src, 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 BASIC_SRC: &str = "f>L n;range 0 5";
fn check_basic(engine: &str) {
assert_eq!(
run(engine, BASIC_SRC, "f"),
"[0, 1, 2, 3, 4]",
"engine={engine}"
);
}
#[test]
fn range_basic_tree() {
check_basic("--run-tree");
}
#[test]
fn range_basic_vm() {
check_basic("--run-vm");
}
#[test]
#[cfg(feature = "cranelift")]
fn range_basic_cranelift() {
check_basic("--jit");
}
const EMPTY_SRC: &str = "f>L n;range 3 3";
fn check_empty(engine: &str) {
assert_eq!(run(engine, EMPTY_SRC, "f"), "[]", "engine={engine}");
}
#[test]
fn range_empty_tree() {
check_empty("--run-tree");
}
#[test]
fn range_empty_vm() {
check_empty("--run-vm");
}
#[test]
#[cfg(feature = "cranelift")]
fn range_empty_cranelift() {
check_empty("--jit");
}
const FLIPPED_SRC: &str = "f>L n;range 5 3";
fn check_flipped(engine: &str) {
assert_eq!(run(engine, FLIPPED_SRC, "f"), "[]", "engine={engine}");
}
#[test]
fn range_flipped_tree() {
check_flipped("--run-tree");
}
#[test]
fn range_flipped_vm() {
check_flipped("--run-vm");
}
#[test]
#[cfg(feature = "cranelift")]
fn range_flipped_cranelift() {
check_flipped("--jit");
}
const NEG_SRC: &str = "f>L n;range -2 3";
fn check_neg(engine: &str) {
assert_eq!(
run(engine, NEG_SRC, "f"),
"[-2, -1, 0, 1, 2]",
"engine={engine}"
);
}
#[test]
fn range_neg_tree() {
check_neg("--run-tree");
}
#[test]
fn range_neg_vm() {
check_neg("--run-vm");
}
#[test]
#[cfg(feature = "cranelift")]
fn range_neg_cranelift() {
check_neg("--jit");
}
const GAUSS_SRC: &str = "f>n;sum (range 0 11)";
fn check_gauss(engine: &str) {
assert_eq!(run(engine, GAUSS_SRC, "f"), "55", "engine={engine}");
}
#[test]
fn range_gauss_tree() {
check_gauss("--run-tree");
}
const FRAC_SRC: &str = "f>L n;range 1.9 4.9";
fn check_frac_errors(engine: &str) {
let out = ilo()
.args([FRAC_SRC, engine, "f"])
.output()
.expect("failed to run ilo");
assert!(
!out.status.success(),
"engine={engine}: expected range 1.9 4.9 to error, got stdout={}",
String::from_utf8_lossy(&out.stdout)
);
let err = String::from_utf8_lossy(&out.stderr);
assert!(
err.contains("integer") || err.contains("bounds"),
"engine={engine}: stderr={err}"
);
}
#[test]
fn range_fractional_bounds_error_tree() {
check_frac_errors("--run-tree");
}
#[test]
fn range_fractional_bounds_error_vm() {
check_frac_errors("--run-vm");
}