use nika::StableDag;
#[test]
fn test_stable_index_after_deletion_invariant() {
let mut graph: StableDag<String> = StableDag::new();
let idx0 = graph.add_node("msg-001".to_string());
let idx1 = graph.add_node("msg-002".to_string());
let idx2 = graph.add_node("msg-003".to_string());
assert_eq!(idx0.index(), 0);
assert_eq!(idx1.index(), 1);
assert_eq!(idx2.index(), 2);
assert_eq!(graph.node_count(), 3);
let removed = graph.remove_node(idx1);
assert_eq!(removed, Some("msg-002".to_string()));
assert_eq!(idx0.index(), 0, "idx0 should remain 0");
assert_eq!(idx2.index(), 2, "idx2 should remain 2, NOT shift to 1");
assert_eq!(graph.node_count(), 2);
assert_eq!(graph.node_weight(idx0), Some(&"msg-001".to_string()));
assert_eq!(graph.node_weight(idx1), None); assert_eq!(graph.node_weight(idx2), Some(&"msg-003".to_string()));
}
#[test]
fn test_edges_survive_unrelated_node_deletion() {
let mut graph: StableDag<String> = StableDag::new();
let a = graph.add_node("A".to_string());
let b = graph.add_node("B".to_string());
let c = graph.add_node("C".to_string());
let d = graph.add_node("D".to_string());
graph.add_edge(a, b);
assert!(graph.has_edge(a, b));
graph.remove_node(c);
graph.remove_node(d);
assert!(
graph.has_edge(a, b),
"Edge should survive unrelated deletion"
);
assert_eq!(graph.edge_count(), 1);
}
#[test]
fn test_new_nodes_reuse_deleted_indices() {
let mut graph: StableDag<String> = StableDag::new();
let idx0 = graph.add_node("first".to_string());
let idx1 = graph.add_node("second".to_string());
graph.remove_node(idx1);
let idx_new = graph.add_node("third".to_string());
assert_eq!(idx_new.index(), 1, "New node should reuse deleted index");
assert_eq!(graph.node_weight(idx_new), Some(&"third".to_string()));
assert_eq!(graph.node_weight(idx0), Some(&"first".to_string()));
}
#[test]
fn test_flow_edge_with_label() {
let mut graph: StableDag<String> = StableDag::new();
let parent = graph.add_node("parent".to_string());
let child = graph.add_node("child".to_string());
let edge = graph.add_edge_with_label(parent, child, "replies_to");
assert!(edge.is_some());
assert!(graph.has_edge(parent, child));
assert!(!graph.has_edge(child, parent)); }
#[test]
fn test_stable_graph_serialization_roundtrip() {
let mut graph: StableDag<String> = StableDag::new();
let a = graph.add_node("node-a".to_string());
let b = graph.add_node("node-b".to_string());
graph.add_edge(a, b);
let json = serde_json::to_string(&graph).expect("serialize");
let restored: StableDag<String> = serde_json::from_str(&json).expect("deserialize");
assert_eq!(restored.node_count(), 2);
assert_eq!(restored.edge_count(), 1);
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
struct ChatMessage {
id: String,
role: String,
content: String,
}
#[test]
fn test_stable_graph_with_struct_weights() {
let mut graph: StableDag<ChatMessage> = StableDag::new();
let msg1 = ChatMessage {
id: "msg-001".to_string(),
role: "user".to_string(),
content: "Hello".to_string(),
};
let msg2 = ChatMessage {
id: "msg-002".to_string(),
role: "assistant".to_string(),
content: "Hi there!".to_string(),
};
let idx1 = graph.add_node(msg1.clone());
let idx2 = graph.add_node(msg2);
graph.add_edge(idx1, idx2);
assert_eq!(
graph.node_weight(idx1).map(|m| &m.id),
Some(&"msg-001".to_string())
);
assert!(graph.has_edge(idx1, idx2));
}