use nightjar_lang::{parse, NightjarLanguageError};
#[test]
fn accepts_simple_verifier() {
parse("(GT 1 2)").expect("should parse");
}
#[test]
fn rejects_verifier_arity_mismatch() {
let err = parse("(GT 1 2 3)").unwrap_err();
assert!(
matches!(
err,
NightjarLanguageError::ArgumentError { .. } | NightjarLanguageError::ParseError { .. }
),
"got {:?}",
err
);
}
#[test]
fn accepts_nested_connective_with_verifiers() {
parse("(AND (GT 1 0) (LT 1 10))").expect("should parse");
}
#[test]
fn accepts_forall_with_partial_verifier() {
parse("(ForAll (GT 0) .ids)").expect("should parse");
}
#[test]
fn accepts_exists_with_nonempty_predicate() {
parse("(Exists NonEmpty .names)").expect("should parse");
}
#[test]
fn rejects_missing_parens_for_multi_arg_operator() {
let err = parse("GT 1 2").unwrap_err();
assert!(matches!(err, NightjarLanguageError::ParseError { .. }));
}
#[test]
fn accepts_root_symbol() {
parse("(NonEmpty .)").expect("should parse");
}
#[test]
fn accepts_not_expression() {
parse("(NOT (EQ .status \"inactive\"))").expect("should parse");
}
#[test]
fn accepts_nested_arithmetic_in_verifier() {
parse("(EQ (Add (Mul 2 3) (Sub 10 4)) 12)").expect("should parse");
}
#[test]
fn accepts_negative_literals() {
parse("(GT -5 -10)").expect("should parse");
}
#[test]
fn accepts_unicode_symbol() {
parse("(EQ .數量 100)").expect("should parse");
}
#[test]
fn accepts_unicode_string_literal() {
parse("(EQ .name \"紅嘴黑鵯\")").expect("should parse");
}
#[test]
fn top_level_bool_literal_parses() {
parse("True").expect("should parse");
parse("False").expect("should parse");
}
#[test]
fn combined_examples() {
for src in [
"(GE .revenue 0)",
"(NonEmpty .)",
"(EQ (Add .dept1_revenue .dept2_revenue) .total_revenue)",
"(AND (GE .revenue 0) (LT .revenue 1000000))",
"(NOT (EQ .status \"inactive\"))",
"(ForAll (GT 0) .scores)",
"(Exists NonEmpty .names)",
"(ForAll (GE 0) (GetValues .revenue_by_dept))",
"(AND (ForAll (GT 0) .scores) (GT (Count .scores) 3))",
] {
parse(src).unwrap_or_else(|e| panic!("failed to parse `{}`: {:?}", src, e));
}
}