#![allow(clippy::single_element_loop)]
use std::process::Command;
fn ilo() -> Command {
Command::new(env!("CARGO_BIN_EXE_ilo"))
}
fn run_ok(engine: &str, src: &str) -> String {
let out = ilo()
.args([src, engine, "f"])
.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()
}
fn run_err(engine: &str, src: &str) -> String {
let out = ilo()
.args([src, engine, "f"])
.output()
.expect("failed to run ilo");
assert!(
!out.status.success(),
"ilo {engine} unexpectedly succeeded for `{src}`: stdout={}",
String::from_utf8_lossy(&out.stdout)
);
format!(
"{}{}",
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
)
}
fn check_all_str(src: &str, expected: &str) {
assert_eq!(run_ok("--vm", src), expected, "vm engine");
#[cfg(feature = "cranelift")]
assert_eq!(run_ok("--jit", src), expected, "cranelift engine");
}
fn check_all_err(src: &str, needle: &str) {
let err_vm = run_err("--vm", src);
assert!(
err_vm.contains(needle),
"vm: expected {needle:?} in: {err_vm}"
);
}
#[test]
fn matvec_identity_3x3() {
check_all_str(
"f>L n;matvec [[1,0,0],[0,1,0],[0,0,1]] [4,5,6]",
"[4, 5, 6]",
);
}
#[test]
fn matvec_2x2_basic() {
check_all_str("f>L n;matvec [[1,2],[3,4]] [5,6]", "[17, 39]");
}
#[test]
fn matvec_2x3() {
check_all_str("f>L n;matvec [[1,2,3],[4,5,6]] [7,8,9]", "[50, 122]");
}
#[test]
fn matvec_1x1() {
check_all_str("f>L n;matvec [[3]] [4]", "[12]");
}
#[test]
fn matvec_negatives_and_zeros() {
check_all_str("f>L n;matvec [[1,-1],[0,2]] [3,4]", "[-1, 8]");
}
#[test]
fn matvec_matches_flatten_matmul_ceremony() {
let direct = run_ok("--vm", "f>L n;matvec [[1,2,3],[4,5,6]] [7,8,9]");
let ceremony = run_ok(
"--vm",
"f>L n;flat (matmul [[1,2,3],[4,5,6]] (map (y:n>L n;[y]) [7,8,9]))",
);
assert_eq!(direct, ceremony, "matvec must match flat+matmul ceremony");
}
#[test]
fn matvec_dim_mismatch_errors() {
check_all_err("f>L n;matvec [[1,2,3],[4,5,6]] [1,2]", "matvec");
}
#[test]
fn matvec_empty_matrix_errors() {
let err = run_err("--vm", "f>L n;matvec [] []");
assert!(
err.contains("matvec") || err.contains("ILO-"),
"expected matvec error, got: {err}"
);
}
#[test]
fn matvec_ragged_rows_errors() {
check_all_err("f>L n;matvec [[1,2,3],[4,5]] [1,2,3]", "matvec");
}