use rayforce::{Runtime, TcpClient, Value};
#[test]
fn values_built_in_a_scope_are_dropped_with_it() {
Runtime::scope(|_rt| {
let vals: Vec<Value> = (0..64).map(Value::i64).collect();
let list = Value::list(&vals);
let vec = Value::vec(&[1i64, 2, 3]);
let cloned = vec.clone();
assert_eq!(list.len(), 64);
assert_eq!(cloned.as_slice::<i64>().unwrap(), &[1, 2, 3]);
Ok(())
})
.unwrap();
}
#[test]
fn the_error_path_still_tears_down() {
let r = Runtime::scope(|rt| Err::<(), _>(rt.eval("(undefined_name_xyz)").unwrap_err()));
assert!(r.is_err());
assert_eq!(Runtime::scope(|rt| rt.eval("1")?.as_i64()).unwrap(), 1);
}
#[test]
fn a_panic_in_the_closure_still_tears_down() {
let caught = std::panic::catch_unwind(|| {
Runtime::scope(|_rt| -> rayforce::Result<()> {
panic!("deliberate");
})
});
assert!(caught.is_err(), "the panic must propagate");
assert_eq!(Runtime::scope(|rt| rt.eval("2")?.as_i64()).unwrap(), 2);
}
#[test]
fn value_is_one_pointer_wide() {
assert_eq!(
std::mem::size_of::<Value>(),
std::mem::size_of::<*mut ()>(),
"Value grew a field — did a liveness tag creep back?"
);
}
#[test]
fn a_refused_connection_leaves_the_scope_usable() {
Runtime::scope(|rt| {
assert!(TcpClient::connect("127.0.0.1", 1, "", "").is_err());
assert_eq!(rt.eval("(+ 1 1)")?.as_i64()?, 2);
Ok(())
})
.unwrap();
Runtime::scope(|rt| rt.eval("1")?.as_i64()).unwrap();
}
#[test]
fn eval_off_the_runtime_thread_is_refused() {
Runtime::scope(|rt| {
assert_eq!(rt.eval("(+ 1 1)")?.as_i64()?, 2);
let off = std::thread::spawn(|| rayforce::eval("(+ 1 1)").map(|v| v.as_i64())).join();
assert!(
off.is_err(),
"eval off the runtime's thread must be refused, not dispatched"
);
Ok(())
})
.unwrap();
}
#[test]
fn construction_off_the_runtime_thread_is_refused() {
Runtime::scope(|_rt| {
assert_eq!(Value::sym("hello").as_sym()?, "hello");
let off = std::thread::spawn(|| Value::sym("hello").as_sym()).join();
assert!(
off.is_err(),
"constructing off the runtime's thread must be refused"
);
Ok(())
})
.unwrap();
}
#[test]
fn a_second_thread_cannot_start_a_runtime() {
Runtime::scope(|rt| {
let nested = std::thread::spawn(|| Runtime::scope(|rt| rt.eval("1")?.as_i64()))
.join()
.expect("the second thread must be refused, not crash");
assert!(nested.is_err(), "a second runtime must not be creatable");
assert_eq!(rt.eval("(+ 2 3)")?.as_i64()?, 5);
Ok(())
})
.unwrap();
}