#[test]
fn test_density_directed() {
let g = Graph::from_edges(&[(0, 1), (1, 2)], true);
assert!((g.density() - 1.0 / 3.0).abs() < 1e-6);
}
#[test]
fn test_diameter_empty() {
let g = Graph::new(false);
assert_eq!(g.diameter(), None);
}
#[test]
fn test_diameter_single_node() {
let g = Graph::from_edges(&[(0, 0)], false);
assert_eq!(g.diameter(), Some(0));
}
#[test]
fn test_diameter_path_graph() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 3)], false);
assert_eq!(g.diameter(), Some(3));
}
#[test]
fn test_diameter_star_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3)], false);
assert_eq!(g.diameter(), Some(2));
}
#[test]
fn test_diameter_disconnected() {
let g = Graph::from_edges(&[(0, 1), (2, 3)], false);
assert_eq!(g.diameter(), None); }
#[test]
fn test_diameter_complete_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)], false);
assert_eq!(g.diameter(), Some(1));
}
#[test]
fn test_clustering_coefficient_empty() {
let g = Graph::new(false);
assert_eq!(g.clustering_coefficient(), 0.0);
}
#[test]
fn test_clustering_coefficient_triangle() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 0)], false);
assert!((g.clustering_coefficient() - 1.0).abs() < 1e-6);
}
#[test]
fn test_clustering_coefficient_star_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3)], false);
assert_eq!(g.clustering_coefficient(), 0.0);
}
#[test]
fn test_clustering_coefficient_partial() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 0), (0, 3)], false);
let cc = g.clustering_coefficient();
assert!(cc > 0.0);
assert!(cc < 1.0);
}
#[test]
fn test_assortativity_empty() {
let g = Graph::new(false);
assert_eq!(g.assortativity(), 0.0);
}
#[test]
fn test_assortativity_star_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3)], false);
assert!(g.assortativity() < 0.0);
}
#[test]
fn test_assortativity_complete_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)], false);
let assort = g.assortativity();
assert_eq!(assort, 0.0);
}
#[test]
fn test_assortativity_path_graph() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 3)], false);
let assort = g.assortativity();
assert!(assort < 0.0);
}
#[test]
fn test_shortest_path_direct_edge() {
let g = Graph::from_edges(&[(0, 1)], false);
let path = g.shortest_path(0, 1).expect("path should exist");
assert_eq!(path, vec![0, 1]);
assert_eq!(path.len(), 2);
}
#[test]
fn test_shortest_path_same_node() {
let g = Graph::from_edges(&[(0, 1), (1, 2)], false);
let path = g.shortest_path(1, 1).expect("path should exist");
assert_eq!(path, vec![1]);
}
#[test]
fn test_shortest_path_disconnected() {
let g = Graph::from_edges(&[(0, 1), (2, 3)], false);
assert!(g.shortest_path(0, 3).is_none());
assert!(g.shortest_path(1, 2).is_none());
}
#[test]
fn test_shortest_path_invalid_nodes() {
let g = Graph::from_edges(&[(0, 1)], false);
assert!(g.shortest_path(0, 10).is_none());
assert!(g.shortest_path(10, 0).is_none());
}
#[test]
fn test_shortest_path_multiple_paths() {
let g = Graph::from_edges(&[(0, 1), (1, 3), (0, 2), (2, 3)], false);
let path = g.shortest_path(0, 3).expect("path should exist");
assert_eq!(path.len(), 3);
assert_eq!(path[0], 0);
assert_eq!(path[2], 3);
assert!(path[1] == 1 || path[1] == 2); }
#[test]
fn test_shortest_path_linear_chain() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 3), (3, 4)], false);
let path = g.shortest_path(0, 4).expect("path should exist");
assert_eq!(path, vec![0, 1, 2, 3, 4]);
let path = g.shortest_path(0, 2).expect("path should exist");
assert_eq!(path, vec![0, 1, 2]);
let path = g.shortest_path(1, 3).expect("path should exist");
assert_eq!(path, vec![1, 2, 3]);
}
#[test]
fn test_shortest_path_triangle() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 0)], false);
let path = g.shortest_path(0, 1).expect("path should exist");
assert_eq!(path.len(), 2);
let path = g.shortest_path(0, 2).expect("path should exist");
assert_eq!(path.len(), 2);
let path = g.shortest_path(1, 2).expect("path should exist");
assert_eq!(path.len(), 2);
}
#[test]
fn test_shortest_path_directed() {
let g = Graph::from_edges(&[(0, 1), (1, 2)], true);
let path = g.shortest_path(0, 2).expect("forward path should exist");
assert_eq!(path, vec![0, 1, 2]);
assert!(g.shortest_path(2, 0).is_none());
}
#[test]
fn test_shortest_path_cycle() {
let g = Graph::from_edges(&[(0, 1), (1, 2), (2, 3), (3, 0)], true);
let path = g.shortest_path(0, 3).expect("path should exist");
assert_eq!(path.len(), 4);
assert_eq!(path, vec![0, 1, 2, 3]);
}
#[test]
fn test_shortest_path_star_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3), (0, 4)], false);
let path = g.shortest_path(0, 1).expect("path should exist");
assert_eq!(path.len(), 2);
let path = g.shortest_path(1, 2).expect("path should exist");
assert_eq!(path.len(), 3);
assert_eq!(path[0], 1);
assert_eq!(path[1], 0); assert_eq!(path[2], 2);
}
#[test]
fn test_shortest_path_empty_graph() {
let g = Graph::new(false);
assert!(g.shortest_path(0, 0).is_none());
}
#[test]
fn test_shortest_path_single_node_graph() {
let g = Graph::from_edges(&[(0, 0)], false);
let path = g.shortest_path(0, 0).expect("path should exist");
assert_eq!(path, vec![0]);
}
#[test]
fn test_shortest_path_complete_graph() {
let g = Graph::from_edges(&[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)], false);
for i in 0..4 {
for j in 0..4 {
if i != j {
let path = g.shortest_path(i, j).expect("path should exist");
assert_eq!(path.len(), 2, "Path from {i} to {j} should be direct");
assert_eq!(path[0], i);
assert_eq!(path[1], j);
}
}
}
}
#[test]
fn test_shortest_path_bidirectional() {
let g = Graph::from_edges(&[(0, 1), (1, 2)], false);
let path_forward = g.shortest_path(0, 2).expect("forward path should exist");
let path_backward = g.shortest_path(2, 0).expect("backward path should exist");
assert_eq!(path_forward.len(), path_backward.len());
assert_eq!(path_forward.len(), 3);
let reversed: Vec<_> = path_backward.iter().rev().copied().collect();
assert_eq!(path_forward, reversed);
}
#[test]
fn test_dijkstra_simple_weighted() {
let g = Graph::from_weighted_edges(&[(0, 1, 1.0), (1, 2, 2.0), (0, 2, 5.0)], false);
let (path, dist) = g.dijkstra(0, 2).expect("path should exist");
assert_eq!(dist, 3.0); assert_eq!(path, vec![0, 1, 2]);
}
#[test]
fn test_dijkstra_same_node() {
let g = Graph::from_weighted_edges(&[(0, 1, 1.0)], false);
let (path, dist) = g.dijkstra(0, 0).expect("path should exist");
assert_eq!(path, vec![0]);
assert_eq!(dist, 0.0);
}
#[test]
fn test_dijkstra_disconnected() {
let g = Graph::from_weighted_edges(&[(0, 1, 1.0), (2, 3, 1.0)], false);
assert!(g.dijkstra(0, 3).is_none());
}
#[test]
fn test_dijkstra_unweighted() {
let g = Graph::from_edges(&[(0, 1), (1, 2)], false);
let (path, dist) = g.dijkstra(0, 2).expect("path should exist");
assert_eq!(dist, 2.0);
assert_eq!(path, vec![0, 1, 2]);
}
#[test]
fn test_dijkstra_triangle_weighted() {
let g = Graph::from_weighted_edges(&[(0, 1, 1.0), (1, 2, 1.0), (0, 2, 5.0)], false);
let (path, dist) = g.dijkstra(0, 2).expect("path should exist");
assert_eq!(dist, 2.0); assert_eq!(path, vec![0, 1, 2]);
}
#[test]
fn test_dijkstra_multiple_paths() {
let g = Graph::from_weighted_edges(
&[
(0, 1, 1.0),
(1, 2, 2.0),
(0, 3, 1.0),
(3, 4, 1.0),
(4, 2, 1.0),
],
false,
);
let (_path, dist) = g.dijkstra(0, 2).expect("path should exist");
assert_eq!(dist, 3.0); }
#[test]
fn test_dijkstra_linear_chain() {
let g = Graph::from_weighted_edges(&[(0, 1, 1.0), (1, 2, 2.0), (2, 3, 3.0)], false);
let (path, dist) = g.dijkstra(0, 3).expect("path should exist");
assert_eq!(dist, 6.0);
assert_eq!(path, vec![0, 1, 2, 3]);
}
#[test]
fn test_dijkstra_directed_graph() {
let g = Graph::from_weighted_edges(&[(0, 1, 1.0), (1, 2, 2.0)], true);
let (path, dist) = g.dijkstra(0, 2).expect("forward path should exist");
assert_eq!(dist, 3.0);
assert_eq!(path, vec![0, 1, 2]);
assert!(g.dijkstra(2, 0).is_none());
}
#[test]
fn test_dijkstra_invalid_nodes() {
let g = Graph::from_weighted_edges(&[(0, 1, 1.0)], false);
assert!(g.dijkstra(0, 10).is_none());
assert!(g.dijkstra(10, 0).is_none());
}
#[test]
#[should_panic(expected = "negative edge weights")]
fn test_dijkstra_negative_weights() {
let g = Graph::from_weighted_edges(&[(0, 1, -1.0)], false);
let _ = g.dijkstra(0, 1);
}
#[test]
fn test_dijkstra_zero_weight_edges() {
let g = Graph::from_weighted_edges(&[(0, 1, 0.0), (1, 2, 1.0)], false);
let (path, dist) = g.dijkstra(0, 2).expect("path should exist");
assert_eq!(dist, 1.0);
assert_eq!(path, vec![0, 1, 2]);
}
#[test]
fn test_dijkstra_complete_graph_weighted() {
let g = Graph::from_weighted_edges(&[(0, 1, 1.0), (1, 2, 1.0), (0, 2, 3.0)], false);
let (path, dist) = g.dijkstra(0, 2).expect("path should exist");
assert_eq!(dist, 2.0);
assert_eq!(path, vec![0, 1, 2]);
}
#[test]
fn test_dijkstra_star_graph_weighted() {
let g = Graph::from_weighted_edges(&[(0, 1, 1.0), (0, 2, 2.0), (0, 3, 3.0)], false);
let (path, dist) = g.dijkstra(1, 3).expect("path should exist");
assert_eq!(dist, 4.0); assert_eq!(path, vec![1, 0, 3]);
}