use std::sync::{Arc, Mutex};
use crate::sharding::*;
#[test]
fn test_csr_shard_real_graph() {
let mut shard = CsrShard::new(0, 0, 1000);
for i in 0..100 {
let caller = i * 10;
let callee = (i + 1) * 10;
shard.add_edge(CsrEdge {
src: caller,
dst: callee,
weight: 0.8,
flags: 0,
});
}
shard.sort_edges();
assert_eq!(shard.edge_count(), 100);
assert_eq!(shard.edges[0].src, 0);
assert_eq!(shard.edges[99].dst, 1000);
}
#[test]
fn test_subgraph_builder_dependency_chain() {
let mut shard = CsrShard::new(0, 1000, 2000);
let deps = vec![
(1000, 1050), (1050, 1100), (1100, 1150), (1150, 1200), ];
for (src, dst) in deps {
shard.add_edge(CsrEdge {
src,
dst,
weight: 1.0,
flags: 0,
});
}
shard.sort_edges();
assert_eq!(shard.edge_count(), 4);
assert_eq!(shard.edges[0].src, 1000);
assert_eq!(shard.edges[0].dst, 1050);
}
#[test]
fn test_bidirectional_index_call_graph() {
let mut shard = CsrShard::new(0, 1000, 2000);
let callers = vec![1000, 1050, 1100];
let callee = 2000;
for caller in &callers {
shard.add_edge(CsrEdge {
src: *caller,
dst: callee,
weight: 0.5,
flags: 0,
});
}
shard.sort_edges();
let total_weight: f32 = shard.edges.iter().map(|e| e.weight).sum();
assert_eq!(total_weight, 1.5); }
#[test]
fn test_hnsw_semantic_layer_code_embeddings() {
let mut layer = SemanticLayer::new(128);
let functions = vec![
(100, "parse_input"),
(200, "validate_data"),
(300, "process_request"),
(400, "handle_error"),
];
for (func_id, _name) in functions {
let embedding: Vec<f32> = (0..128).map(|i| i as f32 / 1000.0).collect();
layer.insert_embedding(func_id, embedding).unwrap();
}
let query: Vec<f32> = (0..128).map(|i| i as f32 / 1000.0).collect();
let results = layer.knn_search(&query, 2);
assert_eq!(results.len(), 2);
assert_eq!(results[0].node_id, 100);
}
#[test]
fn test_property_store_function_metadata() {
let mut store = PropertyStore::in_memory().unwrap();
store.set_token_text(1000, "parse_input").unwrap();
store
.set_metadata(
1000,
"{\"type\": \"function\", \"file\": \"parser.rs\", \"line\": 42}",
)
.unwrap();
let text = store.get_token_text(1000).unwrap();
let metadata = store.get_metadata(1000).unwrap();
assert_eq!(text, Some("parse_input".to_string()));
let parsed: serde_json::Value = metadata.unwrap().parse().unwrap();
assert_eq!(parsed["type"], "function");
assert_eq!(parsed["file"], "parser.rs");
assert_eq!(parsed["line"], 42);
}
#[test]
fn test_pubsub_graph_operations() {
let pubsub = PubSub::new();
let notified = Arc::new(Mutex::new(Vec::new()));
let notified_clone = notified.clone();
pubsub.subscribe(
vec!["graph.edge".to_string()],
Box::new(move |change| {
notified_clone.lock().unwrap().push(change.clone());
}),
);
pubsub.publish(Change::edge_deleted(1000, 1050, "graph.edge".to_string()));
pubsub.publish(Change::edge_inserted(1000, 1100, "graph.edge".to_string()));
std::thread::sleep(std::time::Duration::from_millis(10));
let notifications = notified.lock().unwrap();
assert_eq!(notifications.len(), 2);
assert!(matches!(
notifications[0].change_type,
ChangeType::EdgeDeleted
));
assert!(matches!(
notifications[1].change_type,
ChangeType::EdgeInserted
));
}
#[test]
fn test_csr_hnsw_fallback_integration() {
let mut shard = CsrShard::new(0, 1000, 2000);
shard.add_edge(CsrEdge {
src: 1000,
dst: 1050,
weight: 0.9,
flags: 0,
});
let mut layer = SemanticLayer::new(64);
let embedding1: Vec<f32> = (0..64).map(|i| i as f32).collect();
let embedding2: Vec<f32> = (0..64).map(|i| (i as f32) + 0.1).collect();
layer.insert_embedding(1000, embedding1).unwrap();
layer.insert_embedding(1050, embedding2).unwrap();
assert_eq!(shard.edge_count(), 1);
assert_eq!(shard.edges[0].src, 1000);
assert_eq!(shard.edges[0].dst, 1050);
let query: Vec<f32> = (0..64).map(|i| i as f32).collect();
let semantic_results = layer.knn_search(&query, 2);
assert_eq!(semantic_results.len(), 2);
}
#[test]
fn test_multi_shard_cross_shard_edges() {
let mut shard1 = CsrShard::new(0, 0, 1000);
let mut shard2 = CsrShard::new(1, 1000, 2000);
shard1.add_edge(CsrEdge {
src: 500,
dst: 1500,
weight: 0.7,
flags: 0,
});
shard2.add_edge(CsrEdge {
src: 1500,
dst: 1800,
weight: 0.8,
flags: 0,
});
shard1.sort_edges();
shard2.sort_edges();
assert_eq!(shard1.edge_count(), 1);
assert_eq!(shard2.edge_count(), 1);
assert_eq!(shard1.edges[0].dst, 1500); }
#[test]
fn test_property_store_multiple_tokens() {
let mut store = PropertyStore::in_memory().unwrap();
let functions = vec![
(1000, "parse"),
(1050, "validate"),
(1100, "process"),
(1150, "render"),
];
for (id, name) in functions {
store.set_token_text(id, name).unwrap();
}
let count = store.token_count().unwrap();
assert_eq!(count, 4);
let text = store.get_token_text(1100).unwrap();
assert_eq!(text, Some("process".to_string()));
store.delete_token(1050).unwrap();
assert_eq!(store.token_count().unwrap(), 3);
assert!(store.get_token_text(1050).unwrap().is_none());
}
#[test]
fn test_wal_replay_consistency() {
let pubsub = PubSub::new();
pubsub.publish(Change::node_inserted(100, "graph.node".to_string()));
pubsub.publish(Change::edge_inserted(100, 200, "graph.edge".to_string()));
pubsub.publish(Change::edge_deleted(200, 300, "graph.edge".to_string()));
let count = pubsub.change_log_size();
assert_eq!(count, 3);
pubsub.subscribe(
vec!["graph.edge".to_string(), "graph.node".to_string()],
Box::new(|_change| {
}),
);
let replayed = pubsub.replay_wal().unwrap();
assert!(replayed > 0);
pubsub.clear_change_log();
assert_eq!(pubsub.change_log_size(), 0);
}