use ruvector_mincut::certificate::{AuditData, AuditEntryType, AuditLogger, CutCertificate};
use ruvector_mincut::connectivity::DynamicConnectivity;
use ruvector_mincut::instance::{InstanceResult, StubInstance, WitnessHandle};
use ruvector_mincut::prelude::*;
use ruvector_mincut::wrapper::MinCutWrapper;
use std::sync::Arc;
#[test]
fn test_connectivity_edge_cases() {
let mut dc = DynamicConnectivity::new();
assert!(!dc.is_connected());
assert_eq!(dc.component_count(), 0);
dc.add_vertex(0);
assert!(dc.is_connected()); assert_eq!(dc.component_count(), 1);
dc.add_vertex(1);
assert!(!dc.is_connected());
assert_eq!(dc.component_count(), 2);
}
#[test]
fn test_connectivity_path_compression() {
let mut dc = DynamicConnectivity::new();
for i in 0..5 {
dc.insert_edge(i, i + 1);
}
assert!(dc.connected(0, 5));
assert!(dc.connected(0, 3));
assert!(dc.connected(2, 4));
}
#[test]
fn test_connectivity_multiple_components() {
let mut dc = DynamicConnectivity::new();
dc.insert_edge(0, 1);
dc.insert_edge(1, 2);
dc.insert_edge(3, 4);
dc.add_vertex(5);
assert_eq!(dc.component_count(), 3);
assert!(dc.connected(0, 2));
assert!(dc.connected(3, 4));
assert!(!dc.connected(0, 3));
assert!(!dc.connected(0, 5));
}
#[test]
fn test_witness_large_vertex_ids() {
use roaring::RoaringBitmap;
let mut membership = RoaringBitmap::new();
membership.insert(u32::MAX - 1);
membership.insert(u32::MAX);
let witness = WitnessHandle::new((u32::MAX - 1) as u64, membership, 5);
assert!(witness.contains((u32::MAX - 1) as u64));
assert!(witness.contains(u32::MAX as u64));
assert!(!witness.contains(0));
}
#[test]
fn test_witness_equality() {
use roaring::RoaringBitmap;
let mut m1 = RoaringBitmap::new();
m1.insert(1);
m1.insert(2);
let mut m2 = RoaringBitmap::new();
m2.insert(1);
m2.insert(2);
let w1 = WitnessHandle::new(1, m1, 5);
let w2 = WitnessHandle::new(1, m2, 5);
assert_eq!(w1, w2);
}
#[test]
fn test_witness_materialize() {
use roaring::RoaringBitmap;
let mut membership = RoaringBitmap::new();
membership.insert(1);
membership.insert(3);
membership.insert(5);
let witness = WitnessHandle::new(1, membership, 3);
let (u, v_minus_u) = witness.materialize_partition();
assert!(u.contains(&1));
assert!(u.contains(&3));
assert!(u.contains(&5));
assert_eq!(u.len(), 3);
assert!(v_minus_u.contains(&0));
assert!(v_minus_u.contains(&2));
assert!(v_minus_u.contains(&4));
}
#[test]
fn test_stub_instance_range_behavior() {
let graph = DynamicGraph::new();
graph.insert_edge(0, 1, 1.0).unwrap();
graph.insert_edge(1, 2, 1.0).unwrap();
let mut instance = StubInstance::new(&graph, 0, 0);
assert!(matches!(instance.query(), InstanceResult::AboveRange));
let mut instance = StubInstance::new(&graph, 0, 1);
match instance.query() {
InstanceResult::ValueInRange { value, .. } => assert_eq!(value, 1),
_ => panic!("Expected ValueInRange"),
}
let mut instance = StubInstance::new(&graph, 0, 10);
match instance.query() {
InstanceResult::ValueInRange { value, .. } => assert_eq!(value, 1),
_ => panic!("Expected ValueInRange"),
}
}
#[test]
fn test_wrapper_time_tracking() {
let graph = Arc::new(DynamicGraph::new());
let mut wrapper = MinCutWrapper::new(graph);
assert_eq!(wrapper.current_time(), 0);
wrapper.insert_edge(0, 1, 2);
assert_eq!(wrapper.current_time(), 1);
wrapper.insert_edge(1, 3, 4);
assert_eq!(wrapper.current_time(), 2);
wrapper.delete_edge(0, 1, 2);
assert_eq!(wrapper.current_time(), 3);
}
#[test]
fn test_certificate_json_roundtrip() {
let cert = CutCertificate::new();
let json = cert.to_json().expect("Failed to serialize certificate");
assert!(json.contains("\"witness_summaries\""));
assert!(json.contains("\"version\""));
assert!(json.contains("\"localkcut_responses\""));
assert!(json.contains("\"timestamp\""));
}
#[test]
fn test_audit_logger_capacity() {
let logger = AuditLogger::new(5);
for i in 0..10 {
logger.log(
AuditEntryType::WitnessCreated,
AuditData::Witness {
hash: i,
boundary: i,
seed: i,
},
);
}
let entries = logger.export();
assert_eq!(entries.len(), 5);
}
#[test]
fn test_audit_logger_filtering() {
let logger = AuditLogger::new(100);
logger.log(
AuditEntryType::WitnessCreated,
AuditData::Witness {
hash: 1,
boundary: 1,
seed: 1,
},
);
logger.log(
AuditEntryType::LocalKCutQuery,
AuditData::Query {
budget: 5,
radius: 10,
seeds: vec![1],
},
);
logger.log(
AuditEntryType::WitnessCreated,
AuditData::Witness {
hash: 2,
boundary: 2,
seed: 2,
},
);
let recent = logger.recent(2);
assert_eq!(recent.len(), 2);
}
#[test]
fn test_full_workflow_path_to_cycle() {
let graph = Arc::new(DynamicGraph::new());
let mut wrapper = MinCutWrapper::new(Arc::clone(&graph));
for i in 0..3 {
let edge_id = graph.insert_edge(i, i + 1, 1.0).unwrap();
wrapper.insert_edge(edge_id, i, i + 1);
}
let result = wrapper.query();
assert_eq!(result.value(), 1);
let edge_id = graph.insert_edge(3, 0, 1.0).unwrap();
wrapper.insert_edge(edge_id, 3, 0);
let result = wrapper.query();
assert_eq!(result.value(), 2); }
#[test]
fn test_full_workflow_split_and_merge() {
let graph = Arc::new(DynamicGraph::new());
let mut wrapper = MinCutWrapper::new(Arc::clone(&graph));
let e1 = graph.insert_edge(0, 1, 1.0).unwrap();
let e2 = graph.insert_edge(1, 2, 1.0).unwrap();
let e3 = graph.insert_edge(2, 0, 1.0).unwrap();
wrapper.insert_edge(e1, 0, 1);
wrapper.insert_edge(e2, 1, 2);
wrapper.insert_edge(e3, 2, 0);
assert_eq!(wrapper.query().value(), 2);
graph.delete_edge(2, 0).unwrap();
wrapper.delete_edge(e3, 2, 0);
assert_eq!(wrapper.query().value(), 1); }
#[test]
fn test_self_loop_ignored() {
let graph = Arc::new(DynamicGraph::new());
let _result = graph.insert_edge(0, 0, 1.0);
}
#[test]
fn test_parallel_edges() {
let graph = Arc::new(DynamicGraph::new());
graph.insert_edge(0, 1, 1.0).unwrap();
let _result = graph.insert_edge(0, 1, 1.0);
}
#[test]
fn test_large_vertex_ids() {
let graph = Arc::new(DynamicGraph::new());
let large_id = 1_000_000u64;
graph.insert_edge(large_id, large_id + 1, 1.0).unwrap();
let mut wrapper = MinCutWrapper::new(Arc::clone(&graph));
wrapper.insert_edge(0, large_id, large_id + 1);
let result = wrapper.query();
assert!(result.is_connected());
}