use sqlitegraph::{
EdgeSpec, NodeSpec, SnapshotId,
backend::native::types::NativeNodeId,
backend::native::v2::edge_cluster::{CompactEdgeRecord, Direction, EdgeCluster},
backend::native::v2::node_record_v2::NodeRecordV2,
backend::native::v2::string_table::StringTable,
backend::native::{AdjacencyIterator, EdgeStore, GraphFile, NodeStore},
config::GraphConfig,
open_graph,
};
use tempfile::TempDir;
#[test]
fn v2_single_outgoing_neighbors_use_clustered_path() {
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test_v2_single_outgoing.db");
let config = GraphConfig::native();
let graph = open_graph(&db_path, &config).unwrap();
let node1_id = graph
.insert_node(NodeSpec {
kind: "Node".to_string(),
name: "node1".to_string(),
file_path: None,
data: serde_json::json!({"test": "outgoing"}),
})
.unwrap();
let node2_id = graph
.insert_node(NodeSpec {
kind: "Node".to_string(),
name: "node2".to_string(),
file_path: None,
data: serde_json::json!({"test": "target"}),
})
.unwrap();
graph
.insert_edge(EdgeSpec {
from: node1_id,
to: node2_id,
edge_type: "test_edge".to_string(),
data: serde_json::json!({"weight": 1.0, "test": true}),
})
.unwrap();
let neighbors = graph
.neighbors(SnapshotId::current(), node1_id, sqlitegraph::NeighborQuery {
direction: sqlitegraph::BackendDirection::Outgoing,
edge_type: None,
},
)
.unwrap();
println!(
"DEBUG: V2 outgoing neighbors from node {}: {:?}",
node1_id, neighbors
);
assert_eq!(
neighbors.len(),
1,
"Should have exactly 1 outgoing neighbor"
);
assert_eq!(neighbors[0], node2_id, "Outgoing neighbor should be node2");
let mut graph_file = GraphFile::open(&db_path).unwrap();
let mut node_store = NodeStore::new(&mut graph_file);
let node1 = node_store.read_node_v2(node1_id as NativeNodeId).unwrap();
assert!(
node1.has_outgoing_edges(),
"Node1 should have V2 outgoing cluster metadata"
);
assert_eq!(
node1.outgoing_edge_count, 1,
"Node1 should have 1 outgoing edge in V2 metadata"
);
}
#[test]
fn v2_single_incoming_neighbors_use_clustered_path() {
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test_v2_single_incoming.db");
let config = GraphConfig::native();
let graph = open_graph(&db_path, &config).unwrap();
let node1_id = graph
.insert_node(NodeSpec {
kind: "Source".to_string(),
name: "source".to_string(),
file_path: None,
data: serde_json::json!({"role": "source"}),
})
.unwrap();
let node2_id = graph
.insert_node(NodeSpec {
kind: "Target".to_string(),
name: "target".to_string(),
file_path: None,
data: serde_json::json!({"role": "target"}),
})
.unwrap();
graph
.insert_edge(EdgeSpec {
from: node1_id,
to: node2_id,
edge_type: "connects".to_string(),
data: serde_json::json!({"type": "direct", "strength": 0.9}),
})
.unwrap();
let neighbors = graph
.neighbors(SnapshotId::current(), node2_id, sqlitegraph::NeighborQuery {
direction: sqlitegraph::BackendDirection::Incoming,
edge_type: None,
},
)
.unwrap();
println!(
"DEBUG: V2 incoming neighbors to node {}: {:?}",
node2_id, neighbors
);
assert_eq!(
neighbors.len(),
1,
"Should have exactly 1 incoming neighbor"
);
assert_eq!(neighbors[0], node1_id, "Incoming neighbor should be node1");
let mut graph_file = GraphFile::open(&db_path).unwrap();
let mut node_store = NodeStore::new(&mut graph_file);
let node2 = node_store.read_node_v2(node2_id as NativeNodeId).unwrap();
assert!(
node2.has_incoming_edges(),
"Node2 should have V2 incoming cluster metadata"
);
assert_eq!(
node2.incoming_edge_count, 1,
"Node2 should have 1 incoming edge in V2 metadata"
);
}
#[test]
fn v2_multi_edge_neighbors_preserve_all_edges() {
let temp_dir = TempDir::new().unwrap();
let db_path = temp_dir.path().join("test_v2_multi_edge.db");
let config = GraphConfig::native();
let graph = open_graph(&db_path, &config).unwrap();
let source_id = graph
.insert_node(NodeSpec {
kind: "Source".to_string(),
name: "source".to_string(),
file_path: None,
data: serde_json::json!({"role": "multi_source"}),
})
.unwrap();
let mut target_ids = Vec::new();
for i in 1..=3 {
let target_id = graph
.insert_node(NodeSpec {
kind: "Target".to_string(),
name: format!("target_{}", i),
file_path: None,
data: serde_json::json!({"index": i, "role": "target"}),
})
.unwrap();
target_ids.push(target_id);
graph
.insert_edge(EdgeSpec {
from: source_id,
to: target_id,
edge_type: format!("edge_type_{}", i),
data: serde_json::json!({"index": i, "weight": i as f64 * 0.5}),
})
.unwrap();
}
let neighbors = graph
.neighbors(SnapshotId::current(), source_id, sqlitegraph::NeighborQuery {
direction: sqlitegraph::BackendDirection::Outgoing,
edge_type: None,
},
)
.unwrap();
println!(
"DEBUG: V2 multi-edge neighbors from source {}: {:?}",
source_id, neighbors
);
assert_eq!(
neighbors.len(),
3,
"Should have exactly 3 outgoing neighbors"
);
let mut sorted_neighbors = neighbors.clone();
sorted_neighbors.sort();
let mut sorted_targets = target_ids.clone();
sorted_targets.sort();
assert_eq!(
sorted_neighbors, sorted_targets,
"All 3 target nodes should be returned as neighbors"
);
let mut graph_file = GraphFile::open(&db_path).unwrap();
let mut node_store = NodeStore::new(&mut graph_file);
let source_node = node_store.read_node_v2(source_id as NativeNodeId).unwrap();
assert_eq!(
source_node.outgoing_edge_count, 3,
"Source should have 3 outgoing edges in V2 metadata"
);
assert!(
source_node.has_outgoing_edges(),
"Source should have V2 outgoing cluster metadata"
);
}