pub mod core; pub mod storage; pub mod persistence; pub mod cypher; pub mod algorithms; pub mod index; pub mod transaction; pub mod distributed; pub mod error; pub mod server; pub mod observability; pub mod cli; pub mod visualization; pub use core::{Graph, PersistentGraph, Node, Relationship, Property}; pub use error::{GigabrainError, Result}; pub use observability::{ObservabilitySystem, HealthLevel, HealthStatus}; pub use persistence::{PersistentStorage, StorageBackend}; pub use index::{IndexManager, IndexType, IndexQuery, IndexConfig}; use serde::{Serialize, Deserialize}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)] pub struct NodeId(pub u64); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct RelationshipId(pub u64); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct LabelId(pub u32); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct PropertyKeyId(pub u32); #[cfg(test)] mod tests { use super::*; use crate::core::Graph; use crate::cypher::{parse_cypher, QueryExecutor}; use crate::storage::MemoryStore; use std::sync::Arc; #[tokio::test] async fn test_graph_creation() { let graph = Graph::new(); // Create nodes let alice = graph.create_node(); let bob = graph.create_node(); // Get schema let mut schema = graph.schema().write(); let knows_rel = schema.get_or_create_relationship_type("KNOWS"); drop(schema); // Create relationship let rel = graph.create_relationship(alice, bob, knows_rel).unwrap(); // Verify assert!(graph.get_node(alice).is_some()); assert!(graph.get_node(bob).is_some()); assert!(graph.get_relationship(rel).is_some()); } #[tokio::test] async fn test_cypher_parsing() { let queries = vec![ "MATCH (n) RETURN n", "CREATE (n:Person {name: 'Alice'})", "MATCH (n:Person)-[:KNOWS]->(m) RETURN n, m", // TODO: Add WHERE clause support // "MATCH (n) WHERE n.age > 18 RETURN n", ]; for query in queries { let result = parse_cypher(query); assert!(result.is_ok(), "Failed to parse: {}", query); } } #[tokio::test] async fn test_query_execution() { let graph = Arc::new(Graph::new()); let executor = QueryExecutor::new(graph.clone()); // Test simple MATCH query let query = parse_cypher("MATCH (n) RETURN n").unwrap(); let result = executor.execute_query(&query).await; assert!(result.is_ok()); } #[test] fn test_memory_store() { let store = MemoryStore::new(); // Basic storage operations would be tested here // This is a placeholder for more comprehensive storage tests } #[tokio::test] async fn test_node_relationships() { let graph = Graph::new(); let node1 = graph.create_node(); let node2 = graph.create_node(); let node3 = graph.create_node(); let mut schema = graph.schema().write(); let knows = schema.get_or_create_relationship_type("KNOWS"); let follows = schema.get_or_create_relationship_type("FOLLOWS"); drop(schema); let rel1 = graph.create_relationship(node1, node2, knows).unwrap(); let rel2 = graph.create_relationship(node1, node3, follows).unwrap(); let relationships = graph.get_node_relationships( node1, crate::core::relationship::Direction::Outgoing, None ); assert_eq!(relationships.len(), 2); assert!(relationships.iter().any(|r| r.id == rel1)); assert!(relationships.iter().any(|r| r.id == rel2)); } #[test] fn test_property_value_hash() { use crate::core::PropertyValue; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; let val1 = PropertyValue::String("test".to_string()); let val2 = PropertyValue::String("test".to_string()); let val3 = PropertyValue::Integer(42); let mut hasher1 = DefaultHasher::new(); val1.hash(&mut hasher1); let hash1 = hasher1.finish(); let mut hasher2 = DefaultHasher::new(); val2.hash(&mut hasher2); let hash2 = hasher2.finish(); let mut hasher3 = DefaultHasher::new(); val3.hash(&mut hasher3); let hash3 = hasher3.finish(); assert_eq!(hash1, hash2); // Same values should hash the same assert_ne!(hash1, hash3); // Different values should hash differently } #[tokio::test] async fn test_transaction_manager() { use crate::transaction::{TransactionManager, IsolationLevel}; let tx_manager = TransactionManager::new(); let tx_id = tx_manager.begin(IsolationLevel::ReadCommitted).unwrap(); assert!(tx_manager.commit(tx_id).is_ok()); let tx_id2 = tx_manager.begin(IsolationLevel::Serializable).unwrap(); assert!(tx_manager.rollback(tx_id2).is_ok()); } #[test] fn test_distributed_sharding() { use crate::distributed::ShardManager; let shard_manager = ShardManager::new(4); let node1 = NodeId(1); let node2 = NodeId(2); let node3 = NodeId(5); // Should hash to same shard as node1 let shard1 = shard_manager.get_shard_for_node(node1); let shard2 = shard_manager.get_shard_for_node(node2); let shard3 = shard_manager.get_shard_for_node(node3); // Verify deterministic sharding assert_eq!(shard1, shard_manager.get_shard_for_node(node1)); assert_eq!(shard3, shard_manager.get_shard_for_node(node3)); // Different nodes may or may not be on different shards // depending on the hash function, but the behavior should be consistent } }