use neorusticus::{PrologEngine, quick_query};
#[test]
fn test_basic_facts_and_queries() {
let mut engine = PrologEngine::new();
engine.parse_and_add("parent(tom, bob).").unwrap();
engine.parse_and_add("parent(bob, ann).").unwrap();
engine.parse_and_add("parent(ann, sue).").unwrap();
let solutions = engine.parse_query("parent(tom, X)?").unwrap();
assert_eq!(solutions.len(), 1);
let solutions = engine.parse_query("parent(X, ann)?").unwrap();
assert_eq!(solutions.len(), 1);
let solutions = engine.parse_query("parent(sue, X)?").unwrap();
assert_eq!(solutions.len(), 0);
}
#[test]
fn test_rules_and_recursion() {
let mut engine = PrologEngine::new();
engine.parse_and_add("parent(alice, bob).").unwrap();
engine.parse_and_add("parent(bob, charlie).").unwrap();
engine.parse_and_add("parent(charlie, diana).").unwrap();
engine.parse_and_add("ancestor(X, Y) :- parent(X, Y).").unwrap();
engine.parse_and_add("ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).").unwrap();
let solutions = engine.parse_query("ancestor(alice, bob)?").unwrap();
assert_eq!(solutions.len(), 1);
let solutions = engine.parse_query("ancestor(alice, diana)?").unwrap();
assert_eq!(solutions.len(), 1);
let solutions = engine.parse_query("ancestor(alice, X)?").unwrap();
assert_eq!(solutions.len(), 3); }
#[test]
fn test_arithmetic_operations() {
let mut engine = PrologEngine::new();
let solutions = engine.parse_query("X is 2 + 3 * 4?").unwrap();
assert_eq!(solutions.len(), 1);
let solutions = engine.parse_query("5 > 3?").unwrap();
assert_eq!(solutions.len(), 1);
let solutions = engine.parse_query("3 > 5?").unwrap();
assert_eq!(solutions.len(), 0);
let solutions = engine.parse_query("6 =:= 2 * 3?").unwrap();
assert_eq!(solutions.len(), 1);
}
#[test]
fn test_list_operations() {
let mut engine = PrologEngine::new();
let solutions = engine.parse_query("append([1, 2], [3, 4], X)?").unwrap();
assert_eq!(solutions.len(), 1);
let solutions = engine.parse_query("member(2, [1, 2, 3])?").unwrap();
assert_eq!(solutions.len(), 1);
let solutions = engine.parse_query("member(4, [1, 2, 3])?").unwrap();
assert_eq!(solutions.len(), 0);
let solutions = engine.parse_query("length([a, b, c], X)?").unwrap();
assert_eq!(solutions.len(), 1);
}
#[test]
fn test_cut_operation() {
let mut engine = PrologEngine::new();
engine.parse_and_add("max(X, Y, X) :- X >= Y, !.").unwrap();
engine.parse_and_add("max(X, Y, Y).").unwrap();
let solutions = engine.parse_query("max(5, 3, Z)?").unwrap();
assert_eq!(solutions.len(), 1);
let solutions = engine.parse_query("max(2, 7, Z)?").unwrap();
assert_eq!(solutions.len(), 1); }
#[test]
fn test_error_handling() {
let mut engine = PrologEngine::new();
assert!(engine.parse_and_add("invalid syntax").is_err());
assert!(engine.parse_and_add("foo(bar").is_err());
assert!(engine.parse_query("X is 5 // 0?").is_err()); assert!(engine.parse_query("X is Y + 1?").is_err()); }
#[test]
fn test_quick_query_convenience_function() {
let clauses = &[
"likes(mary, food).",
"likes(mary, wine).",
"likes(john, wine).",
"likes(john, mary).",
];
let solutions = quick_query(clauses, "likes(mary, X)?").unwrap();
assert_eq!(solutions.len(), 2);
let solutions = quick_query(clauses, "likes(X, wine)?").unwrap();
assert_eq!(solutions.len(), 2);
let solutions = quick_query(clauses, "likes(bob, X)?").unwrap();
assert_eq!(solutions.len(), 0);
}
#[test]
fn test_variable_scoping() {
let mut engine = PrologEngine::new();
engine.parse_and_add("test(X, Y) :- X = 1, Y = 2.").unwrap();
engine.parse_and_add("test(A, B) :- A = 3, B = 4.").unwrap();
let solutions = engine.parse_query("test(P, Q)?").unwrap();
assert_eq!(solutions.len(), 2);
}
#[test]
fn test_complex_unification() {
let mut engine = PrologEngine::new();
engine.parse_and_add("complex(f(X, Y), f(a, b)) :- X = a, Y = b.").unwrap();
let solutions = engine.parse_query("complex(f(a, b), Z)?").unwrap();
assert_eq!(solutions.len(), 1);
let solutions = engine.parse_query("complex(f(c, d), f(a, b))?").unwrap();
assert_eq!(solutions.len(), 0);
}