use tensorlogic_adapters::*;
#[test]
fn test_academic_schema() {
let mut table = SymbolTable::new();
table
.add_domain(DomainInfo::new("Student", 1000))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Professor", 100))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Course", 500))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Department", 20))
.expect("unwrap");
let mut hierarchy = DomainHierarchy::new();
hierarchy.add_subtype("Student", "Person");
hierarchy.add_subtype("Professor", "Person");
table
.add_predicate(PredicateInfo::new(
"enrolled",
vec!["Student".to_string(), "Course".to_string()],
))
.expect("unwrap");
table
.add_predicate(PredicateInfo::new(
"teaches",
vec!["Professor".to_string(), "Course".to_string()],
))
.expect("unwrap");
table
.add_predicate(PredicateInfo::new(
"belongs_to",
vec!["Course".to_string(), "Department".to_string()],
))
.expect("unwrap");
table
.add_predicate(PredicateInfo::new(
"advises",
vec!["Professor".to_string(), "Student".to_string()],
))
.expect("unwrap");
let validator = SchemaValidator::new(&table);
let report = validator.validate().expect("unwrap");
assert!(report.errors.is_empty(), "Schema should be valid");
let json = table.to_json().expect("unwrap");
let restored = SymbolTable::from_json(&json).expect("unwrap");
assert_eq!(table.domains.len(), restored.domains.len());
assert_eq!(table.predicates.len(), restored.predicates.len());
let compact = CompactSchema::from_symbol_table(&table);
let stats = compact.compression_stats();
assert!(
stats.compression_ratio() > 0.0,
"Compression ratio should be positive"
);
println!(
"Academic schema - Compression ratio: {:.2}%",
stats.compression_ratio() * 100.0
);
println!(
"Academic schema - Space savings: {:.2}%",
stats.space_savings()
);
}
#[test]
fn test_social_network_versioning() {
let mut v1 = SymbolTable::new();
v1.add_domain(DomainInfo::new("User", 10000))
.expect("unwrap");
v1.add_domain(DomainInfo::new("Post", 50000))
.expect("unwrap");
v1.add_predicate(PredicateInfo::new(
"follows",
vec!["User".to_string(), "User".to_string()],
))
.expect("unwrap");
v1.add_predicate(PredicateInfo::new(
"created",
vec!["User".to_string(), "Post".to_string()],
))
.expect("unwrap");
let mut v2 = v1.clone();
v2.add_domain(DomainInfo::new("Group", 1000))
.expect("unwrap");
v2.add_domain(DomainInfo::new("Reaction", 5))
.expect("unwrap");
v2.add_predicate(PredicateInfo::new(
"member_of",
vec!["User".to_string(), "Group".to_string()],
))
.expect("unwrap");
v2.add_predicate(PredicateInfo::new(
"reacted_with",
vec![
"User".to_string(),
"Post".to_string(),
"Reaction".to_string(),
],
))
.expect("unwrap");
let diff = compute_diff(&v1, &v2);
assert_eq!(diff.domains_added.len(), 2);
assert_eq!(diff.predicates_added.len(), 2);
assert!(diff.is_backward_compatible());
let compat = check_compatibility(&v1, &v2);
assert_eq!(compat, CompatibilityLevel::BackwardCompatible);
let report = diff.report();
assert!(report.contains("Domains Added"));
assert!(report.contains("Group"));
assert!(report.contains("Reaction"));
println!("Social network diff report:\n{}", report);
}
#[test]
fn test_ecommerce_schema() {
let mut table = SymbolTable::new();
table
.add_domain(DomainInfo::new("Customer", 100000))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Product", 10000))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Order", 500000))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Category", 100))
.expect("unwrap");
let mut purchases = PredicateInfo::new(
"purchases",
vec!["Customer".to_string(), "Product".to_string()],
);
purchases.constraints = Some(
PredicateConstraints::new().with_property(PredicateProperty::Functional), );
table.add_predicate(purchases).expect("unwrap");
let mut contains =
PredicateInfo::new("contains", vec!["Order".to_string(), "Product".to_string()]);
contains.description = Some("Products contained in an order".to_string());
table.add_predicate(contains).expect("unwrap");
let mut in_category = PredicateInfo::new(
"in_category",
vec!["Product".to_string(), "Category".to_string()],
);
in_category.constraints = Some(
PredicateConstraints::new().with_property(PredicateProperty::Functional), );
table.add_predicate(in_category).expect("unwrap");
let validator = SchemaValidator::new(&table);
let report = validator.validate().expect("unwrap");
assert!(report.errors.is_empty());
let export = CompilerExport::export_all(&table);
assert_eq!(export.domains.len(), 4);
assert_eq!(export.predicate_signatures.len(), 3);
}
#[test]
fn test_schema_merge() {
let mut base = SymbolTable::new();
base.add_domain(DomainInfo::new("Entity", 1000))
.expect("unwrap");
base.add_predicate(PredicateInfo::new("related", vec!["Entity".to_string()]))
.expect("unwrap");
let mut update1 = SymbolTable::new();
update1
.add_domain(DomainInfo::new("Entity", 1000))
.expect("unwrap"); update1
.add_domain(DomainInfo::new("Attribute", 100))
.expect("unwrap");
update1
.add_predicate(PredicateInfo::new(
"has_attr",
vec!["Entity".to_string(), "Attribute".to_string()],
))
.expect("unwrap");
let mut update2 = SymbolTable::new();
update2
.add_domain(DomainInfo::new("Entity", 2000))
.expect("unwrap");
let merged1 = merge_tables(&base, &update1);
assert_eq!(merged1.domains.len(), 2);
assert_eq!(merged1.predicates.len(), 2);
let final_merged = merge_tables(&merged1, &update2);
assert_eq!(
final_merged
.get_domain("Entity")
.expect("unwrap")
.cardinality,
2000
);
}
#[test]
fn test_collection_schema() {
let mut table = SymbolTable::new();
table
.add_domain(DomainInfo::new("User", 1000))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Item", 5000))
.expect("unwrap");
let user_list = ParametricType::list(TypeParameter::concrete("User"));
let item_set = ParametricType::map(
TypeParameter::concrete("User"),
TypeParameter::concrete("Item"),
);
let mut shopping_cart = DomainInfo::new("ShoppingCart", 1000);
shopping_cart.parametric_type = Some(item_set);
table.add_domain(shopping_cart).expect("unwrap");
let mut friends_list = DomainInfo::new("FriendsList", 1000);
friends_list.parametric_type = Some(user_list);
table.add_domain(friends_list).expect("unwrap");
let validator = SchemaValidator::new(&table);
let report = validator.validate().expect("unwrap");
assert!(report.errors.is_empty());
}
#[test]
fn test_organizational_hierarchy() {
let mut table = SymbolTable::new();
let mut hierarchy = DomainHierarchy::new();
table
.add_domain(DomainInfo::new("Employee", 1000))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Manager", 100))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Director", 20))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Executive", 5))
.expect("unwrap");
hierarchy.add_subtype("Manager", "Employee");
hierarchy.add_subtype("Director", "Manager");
hierarchy.add_subtype("Executive", "Director");
assert!(hierarchy.is_subtype("Executive", "Employee"));
assert!(hierarchy.is_subtype("Director", "Employee"));
assert!(!hierarchy.is_subtype("Employee", "Executive"));
table
.add_predicate(PredicateInfo::new(
"reports_to",
vec!["Employee".to_string(), "Manager".to_string()],
))
.expect("unwrap");
assert!(hierarchy.validate_acyclic().is_ok());
}
#[test]
fn test_metadata_tracking() {
let mut table = SymbolTable::new();
let mut person = DomainInfo::new("Person", 1000);
let provenance = Provenance::new("admin", "2025-11-06T00:00:00Z")
.with_source("schema_v1.yaml", Some(1))
.with_notes("Initial schema setup");
let mut documentation = Documentation::new("Represents individuals in the system")
.with_description("Person domain for storing individual entity data");
documentation.add_example(Example::new(
"John Doe",
"Person { id: 1, name: 'John Doe' }",
));
let mut metadata = Metadata::new();
metadata.provenance = Some(provenance);
metadata.documentation = Some(documentation);
person.metadata = Some(metadata);
table.add_domain(person).expect("unwrap");
let retrieved = table.get_domain("Person").expect("unwrap");
assert!(retrieved.metadata.is_some());
let metadata = retrieved.metadata.as_ref().expect("unwrap");
assert!(metadata.provenance.is_some());
assert!(metadata.documentation.is_some());
}
#[test]
fn test_large_schema() {
let mut table = SymbolTable::new();
for i in 0..100 {
table
.add_domain(DomainInfo::new(format!("Domain{}", i), 1000))
.expect("unwrap");
}
for i in 0..200 {
let domain_idx = i % 100;
table
.add_predicate(PredicateInfo::new(
format!("pred{}", i),
vec![format!("Domain{}", domain_idx)],
))
.expect("unwrap");
}
assert_eq!(table.domains.len(), 100);
assert_eq!(table.predicates.len(), 200);
let compact = CompactSchema::from_symbol_table(&table);
let stats = compact.compression_stats();
println!("Large schema - Unique strings: {}", stats.unique_strings);
println!(
"Large schema - Compression ratio: {:.2}",
stats.compression_ratio()
);
println!(
"Large schema - Space savings: {:.2}%",
stats.space_savings()
);
let restored = compact.to_symbol_table().expect("unwrap");
assert_eq!(table.domains.len(), restored.domains.len());
assert_eq!(table.predicates.len(), restored.predicates.len());
}
#[test]
fn test_binary_storage() {
let mut table = SymbolTable::new();
table
.add_domain(DomainInfo::new("Person", 100))
.expect("unwrap");
table
.add_domain(DomainInfo::new("Location", 50))
.expect("unwrap");
table
.add_predicate(PredicateInfo::new(
"at",
vec!["Person".to_string(), "Location".to_string()],
))
.expect("unwrap");
let compact = CompactSchema::from_symbol_table(&table);
let binary = compact.to_binary().expect("unwrap");
assert!(!binary.is_empty());
println!("Binary size: {} bytes", binary.len());
let restored_compact = CompactSchema::from_binary(&binary).expect("unwrap");
let restored_table = restored_compact.to_symbol_table().expect("unwrap");
assert_eq!(table.domains.len(), restored_table.domains.len());
assert_eq!(table.predicates.len(), restored_table.predicates.len());
}
#[test]
fn test_compiler_bundle_validation() {
let mut table = SymbolTable::new();
table
.add_domain(DomainInfo::new("Person", 100))
.expect("unwrap");
table
.add_predicate(PredicateInfo::new("knows", vec!["Person".to_string()]))
.expect("unwrap");
let bundle = CompilerExport::export_all(&table);
let mut other_table = SymbolTable::new();
other_table
.add_domain(DomainInfo::new("Person", 100))
.expect("unwrap");
let result = SymbolTableSync::validate_bundle(&other_table, &bundle).expect("unwrap");
assert!(result.is_valid());
let mut invalid_bundle = CompilerExportBundle::new();
invalid_bundle.predicate_signatures.insert(
"unknown_pred".to_string(),
vec!["UnknownDomain".to_string()],
);
let result = SymbolTableSync::validate_bundle(&table, &invalid_bundle).expect("unwrap");
assert!(!result.is_valid());
assert!(!result.errors.is_empty());
}
#[test]
fn test_cli_validate_valid_schema() {
use std::fs;
use std::process::Command;
let temp_dir = std::env::temp_dir();
let schema_path = temp_dir.join("test_schema_valid.yaml");
let mut table = SymbolTable::new();
table
.add_domain(DomainInfo::new("Person", 100))
.expect("unwrap");
table
.add_predicate(PredicateInfo::new(
"knows",
vec!["Person".to_string(), "Person".to_string()],
))
.expect("unwrap");
let yaml = table.to_yaml().expect("unwrap");
fs::write(&schema_path, yaml).expect("unwrap");
let output = Command::new("cargo")
.args([
"run",
"--bin",
"schema_validate",
"--",
schema_path.to_str().expect("unwrap"),
])
.output();
let _ = fs::remove_file(&schema_path);
if let Ok(output) = output {
assert!(output.status.success(), "Validation should succeed");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("Schema validation passed"));
}
}
#[test]
fn test_cli_migrate_convert() {
use std::fs;
use std::process::Command;
let temp_dir = std::env::temp_dir();
let json_path = temp_dir.join("test_schema.json");
let yaml_path = temp_dir.join("test_schema_converted.yaml");
let mut table = SymbolTable::new();
table
.add_domain(DomainInfo::new("Person", 100))
.expect("unwrap");
table
.add_predicate(PredicateInfo::new(
"knows",
vec!["Person".to_string(), "Person".to_string()],
))
.expect("unwrap");
let json = table.to_json().expect("unwrap");
fs::write(&json_path, json).expect("unwrap");
let output = Command::new("cargo")
.args([
"run",
"--bin",
"schema_migrate",
"--",
"convert",
json_path.to_str().expect("unwrap"),
yaml_path.to_str().expect("unwrap"),
])
.output();
if let Ok(output) = output {
if output.status.success() {
assert!(yaml_path.exists(), "YAML file should be created");
let yaml_content = fs::read_to_string(&yaml_path).expect("unwrap");
let restored = SymbolTable::from_yaml(&yaml_content).expect("unwrap");
assert_eq!(table.domains.len(), restored.domains.len());
assert_eq!(table.predicates.len(), restored.predicates.len());
}
}
let _ = fs::remove_file(&json_path);
let _ = fs::remove_file(&yaml_path);
}
#[test]
fn test_cli_migrate_diff() {
use std::fs;
use std::process::Command;
let temp_dir = std::env::temp_dir();
let old_path = temp_dir.join("test_schema_old.yaml");
let new_path = temp_dir.join("test_schema_new.yaml");
let mut old_table = SymbolTable::new();
old_table
.add_domain(DomainInfo::new("Person", 100))
.expect("unwrap");
old_table
.add_predicate(PredicateInfo::new(
"knows",
vec!["Person".to_string(), "Person".to_string()],
))
.expect("unwrap");
fs::write(&old_path, old_table.to_yaml().expect("unwrap")).expect("unwrap");
let mut new_table = old_table.clone();
new_table
.add_domain(DomainInfo::new("Location", 50))
.expect("unwrap");
new_table
.add_predicate(PredicateInfo::new(
"at",
vec!["Person".to_string(), "Location".to_string()],
))
.expect("unwrap");
fs::write(&new_path, new_table.to_yaml().expect("unwrap")).expect("unwrap");
let output = Command::new("cargo")
.args([
"run",
"--bin",
"schema_migrate",
"--",
"diff",
old_path.to_str().expect("unwrap"),
new_path.to_str().expect("unwrap"),
])
.output();
if let Ok(output) = output {
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("Added domains") || stdout.contains("Added predicates"));
}
}
let _ = fs::remove_file(&old_path);
let _ = fs::remove_file(&new_path);
}
#[test]
fn test_cli_migrate_merge() {
use std::fs;
use std::process::Command;
let temp_dir = std::env::temp_dir();
let schema1_path = temp_dir.join("test_schema1.yaml");
let schema2_path = temp_dir.join("test_schema2.yaml");
let merged_path = temp_dir.join("test_schema_merged.yaml");
let mut table1 = SymbolTable::new();
table1
.add_domain(DomainInfo::new("Person", 100))
.expect("unwrap");
table1
.add_predicate(PredicateInfo::new(
"knows",
vec!["Person".to_string(), "Person".to_string()],
))
.expect("unwrap");
fs::write(&schema1_path, table1.to_yaml().expect("unwrap")).expect("unwrap");
let mut table2 = SymbolTable::new();
table2
.add_domain(DomainInfo::new("Person", 100))
.expect("unwrap"); table2
.add_domain(DomainInfo::new("Location", 50))
.expect("unwrap");
table2
.add_predicate(PredicateInfo::new(
"at",
vec!["Person".to_string(), "Location".to_string()],
))
.expect("unwrap");
fs::write(&schema2_path, table2.to_yaml().expect("unwrap")).expect("unwrap");
let output = Command::new("cargo")
.args([
"run",
"--bin",
"schema_migrate",
"--",
"merge",
schema1_path.to_str().expect("unwrap"),
schema2_path.to_str().expect("unwrap"),
merged_path.to_str().expect("unwrap"),
])
.output();
if let Ok(output) = output {
if output.status.success() && merged_path.exists() {
let merged_content = fs::read_to_string(&merged_path).expect("unwrap");
let merged_table = SymbolTable::from_yaml(&merged_content).expect("unwrap");
assert!(merged_table.get_domain("Person").is_some());
assert!(merged_table.get_domain("Location").is_some());
}
}
let _ = fs::remove_file(&schema1_path);
let _ = fs::remove_file(&schema2_path);
let _ = fs::remove_file(&merged_path);
}