use serde_json::json;
use test_case::test_case;
use crate::{Ctx, Value};
#[test_case(
0.to_string().as_str()
=> json!(0);
"int zero"
)]
#[test_case(
1.to_string().as_str()
=> json!(1);
"int one"
)]
#[test_case(
(-1).to_string().as_str()
=> json!(-1);
"int minus one"
)]
#[test_case(
i32::MAX.to_string().as_str()
=> json!(2_147_483_647);
"int max"
)]
#[test_case(
i32::MIN.to_string().as_str()
=> json!(-2_147_483_648);
"int min"
)]
#[test_case(
true.to_string().as_str()=>
json!(true);
"true boolean"
)]
#[test_case(
false.to_string().as_str()
=> json!(false);
"false boolean"
)]
#[test_case(
0.0.to_string().as_str()
=> json!(0);
"double zero"
)]
#[test_case(
1.5.to_string().as_str()
=> json!(1.5);
"double positive"
)]
#[test_case(
(-1.5).to_string().as_str()
=> json!(-1.5);
"double negative"
)]
#[test_case(
f32::MAX.to_string().as_str()
=> json!(3.402_823_5e38_f64);
"double max"
)]
#[test_case(
f32::MIN.to_string().as_str()
=> json!(-3.402_823_5e38_f64);
"double min"
)]
#[test_case(
r#""""#
=> json!("");
"empty"
)]
#[test_case(
r#""hello""#
=> json!("hello");
"ascii"
)]
#[test_case(
r#""🦀 rust""#
=> json!("🦀 rust");
"unicode"
)]
fn value_test(val: &str) -> serde_json::Value {
let ctx = Ctx::new().unwrap();
let v = Value::compile_string(&ctx, val).unwrap();
let v_from_bytes = Value::compile_bytes(&ctx, val.as_bytes()).unwrap();
assert_eq!(v, v_from_bytes);
let v_json = serde_json::from_slice::<serde_json::Value>(&v.to_json_bytes().unwrap()).unwrap();
let v_from_bytes_json =
serde_json::from_slice::<serde_json::Value>(&v.to_json_bytes().unwrap()).unwrap();
assert_eq!(v_json, v_from_bytes_json);
v_json
}
#[test_case("42", "42" => json!(42); "identical ints")]
#[test_case("true", "bool" => json!(true); "bool value meets bool type")]
#[test_case(r#""hello""#, "string" => json!("hello"); "string value meets string type")]
#[test_case("1.5", "number" => json!(1.5); "float value meets number type")]
#[test_case(">0", "42" => json!(42); "constraint meets concrete int")]
fn value_unify_test(
a: &str,
b: &str,
) -> serde_json::Value {
let ctx = Ctx::new().unwrap();
let va = Value::compile_string(&ctx, a).unwrap();
let vb = Value::compile_string(&ctx, b).unwrap();
let v = Value::unify(&va, &vb);
serde_json::from_slice::<serde_json::Value>(&v.to_json_bytes().unwrap()).unwrap()
}
#[test_case("1", "2" ; "conflicting ints produce bottom")]
#[test_case(r#""a""#, r#""b""# ; "conflicting strings produce bottom")]
fn value_unify_bottom_test(
a: &str,
b: &str,
) {
let ctx = Ctx::new().unwrap();
let va = Value::compile_string(&ctx, a).unwrap();
let vb = Value::compile_string(&ctx, b).unwrap();
assert!(Value::unify(&va, &vb).is_valid().is_err());
}
#[test_case("42" => true; "int is valid")]
#[test_case("true" => true; "bool is valid")]
#[test_case("1.5" => true; "float is valid")]
#[test_case(r#""hello""# => true; "string is valid")]
#[test_case("_|_" => false; "bottom is invalid")]
#[test_case("1 & 2" => false; "conflicting unification is invalid")]
fn value_valid_test(src: &str) -> bool {
let ctx = Ctx::new().unwrap();
match Value::compile_string(&ctx, src) {
Err(_) => false,
Ok(v) => v.is_valid().is_ok(),
}
}