184 lines
5.2 KiB
Rust
184 lines
5.2 KiB
Rust
|
|
//! Unit tests for relation storage
|
||
|
|
|
||
|
|
use geolog::core::{RelationStorage, Structure, VecRelation};
|
||
|
|
use geolog::id::{NumericId, Slid};
|
||
|
|
use geolog::universe::Universe;
|
||
|
|
use geolog::serialize::{load_structure, save_structure};
|
||
|
|
use tempfile::tempdir;
|
||
|
|
|
||
|
|
/// Helper to create Slid from integer
|
||
|
|
fn slid(n: usize) -> Slid {
|
||
|
|
Slid::from_usize(n)
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_vec_relation_basic() {
|
||
|
|
let mut rel = VecRelation::new(2);
|
||
|
|
|
||
|
|
// Insert a tuple
|
||
|
|
assert!(rel.insert(vec![slid(0), slid(1)]));
|
||
|
|
assert_eq!(rel.len(), 1);
|
||
|
|
|
||
|
|
// Check containment
|
||
|
|
assert!(rel.contains(&[slid(0), slid(1)]));
|
||
|
|
assert!(!rel.contains(&[slid(1), slid(0)]));
|
||
|
|
assert!(!rel.contains(&[slid(0), slid(0)]));
|
||
|
|
|
||
|
|
// Insert another tuple
|
||
|
|
assert!(rel.insert(vec![slid(1), slid(0)]));
|
||
|
|
assert_eq!(rel.len(), 2);
|
||
|
|
|
||
|
|
// Duplicate insert returns false
|
||
|
|
assert!(!rel.insert(vec![slid(0), slid(1)]));
|
||
|
|
assert_eq!(rel.len(), 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_vec_relation_remove() {
|
||
|
|
let mut rel = VecRelation::new(2);
|
||
|
|
|
||
|
|
rel.insert(vec![slid(0), slid(1)]);
|
||
|
|
rel.insert(vec![slid(1), slid(2)]);
|
||
|
|
assert_eq!(rel.len(), 2);
|
||
|
|
|
||
|
|
// Remove existing tuple
|
||
|
|
assert!(rel.remove(&[slid(0), slid(1)]));
|
||
|
|
assert_eq!(rel.len(), 1);
|
||
|
|
assert!(!rel.contains(&[slid(0), slid(1)]));
|
||
|
|
assert!(rel.contains(&[slid(1), slid(2)]));
|
||
|
|
|
||
|
|
// Remove non-existent tuple
|
||
|
|
assert!(!rel.remove(&[slid(0), slid(1)]));
|
||
|
|
assert_eq!(rel.len(), 1);
|
||
|
|
|
||
|
|
// Re-insert removed tuple (should reuse tuple ID)
|
||
|
|
assert!(rel.insert(vec![slid(0), slid(1)]));
|
||
|
|
assert_eq!(rel.len(), 2);
|
||
|
|
assert!(rel.contains(&[slid(0), slid(1)]));
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_vec_relation_iter() {
|
||
|
|
let mut rel = VecRelation::new(2);
|
||
|
|
|
||
|
|
rel.insert(vec![slid(0), slid(1)]);
|
||
|
|
rel.insert(vec![slid(1), slid(2)]);
|
||
|
|
rel.insert(vec![slid(2), slid(3)]);
|
||
|
|
|
||
|
|
let tuples: Vec<_> = rel.iter().collect();
|
||
|
|
assert_eq!(tuples.len(), 3);
|
||
|
|
|
||
|
|
// Remove middle tuple
|
||
|
|
rel.remove(&[slid(1), slid(2)]);
|
||
|
|
|
||
|
|
let tuples: Vec<_> = rel.iter().collect();
|
||
|
|
assert_eq!(tuples.len(), 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_structure_relations() {
|
||
|
|
let mut universe = Universe::new();
|
||
|
|
let mut structure = Structure::new(2);
|
||
|
|
|
||
|
|
// Add elements to two sorts
|
||
|
|
let (a, _) = structure.add_element(&mut universe, 0);
|
||
|
|
let (b, _) = structure.add_element(&mut universe, 0);
|
||
|
|
let (x, _) = structure.add_element(&mut universe, 1);
|
||
|
|
let (y, _) = structure.add_element(&mut universe, 1);
|
||
|
|
|
||
|
|
// Initialize a binary relation (arity 2)
|
||
|
|
structure.init_relations(&[2]);
|
||
|
|
|
||
|
|
// Assert some tuples
|
||
|
|
assert!(structure.assert_relation(0, vec![a, x]));
|
||
|
|
assert!(structure.assert_relation(0, vec![b, y]));
|
||
|
|
assert_eq!(structure.get_relation(0).len(), 2);
|
||
|
|
|
||
|
|
// Query
|
||
|
|
assert!(structure.query_relation(0, &[a, x]));
|
||
|
|
assert!(!structure.query_relation(0, &[a, y]));
|
||
|
|
|
||
|
|
// Retract
|
||
|
|
assert!(structure.retract_relation(0, &[a, x]));
|
||
|
|
assert!(!structure.query_relation(0, &[a, x]));
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_relation_serialization_roundtrip() {
|
||
|
|
let mut universe = Universe::new();
|
||
|
|
let mut structure = Structure::new(2);
|
||
|
|
|
||
|
|
// Add elements
|
||
|
|
let (a, _) = structure.add_element(&mut universe, 0);
|
||
|
|
let (b, _) = structure.add_element(&mut universe, 0);
|
||
|
|
let (x, _) = structure.add_element(&mut universe, 1);
|
||
|
|
|
||
|
|
// Initialize relation and add tuples
|
||
|
|
structure.init_relations(&[2]);
|
||
|
|
structure.assert_relation(0, vec![a, x]);
|
||
|
|
structure.assert_relation(0, vec![b, x]);
|
||
|
|
|
||
|
|
// Serialize and deserialize via StructureData
|
||
|
|
let data = geolog::serialize::StructureData::from_structure(&structure);
|
||
|
|
let restored = data.to_structure();
|
||
|
|
|
||
|
|
// Check relation was preserved
|
||
|
|
assert_eq!(restored.num_relations(), 1);
|
||
|
|
assert_eq!(restored.get_relation(0).len(), 2);
|
||
|
|
assert!(restored.query_relation(0, &[a, x]));
|
||
|
|
assert!(restored.query_relation(0, &[b, x]));
|
||
|
|
assert!(!restored.query_relation(0, &[a, b]));
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_relation_file_roundtrip() {
|
||
|
|
let mut universe = Universe::new();
|
||
|
|
let mut structure = Structure::new(2);
|
||
|
|
|
||
|
|
// Add elements
|
||
|
|
let (a, _) = structure.add_element(&mut universe, 0);
|
||
|
|
let (b, _) = structure.add_element(&mut universe, 1);
|
||
|
|
|
||
|
|
// Initialize relation and add tuples
|
||
|
|
structure.init_relations(&[2]);
|
||
|
|
structure.assert_relation(0, vec![a, b]);
|
||
|
|
|
||
|
|
// Save to file
|
||
|
|
let dir = tempdir().unwrap();
|
||
|
|
let path = dir.path().join("test.structure");
|
||
|
|
save_structure(&structure, &path).expect("save should succeed");
|
||
|
|
|
||
|
|
// Load from file
|
||
|
|
let loaded = load_structure(&path).expect("load should succeed");
|
||
|
|
|
||
|
|
// Check relation was preserved
|
||
|
|
assert_eq!(loaded.num_relations(), 1);
|
||
|
|
assert!(loaded.query_relation(0, &[a, b]));
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_unary_relation() {
|
||
|
|
let mut rel = VecRelation::new(1);
|
||
|
|
|
||
|
|
rel.insert(vec![slid(42)]);
|
||
|
|
rel.insert(vec![slid(100)]);
|
||
|
|
|
||
|
|
assert!(rel.contains(&[slid(42)]));
|
||
|
|
assert!(rel.contains(&[slid(100)]));
|
||
|
|
assert!(!rel.contains(&[slid(0)]));
|
||
|
|
assert_eq!(rel.len(), 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_ternary_relation() {
|
||
|
|
let mut rel = VecRelation::new(3);
|
||
|
|
|
||
|
|
rel.insert(vec![slid(1), slid(2), slid(3)]);
|
||
|
|
rel.insert(vec![slid(4), slid(5), slid(6)]);
|
||
|
|
|
||
|
|
assert!(rel.contains(&[slid(1), slid(2), slid(3)]));
|
||
|
|
assert!(rel.contains(&[slid(4), slid(5), slid(6)]));
|
||
|
|
assert!(!rel.contains(&[slid(1), slid(2), slid(4)]));
|
||
|
|
assert_eq!(rel.len(), 2);
|
||
|
|
}
|