1use super::{CRDT, Mergeable, ReplicaId};
2use serde::{Deserialize, Serialize};
3use std::collections::{HashMap, HashSet, VecDeque};
4use std::error::Error;
5use uuid::Uuid;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct GraphError {
10 message: String,
11}
12
13impl GraphError {
14 pub fn new(message: String) -> Self {
15 Self { message }
16 }
17}
18
19impl std::fmt::Display for GraphError {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 write!(f, "GraphError: {}", self.message)
22 }
23}
24
25impl Error for GraphError {}
26
27#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
29pub struct VertexId {
30 pub id: Uuid,
32 pub replica: ReplicaId,
34}
35
36impl VertexId {
37 pub fn new(replica: ReplicaId) -> Self {
39 Self {
40 id: Uuid::new_v4(),
41 replica,
42 }
43 }
44
45 pub fn from_parts(id: Uuid, replica: ReplicaId) -> Self {
47 Self { id, replica }
48 }
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
53pub struct EdgeId {
54 pub id: Uuid,
56 pub replica: ReplicaId,
58}
59
60impl EdgeId {
61 pub fn new(replica: ReplicaId) -> Self {
63 Self {
64 id: Uuid::new_v4(),
65 replica,
66 }
67 }
68
69 pub fn from_parts(id: Uuid, replica: ReplicaId) -> Self {
71 Self { id, replica }
72 }
73}
74
75#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
77pub struct VertexMetadata {
78 pub created_at: u64,
80 pub modified_at: u64,
82 pub deleted: bool,
84 pub last_modified_by: ReplicaId,
86}
87
88impl VertexMetadata {
89 pub fn new(replica: ReplicaId, timestamp: u64) -> Self {
91 Self {
92 created_at: timestamp,
93 modified_at: timestamp,
94 deleted: false,
95 last_modified_by: replica,
96 }
97 }
98
99 pub fn mark_modified(&mut self, replica: ReplicaId, timestamp: u64) {
101 self.modified_at = timestamp;
102 self.last_modified_by = replica;
103 }
104
105 pub fn mark_deleted(&mut self, replica: ReplicaId, timestamp: u64) {
107 self.deleted = true;
108 self.mark_modified(replica, timestamp);
109 }
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
114pub struct EdgeMetadata {
115 pub created_at: u64,
117 pub modified_at: u64,
119 pub deleted: bool,
121 pub last_modified_by: ReplicaId,
123}
124
125impl EdgeMetadata {
126 pub fn new(replica: ReplicaId, timestamp: u64) -> Self {
128 Self {
129 created_at: timestamp,
130 modified_at: timestamp,
131 deleted: false,
132 last_modified_by: replica,
133 }
134 }
135
136 pub fn mark_modified(&mut self, replica: ReplicaId, timestamp: u64) {
138 self.modified_at = timestamp;
139 self.last_modified_by = replica;
140 }
141
142 pub fn mark_deleted(&mut self, replica: ReplicaId, timestamp: u64) {
144 self.deleted = true;
145 self.mark_modified(replica, timestamp);
146 }
147}
148
149#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
151pub struct Vertex<T> {
152 pub id: VertexId,
154 pub value: T,
156 pub metadata: VertexMetadata,
158}
159
160impl<T> Vertex<T> {
161 pub fn new(value: T, replica: ReplicaId, timestamp: u64) -> Self {
163 Self {
164 id: VertexId::new(replica),
165 value,
166 metadata: VertexMetadata::new(replica, timestamp),
167 }
168 }
169
170 pub fn mark_modified(&mut self, replica: ReplicaId, timestamp: u64) {
172 self.metadata.mark_modified(replica, timestamp);
173 }
174
175 pub fn mark_deleted(&mut self, replica: ReplicaId, timestamp: u64) {
177 self.metadata.mark_deleted(replica, timestamp);
178 }
179}
180
181#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
183pub struct Edge {
184 pub id: EdgeId,
186 pub source: VertexId,
188 pub target: VertexId,
190 pub weight: Option<f64>,
192 pub metadata: EdgeMetadata,
194}
195
196impl Edge {
197 pub fn new(source: VertexId, target: VertexId, replica: ReplicaId, timestamp: u64) -> Self {
199 Self {
200 id: EdgeId::new(replica),
201 source,
202 target,
203 weight: None,
204 metadata: EdgeMetadata::new(replica, timestamp),
205 }
206 }
207
208 pub fn with_weight(source: VertexId, target: VertexId, weight: f64, replica: ReplicaId, timestamp: u64) -> Self {
210 Self {
211 id: EdgeId::new(replica),
212 source,
213 target,
214 weight: Some(weight),
215 metadata: EdgeMetadata::new(replica, timestamp),
216 }
217 }
218
219 pub fn mark_modified(&mut self, replica: ReplicaId, timestamp: u64) {
221 self.metadata.mark_modified(replica, timestamp);
222 }
223
224 pub fn mark_deleted(&mut self, replica: ReplicaId, timestamp: u64) {
226 self.metadata.mark_deleted(replica, timestamp);
227 }
228}
229
230#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
232pub enum GraphStrategy {
233 AddWins,
235 RemoveWins,
237}
238
239#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
241pub struct GraphConfig {
242 pub strategy: GraphStrategy,
244 pub preserve_deleted: bool,
246 pub max_vertices: Option<usize>,
248 pub max_edges: Option<usize>,
250 pub allow_self_loops: bool,
252 pub allow_multiple_edges: bool,
254}
255
256impl Default for GraphConfig {
257 fn default() -> Self {
258 Self {
259 strategy: GraphStrategy::AddWins,
260 preserve_deleted: true,
261 max_vertices: None,
262 max_edges: None,
263 allow_self_loops: false,
264 allow_multiple_edges: false,
265 }
266 }
267}
268
269#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
274pub struct AddWinsGraph<T> {
275 config: GraphConfig,
277 vertices: HashMap<VertexId, Vertex<T>>,
279 edges: HashMap<EdgeId, Edge>,
281 replica: ReplicaId,
283}
284
285impl<T: Clone + PartialEq + Eq + Send + Sync> AddWinsGraph<T> {
286 pub fn new(replica: ReplicaId) -> Self {
288 Self {
289 config: GraphConfig::default(),
290 vertices: HashMap::new(),
291 edges: HashMap::new(),
292 replica,
293 }
294 }
295
296 pub fn with_config(replica: ReplicaId, config: GraphConfig) -> Self {
298 Self {
299 config,
300 vertices: HashMap::new(),
301 edges: HashMap::new(),
302 replica,
303 }
304 }
305
306 pub fn add_vertex(&mut self, value: T, timestamp: u64) -> VertexId {
308 let vertex = Vertex::new(value, self.replica, timestamp);
309 let id = vertex.id.clone();
310 self.vertices.insert(id.clone(), vertex);
311 id
312 }
313
314 pub fn add_edge(&mut self, source: &VertexId, target: &VertexId, timestamp: u64, weight: Option<f64>) -> Result<EdgeId, GraphError> {
316 if !self.vertices.contains_key(source) || !self.vertices.contains_key(target) {
318 return Err(GraphError::new("Source or target vertex not found".to_string()));
319 }
320
321 if !self.config.allow_self_loops && source == target {
323 return Err(GraphError::new("Self-loops are not allowed".to_string()));
324 }
325
326 if !self.config.allow_multiple_edges {
328 for edge in self.edges.values() {
329 if !edge.metadata.deleted && edge.source == *source && edge.target == *target {
330 return Err(GraphError::new("Multiple edges between same vertices not allowed".to_string()));
331 }
332 }
333 }
334
335 let edge = if let Some(w) = weight {
336 Edge::with_weight(source.clone(), target.clone(), w, self.replica, timestamp)
337 } else {
338 Edge::new(source.clone(), target.clone(), self.replica, timestamp)
339 };
340
341 let id = edge.id.clone();
342 self.edges.insert(id.clone(), edge);
343 Ok(id)
344 }
345
346 pub fn update_vertex(&mut self, id: &VertexId, value: T, timestamp: u64) -> Result<(), GraphError> {
348 if let Some(vertex) = self.vertices.get_mut(id) {
349 vertex.value = value;
350 vertex.mark_modified(self.replica, timestamp);
351 Ok(())
352 } else {
353 Err(GraphError::new("Vertex not found".to_string()))
354 }
355 }
356
357 pub fn update_edge(&mut self, id: &EdgeId, weight: f64, timestamp: u64) -> Result<(), GraphError> {
359 if let Some(edge) = self.edges.get_mut(id) {
360 edge.weight = Some(weight);
361 edge.mark_modified(self.replica, timestamp);
362 Ok(())
363 } else {
364 Err(GraphError::new("Edge not found".to_string()))
365 }
366 }
367
368 pub fn remove_vertex(&mut self, id: &VertexId, timestamp: u64) -> Result<(), GraphError> {
370 if let Some(vertex) = self.vertices.get_mut(id) {
371 vertex.mark_deleted(self.replica, timestamp);
372
373 for edge in self.edges.values_mut() {
375 if !edge.metadata.deleted && (edge.source == *id || edge.target == *id) {
376 edge.mark_deleted(self.replica, timestamp);
377 }
378 }
379 Ok(())
380 } else {
381 Err(GraphError::new("Vertex not found".to_string()))
382 }
383 }
384
385 pub fn remove_edge(&mut self, id: &EdgeId, timestamp: u64) -> Result<(), GraphError> {
387 if let Some(edge) = self.edges.get_mut(id) {
388 edge.mark_deleted(self.replica, timestamp);
389 Ok(())
390 } else {
391 Err(GraphError::new("Edge not found".to_string()))
392 }
393 }
394
395 pub fn get_vertex(&self, id: &VertexId) -> Option<&Vertex<T>> {
397 self.vertices.get(id)
398 }
399
400 pub fn get_edge(&self, id: &EdgeId) -> Option<&Edge> {
402 self.edges.get(id)
403 }
404
405 pub fn visible_vertices(&self) -> Vec<&Vertex<T>> {
407 self.vertices
408 .values()
409 .filter(|v| !v.metadata.deleted)
410 .collect()
411 }
412
413 pub fn visible_edges(&self) -> Vec<&Edge> {
415 self.edges
416 .values()
417 .filter(|e| !e.metadata.deleted)
418 .collect()
419 }
420
421 pub fn all_vertices(&self) -> Vec<&Vertex<T>> {
423 self.vertices.values().collect()
424 }
425
426 pub fn all_edges(&self) -> Vec<&Edge> {
428 self.edges.values().collect()
429 }
430
431 pub fn neighbors(&self, id: &VertexId) -> Vec<&Vertex<T>> {
433 let mut neighbors = Vec::new();
434
435 for edge in self.edges.values() {
436 if !edge.metadata.deleted {
437 if edge.source == *id {
438 if let Some(target) = self.vertices.get(&edge.target) {
439 if !target.metadata.deleted {
440 neighbors.push(target);
441 }
442 }
443 } else if edge.target == *id {
444 if let Some(source) = self.vertices.get(&edge.source) {
445 if !source.metadata.deleted {
446 neighbors.push(source);
447 }
448 }
449 }
450 }
451 }
452
453 neighbors
454 }
455
456 pub fn incoming_edges(&self, id: &VertexId) -> Vec<&Edge> {
458 self.edges
459 .values()
460 .filter(|e| !e.metadata.deleted && e.target == *id)
461 .collect()
462 }
463
464 pub fn outgoing_edges(&self, id: &VertexId) -> Vec<&Edge> {
466 self.edges
467 .values()
468 .filter(|e| !e.metadata.deleted && e.source == *id)
469 .collect()
470 }
471
472 pub fn shortest_path(&self, source: &VertexId, target: &VertexId) -> Option<Vec<VertexId>> {
474 if !self.vertices.contains_key(source) || !self.vertices.contains_key(target) {
475 return None;
476 }
477
478 let mut visited = HashSet::new();
479 let mut queue = VecDeque::new();
480 let mut parent: HashMap<VertexId, VertexId> = HashMap::new();
481
482 queue.push_back(source.clone());
483 visited.insert(source.clone());
484
485 while let Some(current) = queue.pop_front() {
486 if current == *target {
487 let mut path = Vec::new();
489 let mut current_id = current;
490
491 while current_id != *source {
492 path.push(current_id.clone());
493 current_id = parent[¤t_id].clone();
494 }
495 path.push(source.clone());
496 path.reverse();
497 return Some(path);
498 }
499
500 for neighbor in self.neighbors(¤t) {
501 if !visited.contains(&neighbor.id) {
502 visited.insert(neighbor.id.clone());
503 parent.insert(neighbor.id.clone(), current.clone());
504 queue.push_back(neighbor.id.clone());
505 }
506 }
507 }
508
509 None
510 }
511
512 pub fn contains_vertex(&self, id: &VertexId) -> bool {
514 self.vertices.contains_key(id)
515 }
516
517 pub fn contains_edge(&self, id: &EdgeId) -> bool {
519 self.edges.contains_key(id)
520 }
521
522 pub fn vertex_count(&self) -> usize {
524 self.visible_vertices().len()
525 }
526
527 pub fn edge_count(&self) -> usize {
529 self.visible_edges().len()
530 }
531
532 pub fn is_empty(&self) -> bool {
534 self.vertex_count() == 0
535 }
536
537 pub fn clear(&mut self) {
539 self.vertices.clear();
540 self.edges.clear();
541 }
542}
543
544impl<T: Clone + PartialEq + Eq + Send + Sync> CRDT for AddWinsGraph<T> {
545 fn replica_id(&self) -> &ReplicaId {
546 &self.replica
547 }
548}
549
550impl<T: Clone + PartialEq + Eq + Send + Sync> Mergeable for AddWinsGraph<T> {
551 type Error = GraphError;
552
553 fn merge(&mut self, other: &Self) -> Result<(), Self::Error> {
554 for (id, vertex) in &other.vertices {
556 match self.vertices.get(id) {
557 Some(existing) => {
558 if vertex.metadata.modified_at > existing.metadata.modified_at {
560 self.vertices.insert(id.clone(), vertex.clone());
561 }
562 }
563 None => {
564 self.vertices.insert(id.clone(), vertex.clone());
566 }
567 }
568 }
569
570 for (id, edge) in &other.edges {
572 match self.edges.get(id) {
573 Some(existing) => {
574 if edge.metadata.modified_at > existing.metadata.modified_at {
576 self.edges.insert(id.clone(), edge.clone());
577 }
578 }
579 None => {
580 self.edges.insert(id.clone(), edge.clone());
582 }
583 }
584 }
585
586 Ok(())
587 }
588
589 fn has_conflict(&self, other: &Self) -> bool {
590 for (id, vertex) in &other.vertices {
592 if let Some(existing) = self.vertices.get(id) {
593 if vertex.metadata.modified_at == existing.metadata.modified_at
594 && vertex.metadata.last_modified_by != existing.metadata.last_modified_by
595 {
596 return true;
597 }
598 }
599 }
600
601 for (id, edge) in &other.edges {
603 if let Some(existing) = self.edges.get(id) {
604 if edge.metadata.modified_at == existing.metadata.modified_at
605 && edge.metadata.last_modified_by != existing.metadata.last_modified_by
606 {
607 return true;
608 }
609 }
610 }
611 false
612 }
613}
614
615#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
620pub struct RemoveWinsGraph<T> {
621 config: GraphConfig,
623 vertices: HashMap<VertexId, Vertex<T>>,
625 edges: HashMap<EdgeId, Edge>,
627 replica: ReplicaId,
629}
630
631impl<T: Clone + PartialEq + Eq + Send + Sync> RemoveWinsGraph<T> {
632 pub fn new(replica: ReplicaId) -> Self {
634 Self {
635 config: GraphConfig {
636 strategy: GraphStrategy::RemoveWins,
637 preserve_deleted: false,
638 max_vertices: None,
639 max_edges: None,
640 allow_self_loops: false,
641 allow_multiple_edges: false,
642 },
643 vertices: HashMap::new(),
644 edges: HashMap::new(),
645 replica,
646 }
647 }
648
649 pub fn with_config(replica: ReplicaId, config: GraphConfig) -> Self {
651 Self {
652 config,
653 vertices: HashMap::new(),
654 edges: HashMap::new(),
655 replica,
656 }
657 }
658
659 pub fn add_vertex(&mut self, value: T, timestamp: u64) -> VertexId {
661 let vertex = Vertex::new(value, self.replica, timestamp);
662 let id = vertex.id.clone();
663 self.vertices.insert(id.clone(), vertex);
664 id
665 }
666
667 pub fn add_edge(&mut self, source: &VertexId, target: &VertexId, timestamp: u64, weight: Option<f64>) -> Result<EdgeId, GraphError> {
669 if !self.vertices.contains_key(source) || !self.vertices.contains_key(target) {
671 return Err(GraphError::new("Source or target vertex not found".to_string()));
672 }
673
674 if !self.config.allow_self_loops && source == target {
676 return Err(GraphError::new("Self-loops are not allowed".to_string()));
677 }
678
679 if !self.config.allow_multiple_edges {
681 for edge in self.edges.values() {
682 if edge.source == *source && edge.target == *target {
683 return Err(GraphError::new("Multiple edges between same vertices not allowed".to_string()));
684 }
685 }
686 }
687
688 let edge = if let Some(w) = weight {
689 Edge::with_weight(source.clone(), target.clone(), w, self.replica, timestamp)
690 } else {
691 Edge::new(source.clone(), target.clone(), self.replica, timestamp)
692 };
693
694 let id = edge.id.clone();
695 self.edges.insert(id.clone(), edge);
696 Ok(id)
697 }
698
699 pub fn update_vertex(&mut self, id: &VertexId, value: T, timestamp: u64) -> Result<(), GraphError> {
701 if let Some(vertex) = self.vertices.get_mut(id) {
702 vertex.value = value;
703 vertex.mark_modified(self.replica, timestamp);
704 Ok(())
705 } else {
706 Err(GraphError::new("Vertex not found".to_string()))
707 }
708 }
709
710 pub fn update_edge(&mut self, id: &EdgeId, weight: f64, timestamp: u64) -> Result<(), GraphError> {
712 if let Some(edge) = self.edges.get_mut(id) {
713 edge.weight = Some(weight);
714 edge.mark_modified(self.replica, timestamp);
715 Ok(())
716 } else {
717 Err(GraphError::new("Edge not found".to_string()))
718 }
719 }
720
721 pub fn remove_vertex(&mut self, id: &VertexId) -> Result<(), GraphError> {
723 if self.vertices.remove(id).is_some() {
724 self.edges.retain(|_, edge| edge.source != *id && edge.target != *id);
726 Ok(())
727 } else {
728 Err(GraphError::new("Vertex not found".to_string()))
729 }
730 }
731
732 pub fn remove_edge(&mut self, id: &EdgeId) -> Result<(), GraphError> {
734 if self.edges.remove(id).is_some() {
735 Ok(())
736 } else {
737 Err(GraphError::new("Edge not found".to_string()))
738 }
739 }
740
741 pub fn get_vertex(&self, id: &VertexId) -> Option<&Vertex<T>> {
743 self.vertices.get(id)
744 }
745
746 pub fn get_edge(&self, id: &EdgeId) -> Option<&Edge> {
748 self.edges.get(id)
749 }
750
751 pub fn vertices(&self) -> Vec<&Vertex<T>> {
753 self.vertices.values().collect()
754 }
755
756 pub fn edges(&self) -> Vec<&Edge> {
758 self.edges.values().collect()
759 }
760
761 pub fn neighbors(&self, id: &VertexId) -> Vec<&Vertex<T>> {
763 let mut neighbors = Vec::new();
764
765 for edge in self.edges.values() {
766 if edge.source == *id {
767 if let Some(target) = self.vertices.get(&edge.target) {
768 neighbors.push(target);
769 }
770 } else if edge.target == *id {
771 if let Some(source) = self.vertices.get(&edge.source) {
772 neighbors.push(source);
773 }
774 }
775 }
776
777 neighbors
778 }
779
780 pub fn incoming_edges(&self, id: &VertexId) -> Vec<&Edge> {
782 self.edges
783 .values()
784 .filter(|e| e.target == *id)
785 .collect()
786 }
787
788 pub fn outgoing_edges(&self, id: &VertexId) -> Vec<&Edge> {
790 self.edges
791 .values()
792 .filter(|e| e.source == *id)
793 .collect()
794 }
795
796 pub fn shortest_path(&self, source: &VertexId, target: &VertexId) -> Option<Vec<VertexId>> {
798 if !self.vertices.contains_key(source) || !self.vertices.contains_key(target) {
799 return None;
800 }
801
802 let mut visited = HashSet::new();
803 let mut queue = VecDeque::new();
804 let mut parent: HashMap<VertexId, VertexId> = HashMap::new();
805
806 queue.push_back(source.clone());
807 visited.insert(source.clone());
808
809 while let Some(current) = queue.pop_front() {
810 if current == *target {
811 let mut path = Vec::new();
813 let mut current_id = current;
814
815 while current_id != *source {
816 path.push(current_id.clone());
817 current_id = parent[¤t_id].clone();
818 }
819 path.push(source.clone());
820 path.reverse();
821 return Some(path);
822 }
823
824 for neighbor in self.neighbors(¤t) {
825 if !visited.contains(&neighbor.id) {
826 visited.insert(neighbor.id.clone());
827 parent.insert(neighbor.id.clone(), current.clone());
828 queue.push_back(neighbor.id.clone());
829 }
830 }
831 }
832
833 None
834 }
835
836 pub fn contains_vertex(&self, id: &VertexId) -> bool {
838 self.vertices.contains_key(id)
839 }
840
841 pub fn contains_edge(&self, id: &EdgeId) -> bool {
843 self.edges.contains_key(id)
844 }
845
846 pub fn vertex_count(&self) -> usize {
848 self.vertices.len()
849 }
850
851 pub fn edge_count(&self) -> usize {
853 self.edges.len()
854 }
855
856 pub fn is_empty(&self) -> bool {
858 self.vertex_count() == 0
859 }
860
861 pub fn clear(&mut self) {
863 self.vertices.clear();
864 self.edges.clear();
865 }
866}
867
868impl<T: Clone + PartialEq + Eq + Send + Sync> CRDT for RemoveWinsGraph<T> {
869 fn replica_id(&self) -> &ReplicaId {
870 &self.replica
871 }
872}
873
874impl<T: Clone + PartialEq + Eq + Send + Sync> Mergeable for RemoveWinsGraph<T> {
875 type Error = GraphError;
876
877 fn merge(&mut self, other: &Self) -> Result<(), Self::Error> {
878 for (id, vertex) in &other.vertices {
880 match self.vertices.get(id) {
881 Some(existing) => {
882 if vertex.metadata.modified_at > existing.metadata.modified_at {
884 self.vertices.insert(id.clone(), vertex.clone());
885 }
886 }
887 None => {
888 self.vertices.insert(id.clone(), vertex.clone());
890 }
891 }
892 }
893
894 for (id, edge) in &other.edges {
896 match self.edges.get(id) {
897 Some(existing) => {
898 if edge.metadata.modified_at > existing.metadata.modified_at {
900 self.edges.insert(id.clone(), edge.clone());
901 }
902 }
903 None => {
904 self.edges.insert(id.clone(), edge.clone());
906 }
907 }
908 }
909
910 Ok(())
911 }
912
913 fn has_conflict(&self, other: &Self) -> bool {
914 for (id, vertex) in &other.vertices {
916 if let Some(existing) = self.vertices.get(id) {
917 if vertex.metadata.modified_at == existing.metadata.modified_at
918 && vertex.metadata.last_modified_by != existing.metadata.last_modified_by
919 {
920 return true;
921 }
922 }
923 }
924
925 for (id, edge) in &other.edges {
927 if let Some(existing) = self.edges.get(id) {
928 if edge.metadata.modified_at == existing.metadata.modified_at
929 && edge.metadata.last_modified_by != existing.metadata.last_modified_by
930 {
931 return true;
932 }
933 }
934 }
935 false
936 }
937}
938
939#[cfg(test)]
940mod tests {
941 use super::*;
942 use super::super::ReplicaId;
943 use uuid::Uuid;
944
945 fn create_replica(id: u64) -> ReplicaId {
946 ReplicaId::from(Uuid::from_u64_pair(0, id))
947 }
948
949 #[test]
950 fn test_vertex_id_creation() {
951 let replica = create_replica(1);
952 let vertex_id = VertexId::new(replica);
953
954 assert_eq!(vertex_id.replica, replica);
955 assert_ne!(vertex_id.id, Uuid::nil());
956 }
957
958 #[test]
959 fn test_edge_id_creation() {
960 let replica = create_replica(1);
961 let edge_id = EdgeId::new(replica);
962
963 assert_eq!(edge_id.replica, replica);
964 assert_ne!(edge_id.id, Uuid::nil());
965 }
966
967 #[test]
968 fn test_vertex_creation() {
969 let replica = create_replica(1);
970 let timestamp = 1234567890;
971 let vertex = Vertex::new("test_value", replica, timestamp);
972
973 assert_eq!(vertex.value, "test_value");
974 assert_eq!(vertex.metadata.created_at, timestamp);
975 assert_eq!(vertex.metadata.modified_at, timestamp);
976 assert_eq!(vertex.metadata.deleted, false);
977 assert_eq!(vertex.metadata.last_modified_by, replica);
978 }
979
980 #[test]
981 fn test_edge_creation() {
982 let replica = create_replica(1);
983 let timestamp = 1234567890;
984 let source = VertexId::new(replica);
985 let target = VertexId::new(replica);
986 let edge = Edge::new(source.clone(), target.clone(), replica, timestamp);
987
988 assert_eq!(edge.source, source);
989 assert_eq!(edge.target, target);
990 assert_eq!(edge.weight, None);
991 assert_eq!(edge.metadata.created_at, timestamp);
992 assert_eq!(edge.metadata.deleted, false);
993 }
994
995 #[test]
996 fn test_edge_with_weight() {
997 let replica = create_replica(1);
998 let timestamp = 1234567890;
999 let source = VertexId::new(replica);
1000 let target = VertexId::new(replica);
1001 let weight = 5.5;
1002 let edge = Edge::with_weight(source.clone(), target.clone(), weight, replica, timestamp);
1003
1004 assert_eq!(edge.weight, Some(weight));
1005 }
1006
1007 #[test]
1008 fn test_add_wins_graph_basic_operations() {
1009 let replica = create_replica(1);
1010 let mut graph = AddWinsGraph::new(replica);
1011
1012 let v1_id = graph.add_vertex("vertex1", 1000);
1014 let v2_id = graph.add_vertex("vertex2", 2000);
1015
1016 assert_eq!(graph.vertex_count(), 2);
1017 assert!(graph.contains_vertex(&v1_id));
1018 assert!(graph.contains_vertex(&v2_id));
1019
1020 let edge_id = graph.add_edge(&v1_id, &v2_id, 3000, None).unwrap();
1022 assert_eq!(graph.edge_count(), 1);
1023 assert!(graph.contains_edge(&edge_id));
1024
1025 graph.update_vertex(&v1_id, "updated_vertex1", 4000).unwrap();
1027 assert_eq!(graph.get_vertex(&v1_id).unwrap().value, "updated_vertex1");
1028 }
1029
1030 #[test]
1031 fn test_remove_wins_graph_basic_operations() {
1032 let replica = create_replica(1);
1033 let mut graph = RemoveWinsGraph::new(replica);
1034
1035 let v1_id = graph.add_vertex("vertex1", 1000);
1037 let v2_id = graph.add_vertex("vertex2", 2000);
1038 let edge_id = graph.add_edge(&v1_id, &v2_id, 3000, None).unwrap();
1039
1040 assert_eq!(graph.vertex_count(), 2);
1041 assert_eq!(graph.edge_count(), 1);
1042
1043 graph.remove_edge(&edge_id).unwrap();
1045 assert_eq!(graph.edge_count(), 0);
1046 assert!(!graph.contains_edge(&edge_id));
1047
1048 graph.remove_vertex(&v1_id).unwrap();
1050 assert_eq!(graph.vertex_count(), 1);
1051 assert!(!graph.contains_vertex(&v1_id));
1052 }
1053
1054 #[test]
1055 fn test_graph_neighbors() {
1056 let replica = create_replica(1);
1057 let mut graph = AddWinsGraph::new(replica);
1058
1059 let v1_id = graph.add_vertex("vertex1", 1000);
1061 let v2_id = graph.add_vertex("vertex2", 2000);
1062 let v3_id = graph.add_vertex("vertex3", 3000);
1063
1064 graph.add_edge(&v1_id, &v2_id, 4000, None).unwrap();
1065 graph.add_edge(&v2_id, &v3_id, 5000, None).unwrap();
1066 graph.add_edge(&v3_id, &v1_id, 6000, None).unwrap();
1067
1068 let v1_neighbors = graph.neighbors(&v1_id);
1070 assert_eq!(v1_neighbors.len(), 2); let v2_neighbors = graph.neighbors(&v2_id);
1073 assert_eq!(v2_neighbors.len(), 2); let v3_neighbors = graph.neighbors(&v3_id);
1076 assert_eq!(v3_neighbors.len(), 2); }
1078
1079 #[test]
1080 fn test_graph_shortest_path() {
1081 let replica = create_replica(1);
1082 let mut graph = AddWinsGraph::new(replica);
1083
1084 let v1_id = graph.add_vertex("vertex1", 1000);
1086 let v2_id = graph.add_vertex("vertex2", 2000);
1087 let v3_id = graph.add_vertex("vertex3", 3000);
1088 let v4_id = graph.add_vertex("vertex4", 4000);
1089
1090 graph.add_edge(&v1_id, &v2_id, 5000, None).unwrap();
1091 graph.add_edge(&v2_id, &v3_id, 6000, None).unwrap();
1092 graph.add_edge(&v3_id, &v4_id, 7000, None).unwrap();
1093
1094 let path = graph.shortest_path(&v1_id, &v4_id).unwrap();
1096 assert_eq!(path.len(), 4);
1097 assert_eq!(path[0], v1_id);
1098 assert_eq!(path[1], v2_id);
1099 assert_eq!(path[2], v3_id);
1100 assert_eq!(path[3], v4_id);
1101 }
1102
1103 #[test]
1104 fn test_graph_merge() {
1105 let replica1 = create_replica(1);
1106 let replica2 = create_replica(2);
1107
1108 let mut graph1 = AddWinsGraph::new(replica1);
1109 let mut graph2 = AddWinsGraph::new(replica2);
1110
1111 let v1_id = graph1.add_vertex("vertex1", 1000);
1113 let v2_id = graph2.add_vertex("vertex2", 2000);
1114
1115 graph1.merge(&graph2).unwrap();
1117
1118 assert_eq!(graph1.vertex_count(), 2);
1120 assert!(graph1.contains_vertex(&v1_id));
1121 assert!(graph1.contains_vertex(&v2_id));
1122 }
1123
1124 #[test]
1125 fn test_graph_configuration() {
1126 let replica = create_replica(1);
1127 let config = GraphConfig {
1128 strategy: GraphStrategy::RemoveWins,
1129 preserve_deleted: false,
1130 max_vertices: Some(100),
1131 max_edges: Some(200),
1132 allow_self_loops: true,
1133 allow_multiple_edges: true,
1134 };
1135
1136 let graph: AddWinsGraph<String> = AddWinsGraph::with_config(replica, config);
1137 assert_eq!(graph.config.strategy, GraphStrategy::RemoveWins);
1138 assert_eq!(graph.config.max_vertices, Some(100));
1139 assert_eq!(graph.config.allow_self_loops, true);
1140 assert_eq!(graph.config.allow_multiple_edges, true);
1141 }
1142
1143 #[test]
1144 fn test_graph_validation() {
1145 let replica = create_replica(1);
1146 let mut graph = AddWinsGraph::new(replica);
1147
1148 let v1_id = graph.add_vertex("vertex1", 1000);
1150 let v2_id = graph.add_vertex("vertex2", 2000);
1151
1152 let fake_id = VertexId::new(create_replica(999));
1154 let result = graph.add_edge(&v1_id, &fake_id, 3000, None);
1155 assert!(result.is_err());
1156
1157 let result = graph.add_edge(&v1_id, &v1_id, 3000, None);
1159 assert!(result.is_err());
1160 }
1161}