kotoba_graph/
lib.rs

1//! `kotoba-graph`
2//!
3//! This crate provides the core graph data structures for Kotoba, including
4//! vertices, edges, and the graph itself, along with graph algorithms.
5
6pub mod graph;
7
8pub mod prelude {
9    pub use crate::graph::*;
10}
11
12#[cfg(test)]
13mod tests {
14    use super::*;
15    use crate::graph::*;
16    use kotoba_core::types::*;
17    use std::collections::HashMap;
18
19    #[test]
20    fn test_graph_creation() {
21        // Test empty graph creation
22        let graph = Graph::empty();
23        assert_eq!(graph.vertices.len(), 0);
24        assert_eq!(graph.edges.len(), 0);
25        assert_eq!(graph.adj_out.len(), 0);
26        assert_eq!(graph.adj_in.len(), 0);
27    }
28
29    #[test]
30    fn test_vertex_operations() {
31        let mut graph = Graph::empty();
32
33        // Create vertex data
34        let vertex_id = VertexId::new_v4();
35        let mut props = HashMap::new();
36        props.insert("name".to_string(), Value::String("Test Vertex".to_string()));
37
38        let vertex_data = VertexData {
39            id: vertex_id,
40            labels: vec!["Test".to_string()],
41            props,
42        };
43
44        // Add vertex
45        graph.add_vertex(vertex_data.clone());
46
47        // Verify vertex was added
48        assert_eq!(graph.vertices.len(), 1);
49        assert!(graph.vertices.contains_key(&vertex_id));
50
51        // Verify vertex data
52        let retrieved = graph.vertices.get(&vertex_id).unwrap();
53        assert_eq!(retrieved.id, vertex_id);
54        assert_eq!(retrieved.labels, vec!["Test".to_string()]);
55        assert_eq!(retrieved.props.get("name").unwrap(), &Value::String("Test Vertex".to_string()));
56
57        // Test vertex existence
58        assert!(graph.get_vertex(&vertex_id).is_some());
59        assert!(graph.get_vertex(&VertexId::new_v4()).is_none());
60    }
61
62    #[test]
63    fn test_edge_operations() {
64        let mut graph = Graph::empty();
65
66        // Create vertices first
67        let src_id = VertexId::new_v4();
68        let dst_id = VertexId::new_v4();
69
70        let src_vertex = VertexData {
71            id: src_id,
72            labels: vec!["Source".to_string()],
73            props: HashMap::new(),
74        };
75
76        let dst_vertex = VertexData {
77            id: dst_id,
78            labels: vec!["Destination".to_string()],
79            props: HashMap::new(),
80        };
81
82        graph.add_vertex(src_vertex);
83        graph.add_vertex(dst_vertex);
84
85        // Create edge
86        let edge_id = EdgeId::new_v4();
87        let mut edge_props = HashMap::new();
88        edge_props.insert("weight".to_string(), Value::Int(10));
89
90        let edge_data = EdgeData {
91            id: edge_id,
92            src: src_id,
93            dst: dst_id,
94            label: "CONNECTS".to_string(),
95            props: edge_props,
96        };
97
98        // Add edge
99        graph.add_edge(edge_data.clone());
100
101        // Verify edge was added
102        assert_eq!(graph.edges.len(), 1);
103        assert!(graph.edges.contains_key(&edge_id));
104
105        // Verify adjacency lists
106        assert!(graph.adj_out.get(&src_id).unwrap().contains(&dst_id));
107        assert!(graph.adj_in.get(&dst_id).unwrap().contains(&src_id));
108
109        // Verify edge data
110        let retrieved = graph.edges.get(&edge_id).unwrap();
111        assert_eq!(retrieved.src, src_id);
112        assert_eq!(retrieved.dst, dst_id);
113        assert_eq!(retrieved.label, "CONNECTS");
114        assert_eq!(retrieved.props.get("weight").unwrap(), &Value::Int(10));
115    }
116
117    #[test]
118    fn test_graph_statistics() {
119        let mut graph = Graph::empty();
120
121        // Add some vertices and edges
122        for i in 0..5 {
123            let vertex_id = VertexId::new_v4();
124            let vertex_data = VertexData {
125                id: vertex_id,
126                labels: vec![format!("Label{}", i)],
127                props: HashMap::new(),
128            };
129            graph.add_vertex(vertex_data);
130        }
131
132        // Add some edges
133        let vertices: Vec<VertexId> = graph.vertices.keys().cloned().collect();
134        for i in 0..3 {
135            let edge_id = EdgeId::new_v4();
136            let edge_data = EdgeData {
137                id: edge_id,
138                src: vertices[i],
139                dst: vertices[i + 1],
140                label: "LINK".to_string(),
141                props: HashMap::new(),
142            };
143            graph.add_edge(edge_data);
144        }
145
146        // Test basic statistics
147        assert_eq!(graph.vertex_count(), 5);
148        assert_eq!(graph.edge_count(), 3);
149    }
150
151    #[test]
152    fn test_vertex_edge_data() {
153        let mut graph = Graph::empty();
154
155        // Create test data
156        let vertex_id = VertexId::new_v4();
157        let edge_id = EdgeId::new_v4();
158
159        let mut vertex_props = HashMap::new();
160        vertex_props.insert("name".to_string(), Value::String("Test".to_string()));
161        vertex_props.insert("age".to_string(), Value::Int(25));
162
163        let vertex_data = VertexData {
164            id: vertex_id,
165            labels: vec!["Person".to_string()],
166            props: vertex_props,
167        };
168
169        let mut edge_props = HashMap::new();
170        edge_props.insert("weight".to_string(), Value::Int(5));
171        edge_props.insert("directed".to_string(), Value::Bool(true));
172
173        let edge_data = EdgeData {
174            id: edge_id,
175            src: vertex_id,
176            dst: VertexId::new_v4(), // Dummy destination
177            label: "SELF".to_string(),
178            props: edge_props,
179        };
180
181        // Test serialization/deserialization
182        let vertex_json = serde_json::to_string(&vertex_data).unwrap();
183        let vertex_deserialized: VertexData = serde_json::from_str(&vertex_json).unwrap();
184        assert_eq!(vertex_data, vertex_deserialized);
185
186        let edge_json = serde_json::to_string(&edge_data).unwrap();
187        let edge_deserialized: EdgeData = serde_json::from_str(&edge_json).unwrap();
188        assert_eq!(edge_data, edge_deserialized);
189    }
190}