use std::sync::Arc;
use cljrs_reader::Parser;
use cljrs_runtime::env::env::{Env, GlobalEnv};
use cljrs_value::Value;
fn make_env() -> (Arc<GlobalEnv>, Env) {
let globals = cljrs_runtime::Runtime::builder()
.execution_mode(cljrs_runtime::ExecutionMode::TreeWalk)
.build()
.expect("runtime")
.into_globals();
let env = Env::new(globals.clone(), "user");
(globals, env)
}
fn eval_fresh(src: &str) -> Result<Value, String> {
let (_, mut env) = make_env();
let mut parser = Parser::new(src.to_string(), "<test>".to_string());
let forms = parser.parse_all().map_err(|e| format!("parse: {e:?}"))?;
let mut result = Value::Nil;
for form in forms {
result = cljrs_runtime::interp::eval::eval(&form, &mut env)
.map_err(|e| format!("eval: {e:?}"))?;
}
Ok(result)
}
fn value_of(src: &str) -> Value {
eval_fresh(src).unwrap_or_else(|e| panic!("{src}\n{e}"))
}
const PRESENT: &str = "PATH";
#[test]
fn reads_a_variable_that_is_set() {
let expected = std::env::var(PRESENT).expect("test host has no PATH");
assert_eq!(
value_of(&format!(r#"(System/getenv "{PRESENT}")"#)),
Value::string(expected)
);
}
#[test]
fn an_unset_variable_is_nil() {
let absent = "CLJRS_GETENV_TEST_DEFINITELY_UNSET";
assert!(std::env::var(absent).is_err(), "test premise broken");
assert_eq!(
value_of(&format!(r#"(System/getenv "{absent}")"#)),
Value::Nil
);
}
#[test]
fn the_no_arg_form_returns_the_environment_as_a_map() {
let expected = std::env::var(PRESENT).expect("test host has no PATH");
assert_eq!(
value_of(&format!(r#"(get (System/getenv) "{PRESENT}")"#)),
Value::string(expected)
);
}
#[test]
fn a_non_string_name_is_a_type_error() {
let err = eval_fresh("(System/getenv :PATH)").expect_err("keyword name");
assert!(
err.contains("string") || err.contains("WrongType"),
"unhelpful error: {err}"
);
}