use std::process::Command;
fn ilo() -> Command {
Command::new(env!("CARGO_BIN_EXE_ilo"))
}
fn run_args(args: &[&str]) -> (bool, String, String) {
let out = ilo()
.args(args)
.output()
.unwrap_or_else(|e| panic!("failed to spawn ilo: {e}"));
let stdout = String::from_utf8_lossy(&out.stdout).to_string();
let stderr = String::from_utf8_lossy(&out.stderr).to_string();
(out.status.success(), stdout, stderr)
}
fn write_temp_ilo(content: &str) -> (tempfile::TempDir, std::path::PathBuf) {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("test.ilo");
std::fs::write(&path, content).expect("write temp ilo");
(dir, path)
}
#[test]
fn run_tree_flag_after_code_before_func() {
let (ok, stdout, stderr) = run_args(&["f>n;5", "--run-tree", "f"]);
assert!(ok, "canonical placement should work; stderr: {stderr}");
assert_eq!(stdout.trim(), "5");
}
#[test]
fn run_tree_flag_after_func() {
let (ok, stdout, stderr) = run_args(&["f>n;5", "f", "--run-tree"]);
assert!(ok, "trailing --run-tree should work; stderr: {stderr}");
assert_eq!(stdout.trim(), "5");
}
#[test]
fn run_tree_flag_before_code() {
let (ok, stdout, stderr) = run_args(&["--run-tree", "f>n;5", "f"]);
assert!(ok, "leading --run-tree should work; stderr: {stderr}");
assert_eq!(stdout.trim(), "5");
}
#[test]
fn run_vm_flag_after_code_before_func() {
let (ok, stdout, stderr) = run_args(&["f x:n>n;*x 2", "--run-vm", "f", "5"]);
assert!(ok, "stderr: {stderr}");
assert_eq!(stdout.trim(), "10");
}
#[test]
fn run_vm_flag_after_func() {
let (ok, stdout, stderr) = run_args(&["f x:n>n;*x 2", "f", "5", "--run-vm"]);
assert!(ok, "stderr: {stderr}");
assert_eq!(stdout.trim(), "10");
}
#[test]
fn run_vm_flag_before_code() {
let (ok, stdout, stderr) = run_args(&["--run-vm", "f x:n>n;*x 2", "f", "5"]);
assert!(ok, "stderr: {stderr}");
assert_eq!(stdout.trim(), "10");
}
#[test]
fn run_cranelift_flag_after_func_accepted() {
let (_ok, _stdout, stderr) = run_args(&["f>n;5", "f", "--jit"]);
assert!(
!stderr.contains("Usage:") && !stderr.contains("unknown flag"),
"--jit trailing should be parsed; stderr: {stderr}"
);
}
#[test]
fn run_cranelift_flag_before_code_accepted() {
let (_ok, _stdout, stderr) = run_args(&["--jit", "f>n;5", "f"]);
assert!(
!stderr.contains("Usage:") && !stderr.contains("unknown flag"),
"--jit leading should be parsed; stderr: {stderr}"
);
}
#[test]
fn run_tree_flag_after_file_path() {
let (_dir, path) = write_temp_ilo("main>n;5");
let (ok, stdout, stderr) = run_args(&[path.to_str().unwrap(), "--run-tree", "main"]);
assert!(ok, "stderr: {stderr}");
assert_eq!(stdout.trim(), "5");
}
#[test]
fn run_tree_flag_before_file_path() {
let (_dir, path) = write_temp_ilo("main>n;5");
let (ok, stdout, stderr) = run_args(&["--run-tree", path.to_str().unwrap(), "main"]);
assert!(ok, "stderr: {stderr}");
assert_eq!(stdout.trim(), "5");
}
#[test]
fn run_tree_flag_trailing_after_file_and_func() {
let (_dir, path) = write_temp_ilo("main>n;5");
let (ok, stdout, stderr) = run_args(&[path.to_str().unwrap(), "main", "--run-tree"]);
assert!(ok, "stderr: {stderr}");
assert_eq!(stdout.trim(), "5");
}
#[test]
fn conflicting_run_flags_error() {
let (ok, _stdout, stderr) = run_args(&["--run-tree", "--run-vm", "f>n;5", "f"]);
assert!(!ok, "conflicting engine flags should error");
assert!(
stderr.contains("mutually exclusive"),
"should mention mutual exclusion; stderr: {stderr}"
);
}
#[test]
fn conflicting_run_flags_trailing_error() {
let (ok, _stdout, stderr) = run_args(&["f>n;5", "f", "--run-tree", "--run-vm"]);
assert!(!ok, "conflicting engine flags should error");
assert!(
stderr.contains("mutually exclusive"),
"should mention mutual exclusion; stderr: {stderr}"
);
}
#[test]
fn repeated_same_run_flag_ok() {
let (ok, stdout, stderr) = run_args(&["--run-tree", "f>n;5", "f", "--run-tree"]);
assert!(
ok,
"repeating the same engine flag should not conflict; stderr: {stderr}"
);
assert_eq!(stdout.trim(), "5");
}
#[test]
fn run_alias_trailing() {
let (ok, stdout, stderr) = run_args(&["f>n;5", "f", "--run"]);
assert!(ok, "stderr: {stderr}");
assert_eq!(stdout.trim(), "5");
}
#[test]
fn run_alias_leading() {
let (ok, stdout, stderr) = run_args(&["--run", "f>n;5", "f"]);
assert!(ok, "stderr: {stderr}");
assert_eq!(stdout.trim(), "5");
}
#[test]
fn run_subcommand_path_unchanged() {
let (ok, stdout, stderr) = run_args(&["run", "--run-tree", "f>n;5", "f"]);
assert!(
ok,
"clap subcommand path should still work; stderr: {stderr}"
);
assert_eq!(stdout.trim(), "5");
}