use asdi::features::{
FeatureSet, FEATURE_COMPARISONS, FEATURE_CONSTRAINTS, FEATURE_DISJUNCTION, FEATURE_NEGATION,
};
use asdi::Program;
mod common;
use common::{quick_parser_check, quick_parser_check_with_options};
#[test]
fn test_parse_comments() {
quick_parser_check(
r#".infer ancestor(string,string).
% Here's a comment
?- ancestor(xerces, X). % and another
"#,
None,
);
}
#[test]
fn test_parse_nothing() {
quick_parser_check("", Program::default());
}
#[test]
fn test_parse_string_fact() {
quick_parser_check("human(\"Socrates\").", None);
}
#[test]
fn test_parse_number_fact() {
quick_parser_check("age(socrates, 42).", None);
}
#[test]
fn test_parse_boolean_fact_t() {
quick_parser_check("deceased(socrates, true).", None);
}
#[test]
fn test_parse_boolean_fact_f() {
quick_parser_check("deceased(socrates, false).", None);
}
#[test]
fn test_parse_identifier_fact() {
quick_parser_check("edge(a, b).", None);
}
#[test]
fn test_parse_one_rule_turnstile() {
quick_parser_check("mortal(X) :- human(X).", None);
}
#[test]
#[should_panic]
fn test_parse_rule_expression_fail() {
quick_parser_check("old(X) :- human(X), X > 50.", None);
}
#[test]
fn test_parse_one_rule_unicode_arrow() {
quick_parser_check("mortal(X) ⟵ human(X).", None);
}
#[test]
fn test_parse_one_rule_ascii_arrow() {
quick_parser_check("mortal(X) <- human(X).", None);
}
#[test]
fn test_parse_one_rule_multiples_unicode_and() {
quick_parser_check("path(X, Y) ⟵ edge(X, Z) ∧ path(Z, Y).", None);
}
#[test]
fn test_parse_one_rule_multiples_comma() {
quick_parser_check("path(X, Y) ⟵ edge(X, Z), path(Z, Y).", None);
}
#[test]
fn test_parse_one_rule_multiples_ampersand() {
quick_parser_check("path(X, Y) ⟵ edge(X, Z) & path(Z, Y).", None);
}
#[test]
fn test_parse_one_rule_multiples_and() {
quick_parser_check("path(X, Y) ⟵ edge(X, Z) AND path(Z, Y).", None);
}
#[test]
fn test_parse_query_prefixed() {
quick_parser_check(".infer path(string, string). ?- path(X, Y).", None);
}
#[test]
fn test_parse_query_suffixed() {
quick_parser_check(".infer path(string, string). path(X, Y)?", None);
}
#[test]
fn test_parse_pragma_assert() {
quick_parser_check(r#".assert human(string)."#, None);
}
#[test]
fn test_parse_pragma_assert_named() {
quick_parser_check(r#".assert human(name: string)."#, None);
}
#[test]
fn test_parse_rule_expression_negated_term() {
quick_parser_check_with_options(
"alien(X) :- living(X), ! human(X).",
FeatureSet::default().add_support_for(&FEATURE_NEGATION),
None,
);
}
#[test]
fn test_parse_rule_with_comparison() {
quick_parser_check_with_options(
"old(X) :- human(X), X > 50.",
FeatureSet::default().add_support_for(&FEATURE_COMPARISONS),
None,
);
}
#[test]
fn test_parse_rule_with_unicode_comparison() {
quick_parser_check_with_options(
r#"old(X) :- human(X), X ≛ "$xerc.*"."#,
FeatureSet::default().add_support_for(&FEATURE_COMPARISONS),
None,
);
}
#[test]
fn test_parse_constraint_rule() {
quick_parser_check_with_options(
"⊥ :- dead(X) AND alive(X).",
FeatureSet::default().add_support_for(&FEATURE_CONSTRAINTS),
None,
);
quick_parser_check_with_options(
":- dead(X) AND alive(X).",
FeatureSet::default().add_support_for(&FEATURE_CONSTRAINTS),
None,
);
}
#[test]
fn test_parse_rule_with_disjunction() {
quick_parser_check_with_options(
"mother(X); father(X) :- parent(X).",
FeatureSet::default().add_support_for(&FEATURE_DISJUNCTION),
None,
);
quick_parser_check_with_options(
"mother(X) | father(X) :- parent(X).",
FeatureSet::default().add_support_for(&FEATURE_DISJUNCTION),
None,
);
quick_parser_check_with_options(
"mother(X) OR father(X) :- parent(X).",
FeatureSet::default().add_support_for(&FEATURE_DISJUNCTION),
None,
);
quick_parser_check_with_options(
"mother(X) ∨ father(X) :- parent(X).",
FeatureSet::default().add_support_for(&FEATURE_DISJUNCTION),
None,
);
}
#[test]
#[should_panic]
fn test_fail_disabled_negated_term() {
quick_parser_check("alien(X) :- ! human(X).", None);
}
#[test]
#[should_panic]
fn test_fail_not_well_formed_1() {
quick_parser_check("mortal(X, Y) :- human(X).", None);
}
#[test]
#[should_panic]
fn test_fail_not_well_formed_2() {
quick_parser_check_with_options(
"alien(X) :- ! human(X).",
FeatureSet::default().add_support_for(&FEATURE_NEGATION),
None,
);
}
#[cfg(test_old)]
mod tests {
use super::*;
use crate::parse::parse_str;
#[test]
fn test_well_formed() {
let program = parse_str(r#"reachable(n1,n3) :- link(n1,n2), reachable(n2,n3)."#);
assert!(program.is_ok());
let well_formed = WellFormedValidator::default().validate(&program.unwrap().into_parsed());
assert!(well_formed.is_ok())
}
#[test]
fn test_not_well_formed() {
let program = parse_str(r#"reachable(n1,n3) :- link(n1,n2), reachable(n1,n2)."#);
assert!(program.is_ok());
let well_formed = WellFormedValidator::default().validate(&program.unwrap().into_parsed());
assert_eq!(
well_formed.err().unwrap().to_string(),
String::from("Atom 'reachable', [line 1, column 1]: the variables 'n3' in the head do not appear in any positive form in the body.")
);
}
#[test]
#[ignore]
fn test_well_formed_negative() {
let program = parse_str(r#"moreThanOneHop(n1,n2) :‐ reachable(n1,n2), !link(n1,n2)."#);
assert!(program.is_ok());
let well_formed = WellFormedValidator::default().validate(&program.unwrap().into_parsed());
assert!(well_formed.is_ok())
}
#[test]
#[ignore]
fn test_not_well_formed_negative() {
let program = parse_str(r#"moreThanOneHop(n1,n2) :‐ !link(n1,n2)."#);
assert!(program.is_ok());
let well_formed = WellFormedValidator::default().validate(&program.unwrap().into_parsed());
assert!(well_formed.is_ok())
}
}