use tatara_lisp_script::{Value, eval_str};
fn eval_str_field(src: &str) -> String {
match eval_str(src).unwrap_or_else(|e| panic!("script failed: {e}")) {
Value::Str(s) => s.to_string(),
other => panic!("expected a string, got {other:?}"),
}
}
fn eval_int_field(src: &str) -> i64 {
match eval_str(src).unwrap_or_else(|e| panic!("script failed: {e}")) {
Value::Int(n) => n,
other => panic!("expected an int, got {other:?}"),
}
}
#[test]
fn the_three_original_fields_are_unchanged() {
assert_eq!(
eval_str_field(r#"(alist-get (exec-capture "echo" "hi") "stdout" "")"#).trim(),
"hi"
);
assert_eq!(
eval_int_field(r#"(alist-get (exec-capture "true") "status" -99)"#),
0
);
assert_eq!(
eval_int_field(r#"(alist-get (exec-capture "false") "status" -99)"#),
1,
"a non-zero exit must still be reported as itself"
);
}
#[test]
fn program_records_what_was_asked_for() {
assert_eq!(
eval_str_field(r#"(alist-get (exec-capture "echo" "x") "program" "")"#),
"echo"
);
}
#[test]
fn resolved_answers_which_binary_actually_ran() {
let resolved = eval_str_field(r#"(alist-get (exec-capture "echo" "x") "resolved" "")"#);
assert!(
resolved.starts_with('/'),
"a bare program name must resolve to an absolute path, got {resolved:?}"
);
assert!(
resolved.ends_with("echo"),
"the resolved path must name the program, got {resolved:?}"
);
assert_ne!(
resolved, "echo",
"resolved must not merely echo the program back — that would render \
'resolved' and 'unresolved' as the same bytes"
);
}
#[test]
fn an_absolute_program_is_already_unambiguous() {
let resolved = eval_str_field(r#"(alist-get (exec-capture "/bin/echo" "x") "resolved" "")"#);
assert_eq!(resolved, "/bin/echo");
}
#[test]
fn argv_is_a_list_and_keeps_arguments_separate() {
let joined = eval_str_field(
r#"(string-join "|" (alist-get (exec-capture "echo" "a b" "c") "argv" (list)))"#,
);
assert_eq!(
joined, "echo|a b|c",
"argv must preserve argument boundaries, including a space INSIDE one"
);
}
#[test]
fn cwd_is_recorded_as_an_absolute_path() {
let cwd = eval_str_field(r#"(alist-get (exec-capture "true") "cwd" "")"#);
assert!(cwd.starts_with('/'), "cwd must be absolute, got {cwd:?}");
}
#[test]
fn duration_is_present_and_plausible() {
let fast = eval_int_field(r#"(alist-get (exec-capture "true") "duration-ms" -1)"#);
assert!(fast >= 0, "duration must be non-negative, got {fast}");
assert!(
fast < 60_000,
"`true` should not take a minute; got {fast}ms — suggests the clock is \
measuring the wrong span"
);
}
#[test]
fn sh_exec_records_that_a_SHELL_was_involved() {
assert_eq!(
eval_str_field(r#"(alist-get (sh-exec "echo hi") "program" "")"#),
"sh"
);
let joined =
eval_str_field(r#"(string-join "|" (alist-get (sh-exec "echo hi") "argv" (list)))"#);
assert_eq!(joined, "sh|-c|echo hi");
}
#[test]
fn every_capture_form_returns_the_same_field_set() {
for expr in [
r#"(exec-capture "echo" "x")"#,
r#"(exec-with-stdin "" "cat")"#,
r#"(exec-with-env (list (list "K" "V")) "echo" "x")"#,
r#"(sh-exec "echo x")"#,
] {
for field in [
"status",
"stdout",
"stderr",
"argv",
"program",
"resolved",
"cwd",
"duration-ms",
] {
let probe = format!(
r#"(if (equal? (alist-get {expr} "{field}" :MISSING) :MISSING) "MISSING" "present")"#
);
assert_eq!(
eval_str_field(&probe),
"present",
"{expr} is missing the {field} field"
);
}
}
}