diff --git a/src/lib.rs b/src/lib.rs index c45198a..c2515f4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -149,4 +149,4 @@ pub mod prelude { }; } -mod testing; +pub mod testing; diff --git a/src/models/append_graph.rs b/src/models/append_graph.rs index ad7de88..84730c3 100644 --- a/src/models/append_graph.rs +++ b/src/models/append_graph.rs @@ -239,12 +239,16 @@ impl GraphTopologyAddition for AppendGraph { } #[cfg(test)] -mod tests { - use super::*; +mod trait_tests { + use super::AppendGraph; - crate::graph_topology_test_fixtures!(AppendGraph); crate::graph_topology_tests!(AppendGraph); crate::graph_topology_addition_tests!(AppendGraph); +} + +#[cfg(test)] +mod tests { + use super::*; #[test] fn incident_vertices_paired_index() { diff --git a/src/models/graph.rs b/src/models/graph.rs index 4ccef26..5eda23a 100644 --- a/src/models/graph.rs +++ b/src/models/graph.rs @@ -378,13 +378,18 @@ impl GraphTopologyDeletion for Graph { } #[cfg(test)] -mod tests { - use super::*; +mod trait_tests { + use super::Graph; - crate::graph_topology_test_fixtures!(Graph); crate::graph_topology_tests!(Graph); crate::graph_topology_addition_tests!(Graph); crate::graph_topology_deletion_tests!(Graph); + crate::graph_topology_addition_deletion_tests!(Graph); +} + +#[cfg(test)] +mod tests { + use super::*; #[test] fn incident_vertices_paired_index() { diff --git a/src/testing.rs b/src/testing.rs index d815794..b92fa0d 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -4,3 +4,6 @@ pub(crate) mod bfs_testing; pub(crate) mod dfs_testing; pub(crate) mod dijkstra_testing; pub(crate) mod graph_topology_testing; + +#[doc(hidden)] +pub mod fixtures; diff --git a/src/testing/bfs_testing.rs b/src/testing/bfs_testing.rs index 63f8fae..2d5bf23 100644 --- a/src/testing/bfs_testing.rs +++ b/src/testing/bfs_testing.rs @@ -4,9 +4,7 @@ macro_rules! bfs_tests { ($T:ty) => { #[test] fn bfs_single_vertex() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); let result = $crate::algorithms::bfs(&graph, v); assert_eq!( result.distances[v], @@ -21,7 +19,8 @@ macro_rules! bfs_tests { #[test] fn bfs_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = + $crate::testing::fixtures::MakeTestGraph::disconnected(); let result = $crate::algorithms::bfs(&graph, vertices[0]); assert_eq!( result.distances[vertices[0]], @@ -46,7 +45,8 @@ macro_rules! bfs_tests { #[test] fn bfs() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = + $crate::testing::fixtures::MakeTestGraph::standard(); let result = $crate::algorithms::bfs(&graph, vertices[0]); assert_bfs_distances(&result.distances, &vertices); assert_bfs_predecessors(&result.predecessors, &vertices); @@ -54,9 +54,7 @@ macro_rules! bfs_tests { #[test] fn bfs_distances_single_vertex() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); let distances = $crate::algorithms::bfs_distances(&graph, v); assert_eq!( distances[v], @@ -67,7 +65,8 @@ macro_rules! bfs_tests { #[test] fn bfs_distances_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = + $crate::testing::fixtures::MakeTestGraph::disconnected(); let distances = $crate::algorithms::bfs_distances(&graph, vertices[0]); assert_eq!( distances[vertices[0]], @@ -84,16 +83,15 @@ macro_rules! bfs_tests { #[test] fn bfs_distances() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = + $crate::testing::fixtures::MakeTestGraph::standard(); let distances = $crate::algorithms::bfs_distances(&graph, vertices[0]); assert_bfs_distances(&distances, &vertices); } #[test] fn bfs_find_source() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); assert_eq!( $crate::algorithms::bfs_find(&graph, v, v), Some(0), @@ -103,7 +101,8 @@ macro_rules! bfs_tests { #[test] fn bfs_find_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = + $crate::testing::fixtures::MakeTestGraph::disconnected(); assert_eq!( $crate::algorithms::bfs_find(&graph, vertices[0], vertices[1]), None, @@ -113,7 +112,8 @@ macro_rules! bfs_tests { #[test] fn bfs_find() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = + $crate::testing::fixtures::MakeTestGraph::standard(); let expected_distances = [ Some(0), Some(1), @@ -139,9 +139,7 @@ macro_rules! bfs_tests { #[test] fn bfs_find_where_source_matches() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); assert_eq!( $crate::algorithms::bfs_find_where(&graph, v, |u| u == v), Some((v, 0)), @@ -151,7 +149,8 @@ macro_rules! bfs_tests { #[test] fn bfs_find_where_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = + $crate::testing::fixtures::MakeTestGraph::disconnected(); assert_eq!( $crate::algorithms::bfs_find_where(&graph, vertices[0], |v| v == vertices[1]), None, @@ -162,7 +161,8 @@ macro_rules! bfs_tests { #[test] fn bfs_find_where_no_match() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = + $crate::testing::fixtures::MakeTestGraph::standard(); assert_eq!( $crate::algorithms::bfs_find_where(&graph, vertices[0], |_| false), None, @@ -172,7 +172,8 @@ macro_rules! bfs_tests { #[test] fn bfs_find_where_nearest() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = + $crate::testing::fixtures::MakeTestGraph::standard(); // vertices[5], vertices[6], vertices[7], vertices[8] are all at distance 3 from vertices[0]. // vertices[9] is at distance 4. Predicate matches vertices[7], vertices[8], vertices[9]. // BFS must return one of the distance-3 ones, not vertices[9]. @@ -193,6 +194,7 @@ macro_rules! bfs_tests { ); } + // TODO: Move out of macro. fn assert_bfs_distances( distances: &$crate::maps::ElementMap< <$T as $crate::traits::GraphTopology>::Vertex, @@ -221,6 +223,7 @@ macro_rules! bfs_tests { } } + // TODO: Move out of macro. fn assert_bfs_predecessors( predecessors: &$crate::maps::ElementMap< <$T as $crate::traits::GraphTopology>::Vertex, diff --git a/src/testing/dfs_testing.rs b/src/testing/dfs_testing.rs index 61f4944..e57ad56 100644 --- a/src/testing/dfs_testing.rs +++ b/src/testing/dfs_testing.rs @@ -4,9 +4,7 @@ macro_rules! dfs_tests { ($T:ty) => { #[test] fn dfs_single_vertex() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); let result = $crate::algorithms::dfs(&graph, v); assert!(result.visited[v], "source vertex should be visited"); assert_eq!( @@ -17,7 +15,7 @@ macro_rules! dfs_tests { #[test] fn dfs_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = $crate::testing::fixtures::MakeTestGraph::disconnected(); let result = $crate::algorithms::dfs(&graph, vertices[0]); assert!( result.visited[vertices[0]], @@ -41,7 +39,7 @@ macro_rules! dfs_tests { #[test] fn dfs() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); let result = $crate::algorithms::dfs(&graph, vertices[0]); assert_dfs_visited(&result.visited, &vertices); assert_dfs_predecessors(&graph, &result.visited, &result.predecessors, &vertices); @@ -49,16 +47,14 @@ macro_rules! dfs_tests { #[test] fn dfs_visited_single_vertex() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); let visited = $crate::algorithms::dfs_visited(&graph, v); assert!(visited[v], "source vertex should be visited"); } #[test] fn dfs_visited_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = $crate::testing::fixtures::MakeTestGraph::disconnected(); let visited = $crate::algorithms::dfs_visited(&graph, vertices[0]); assert!(visited[vertices[0]], "source vertex should be visited"); for &v in &vertices[1..3] { @@ -71,16 +67,14 @@ macro_rules! dfs_tests { #[test] fn dfs_visited() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); let visited = $crate::algorithms::dfs_visited(&graph, vertices[0]); assert_dfs_visited(&visited, &vertices); } #[test] fn dfs_find_source() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); assert!( $crate::algorithms::dfs_find(&graph, v, v), "source should find itself" @@ -89,7 +83,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = $crate::testing::fixtures::MakeTestGraph::disconnected(); assert!( !$crate::algorithms::dfs_find(&graph, vertices[0], vertices[1]), "disconnected target should not be found" @@ -98,7 +92,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); for i in 0..10 { assert!( $crate::algorithms::dfs_find(&graph, vertices[0], vertices[i]), @@ -111,9 +105,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_where_source_matches() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); assert_eq!( $crate::algorithms::dfs_find_where(&graph, v, |u| u == v), Some(v), @@ -123,7 +115,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_where_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = $crate::testing::fixtures::MakeTestGraph::disconnected(); assert_eq!( $crate::algorithms::dfs_find_where(&graph, vertices[0], |v| v == vertices[1]), None, @@ -134,7 +126,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_where_no_match() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); assert_eq!( $crate::algorithms::dfs_find_where(&graph, vertices[0], |_| false), None, @@ -144,7 +136,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_where_adjacent() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); assert_eq!( $crate::algorithms::dfs_find_where(&graph, vertices[0], |v| v == vertices[1]), Some(vertices[1]), @@ -154,7 +146,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_where() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); assert_eq!( $crate::algorithms::dfs_find_where(&graph, vertices[0], |v| v == vertices[9]), Some(vertices[9]), @@ -162,6 +154,7 @@ macro_rules! dfs_tests { ); } + // TODO: Move out of macro. fn assert_dfs_visited( visited: &$crate::maps::ElementMap<<$T as $crate::traits::GraphTopology>::Vertex, bool>, vertices: &[<$T as $crate::traits::GraphTopology>::Vertex], @@ -175,6 +168,7 @@ macro_rules! dfs_tests { } } + // TODO: Move out of macro. fn assert_dfs_predecessors( graph: &$T, visited: &$crate::maps::ElementMap<<$T as $crate::traits::GraphTopology>::Vertex, bool>, @@ -205,9 +199,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_path_source_equals_target() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); assert_eq!( $crate::algorithms::dfs_find_path(&graph, v, v), Some(vec![]), @@ -217,7 +209,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_path_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = $crate::testing::fixtures::MakeTestGraph::disconnected(); assert_eq!( $crate::algorithms::dfs_find_path(&graph, vertices[0], vertices[1]), None, @@ -227,24 +219,16 @@ macro_rules! dfs_tests { #[test] fn dfs_find_path_adjacent() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let e = graph.add_edge(v1, v2); - let path = $crate::algorithms::dfs_find_path(&graph, v1, v2) + let (graph, vertices, e): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::single_edge(); + let path = $crate::algorithms::dfs_find_path(&graph, vertices[0], vertices[1]) .expect("path should exist between adjacent vertices"); - assert_eq!( - path.len(), - 1, - "unexpected path length between adjacent vertices" - ); + assert_eq!(path.len(), 1, "unexpected path length between adjacent vertices"); assert_eq!(path[0], e, "path should use the connecting edge"); } #[test] fn dfs_find_path() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); let path = $crate::algorithms::dfs_find_path(&graph, vertices[0], vertices[9]) .expect(&format!( "path should exist between connected vertices {:?} and {:?}", @@ -255,9 +239,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_path_where_source_matches() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); assert_eq!( $crate::algorithms::dfs_find_path_where(&graph, v, |u| u == v), Some(vec![]), @@ -267,7 +249,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_path_where_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = $crate::testing::fixtures::MakeTestGraph::disconnected(); assert_eq!( $crate::algorithms::dfs_find_path_where(&graph, vertices[0], |v| v == vertices[1]), None, @@ -277,7 +259,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_path_where_no_match() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); assert_eq!( $crate::algorithms::dfs_find_path_where(&graph, vertices[0], |_| false), None, @@ -287,7 +269,7 @@ macro_rules! dfs_tests { #[test] fn dfs_find_path_where() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); let path = $crate::algorithms::dfs_find_path_where(&graph, vertices[0], |v| v == vertices[9]) .expect(&format!( @@ -297,6 +279,7 @@ macro_rules! dfs_tests { assert_valid_path(&graph, &path, vertices[0], vertices[9]); } + // TODO: Move out of macro. fn assert_valid_path( graph: &$T, path: &[<$T as $crate::traits::GraphTopology>::Edge], diff --git a/src/testing/dijkstra_testing.rs b/src/testing/dijkstra_testing.rs index d015ca6..fc3d333 100644 --- a/src/testing/dijkstra_testing.rs +++ b/src/testing/dijkstra_testing.rs @@ -4,9 +4,7 @@ macro_rules! dijkstra_tests { ($T:ty) => { #[test] fn dijkstra_single_vertex() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); let result = $crate::algorithms::dijkstra(&graph, v, |_| { panic!("unexpected call of weight functor") }); @@ -15,7 +13,8 @@ macro_rules! dijkstra_tests { #[test] fn dijkstra_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = + $crate::testing::fixtures::MakeTestGraph::disconnected(); let result = $crate::algorithms::dijkstra(&graph, vertices[0], |_| { panic!("unexpected call of weight functor") }); @@ -25,17 +24,7 @@ macro_rules! dijkstra_tests { #[test] fn dijkstra_zero_weight_loop() { - use $crate::traits::{GraphTopology, GraphTopologyAddition}; - let mut graph = <$T>::new(); - let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 3] = - core::array::from_fn(|_| graph.add_vertex()); - let e1 = graph.add_edge(vertices[0], vertices[0]); - let e2 = graph.add_edge(vertices[1], vertices[1]); - graph.add_edge(vertices[0], vertices[1]); - graph.add_edge(vertices[1], vertices[2]); - let mut weights = graph.edge_map(1); - weights[e1] = 0; - weights[e2] = 0; + let (graph, vertices, _, weights) = make_two_edge_path_with_zero_weight_loops(); let result = $crate::algorithms::dijkstra(&graph, vertices[0], |e| weights[e]); assert_single_vertex(&result, vertices[0]); for i in 1..3 { @@ -71,16 +60,15 @@ macro_rules! dijkstra_tests { #[test] fn dijkstra_unweighted_single_vertex() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); let result = $crate::algorithms::dijkstra_unweighted(&graph, v); assert_single_vertex(&result, v) } #[test] fn dijkstra_unweighted_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = + $crate::testing::fixtures::MakeTestGraph::disconnected(); let result = $crate::algorithms::dijkstra_unweighted(&graph, vertices[0]); assert_single_vertex(&result, vertices[0]); assert_disconnected(&result, &vertices[1..3]); @@ -88,23 +76,23 @@ macro_rules! dijkstra_tests { #[test] fn dijkstra_unweighted() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = + $crate::testing::fixtures::MakeTestGraph::standard(); let result = $crate::algorithms::dijkstra_unweighted(&graph, vertices[0]); assert_unweighted_test_graph(&result, &vertices); } #[test] fn dijkstra_distances_unweighted_single_vertex() { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); let distances = $crate::algorithms::dijkstra_distances_unweighted(&graph, v); assert_distances_single_vertex(&distances, v); } #[test] fn dijkstra_distances_unweighted_disconnected() { - let (graph, vertices) = make_test_graph_disconnected(); + let (graph, vertices): ($T, _) = + $crate::testing::fixtures::MakeTestGraph::disconnected(); let distances = $crate::algorithms::dijkstra_distances_unweighted(&graph, vertices[0]); assert_distances_single_vertex(&distances, vertices[0]); assert_distances_disconnected(&distances, &vertices[1..3]); @@ -112,11 +100,13 @@ macro_rules! dijkstra_tests { #[test] fn dijkstra_distances_unweighted() { - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = + $crate::testing::fixtures::MakeTestGraph::standard(); let distances = $crate::algorithms::dijkstra_distances_unweighted(&graph, vertices[0]); assert_distances_unweighted_test_graph(&distances, &vertices); } + // TODO: Move out of macro. fn assert_single_vertex( result: &$crate::algorithms::DijkstraResult< <$T as $crate::traits::GraphTopology>::Vertex, @@ -130,6 +120,7 @@ macro_rules! dijkstra_tests { ); } + // TODO: Move out of macro. fn assert_distances_single_vertex( distances: &$crate::maps::ElementMap< <$T as $crate::traits::GraphTopology>::Vertex, @@ -144,6 +135,7 @@ macro_rules! dijkstra_tests { ); } + // TODO: Move out of macro. fn assert_disconnected( result: &$crate::algorithms::DijkstraResult< <$T as $crate::traits::GraphTopology>::Vertex, @@ -159,6 +151,7 @@ macro_rules! dijkstra_tests { } } + // TODO: Move out of macro. fn assert_distances_disconnected( distances: &$crate::maps::ElementMap< <$T as $crate::traits::GraphTopology>::Vertex, @@ -174,6 +167,7 @@ macro_rules! dijkstra_tests { } } + // TODO: Move out of macro. fn assert_test_graph( result: &$crate::algorithms::DijkstraResult< <$T as $crate::traits::GraphTopology>::Vertex, @@ -203,6 +197,7 @@ macro_rules! dijkstra_tests { } } + // TODO: Move out of macro. fn assert_distances_test_graph( distances: &$crate::maps::ElementMap< <$T as $crate::traits::GraphTopology>::Vertex, @@ -231,6 +226,7 @@ macro_rules! dijkstra_tests { } } + // TODO: Move out of macro. fn assert_unweighted_test_graph( result: &$crate::algorithms::DijkstraResult< <$T as $crate::traits::GraphTopology>::Vertex, @@ -260,6 +256,7 @@ macro_rules! dijkstra_tests { } } + // TODO: Move out of macro. fn assert_distances_unweighted_test_graph( distances: &$crate::maps::ElementMap< <$T as $crate::traits::GraphTopology>::Vertex, @@ -288,6 +285,7 @@ macro_rules! dijkstra_tests { } } + // TODO: Move out of macro. fn make_test_graph_weighted() -> ( $T, [<$T as $crate::traits::GraphTopology>::Vertex; 10], @@ -305,12 +303,29 @@ macro_rules! dijkstra_tests { $crate::maps::ElementMap<<$T as $crate::traits::GraphTopology>::Edge, u32>, ) { use $crate::traits::GraphTopology; - let (graph, vertices, edges, incidences) = make_test_graph(); - let mut weights = graph.edge_map(99_u32); + let (graph, vertices, edges, incidences): ($T, _, _, _) = + $crate::testing::fixtures::MakeTestGraph::standard(); + let mut weights = graph.edge_map(99); for i in [1, 3, 7, 10, 12, 14, 15, 17] { weights[edges[i].0] = i.try_into().unwrap(); } (graph, vertices, edges, incidences, weights) } + + // TODO: Move out of macro. + fn make_two_edge_path_with_zero_weight_loops() -> ( + $T, + [<$T as $crate::traits::GraphTopology>::Vertex; 3], + [<$T as $crate::traits::GraphTopology>::Edge; 4], + $crate::maps::ElementMap<<$T as $crate::traits::GraphTopology>::Edge, u32>, + ) { + use $crate::traits::GraphTopology; + let (graph, vertices, edges): ($T, _, _) = + $crate::testing::fixtures::MakeTestGraph::two_edge_path_with_loops(); + let mut weights = graph.edge_map(1); + weights[edges[2]] = 0; + weights[edges[3]] = 0; + (graph, vertices, edges, weights) + } }; } diff --git a/src/testing/fixtures.rs b/src/testing/fixtures.rs new file mode 100644 index 0000000..d4c2109 --- /dev/null +++ b/src/testing/fixtures.rs @@ -0,0 +1,164 @@ +use crate::traits::{GraphTopology, GraphTopologyAddition, Incidence}; + +pub trait MakeTestGraph: GraphTopology + Sized { + fn standard() -> ( + Self, + [Self::Vertex; 10], + [(Self::Edge, Self::Vertex, Self::Vertex); 18], + [Vec>; 10], + ); + + fn empty() -> Self; + + fn single_vertex() -> (Self, Self::Vertex); + + fn single_edge() -> (Self, [Self::Vertex; 2], Self::Edge); + + fn disconnected() -> (Self, [Self::Vertex; 3]); + + fn loop_edge() -> (Self, Self::Vertex, Self::Edge); + + fn multiple_edges() -> (Self, [Self::Vertex; 2], [Self::Edge; K]); + + fn two_edge_path() -> (Self, [Self::Vertex; 3], [Self::Edge; 2]); + + fn two_edge_path_with_loops() -> (Self, [Self::Vertex; 3], [Self::Edge; 4]); +} + +impl MakeTestGraph for G { + fn standard() -> ( + Self, + [Self::Vertex; 10], + [(Self::Edge, Self::Vertex, Self::Vertex); 18], + [Vec>; 10], + ) { + let mut graph = Self::default(); + let vertices = core::array::from_fn(|_| graph.add_vertex()); + let edges = [ + (vertices[0], vertices[1]), + (vertices[0], vertices[1]), + (vertices[1], vertices[2]), + (vertices[1], vertices[3]), + (vertices[1], vertices[4]), + (vertices[2], vertices[2]), + (vertices[2], vertices[4]), + (vertices[2], vertices[4]), + (vertices[2], vertices[5]), + (vertices[2], vertices[6]), + (vertices[3], vertices[6]), + (vertices[4], vertices[4]), + (vertices[4], vertices[7]), + (vertices[4], vertices[8]), + (vertices[5], vertices[9]), + (vertices[6], vertices[9]), + (vertices[7], vertices[8]), + (vertices[7], vertices[9]), + ] + .map(|(v1, v2)| (graph.add_edge(v1, v2), v1, v2)); + let i = |vertex, edge| Incidence { vertex, edge }; + let incidences = [ + vec![i(vertices[1], edges[0].0), i(vertices[1], edges[1].0)], + vec![ + i(vertices[0], edges[0].0), + i(vertices[0], edges[1].0), + i(vertices[2], edges[2].0), + i(vertices[3], edges[3].0), + i(vertices[4], edges[4].0), + ], + vec![ + i(vertices[2], edges[5].0), + i(vertices[2], edges[5].0), + i(vertices[1], edges[2].0), + i(vertices[4], edges[6].0), + i(vertices[4], edges[7].0), + i(vertices[5], edges[8].0), + i(vertices[6], edges[9].0), + ], + vec![i(vertices[1], edges[3].0), i(vertices[6], edges[10].0)], + vec![ + i(vertices[1], edges[4].0), + i(vertices[2], edges[6].0), + i(vertices[2], edges[7].0), + i(vertices[4], edges[11].0), + i(vertices[4], edges[11].0), + i(vertices[7], edges[12].0), + i(vertices[8], edges[13].0), + ], + vec![i(vertices[2], edges[8].0), i(vertices[9], edges[14].0)], + vec![ + i(vertices[2], edges[9].0), + i(vertices[3], edges[10].0), + i(vertices[9], edges[15].0), + ], + vec![ + i(vertices[4], edges[12].0), + i(vertices[8], edges[16].0), + i(vertices[9], edges[17].0), + ], + vec![i(vertices[4], edges[13].0), i(vertices[7], edges[16].0)], + vec![ + i(vertices[5], edges[14].0), + i(vertices[6], edges[15].0), + i(vertices[7], edges[17].0), + ], + ]; + (graph, vertices, edges, incidences) + } + + fn empty() -> Self { + Self::default() + } + + fn single_vertex() -> (Self, Self::Vertex) { + let mut graph = Self::default(); + let v = graph.add_vertex(); + (graph, v) + } + + fn single_edge() -> (Self, [Self::Vertex; 2], Self::Edge) { + let mut graph = Self::default(); + let vertices = core::array::from_fn(|_| graph.add_vertex()); + let e = graph.add_edge(vertices[0], vertices[1]); + (graph, vertices, e) + } + + fn disconnected() -> (Self, [Self::Vertex; 3]) { + let mut graph = Self::default(); + let vertices = core::array::from_fn(|_| graph.add_vertex()); + graph.add_edge(vertices[1], vertices[2]); + (graph, vertices) + } + + fn loop_edge() -> (Self, Self::Vertex, Self::Edge) { + let mut graph = Self::default(); + let v = graph.add_vertex(); + let e = graph.add_edge(v, v); + (graph, v, e) + } + + fn multiple_edges() -> (Self, [Self::Vertex; 2], [Self::Edge; K]) { + let mut graph = Self::default(); + let vertices = core::array::from_fn(|_| graph.add_vertex()); + let edges = core::array::from_fn(|_| graph.add_edge(vertices[0], vertices[1])); + (graph, vertices, edges) + } + + fn two_edge_path() -> (Self, [Self::Vertex; 3], [Self::Edge; 2]) { + let mut graph = Self::default(); + let vertices = core::array::from_fn(|_| graph.add_vertex()); + let edges = core::array::from_fn(|i| graph.add_edge(vertices[i], vertices[i + 1])); + (graph, vertices, edges) + } + + fn two_edge_path_with_loops() -> (Self, [Self::Vertex; 3], [Self::Edge; 4]) { + let mut graph = Self::default(); + let vertices = core::array::from_fn(|_| graph.add_vertex()); + // Path edges. + let e0 = graph.add_edge(vertices[0], vertices[1]); + let e1 = graph.add_edge(vertices[1], vertices[2]); + // Loops. + let e2 = graph.add_edge(vertices[0], vertices[0]); + let e3 = graph.add_edge(vertices[1], vertices[1]); + (graph, vertices, [e0, e1, e2, e3]) + } +} diff --git a/src/testing/graph_topology_testing.rs b/src/testing/graph_topology_testing.rs index 07e9793..dd414b7 100644 --- a/src/testing/graph_topology_testing.rs +++ b/src/testing/graph_topology_testing.rs @@ -1,111 +1,3 @@ -#[doc(hidden)] -#[macro_export] -macro_rules! graph_topology_test_fixtures { - ($T:ty) => { - fn make_test_graph() -> ( - $T, - [<$T as $crate::traits::GraphTopology>::Vertex; 10], - [( - <$T as $crate::traits::GraphTopology>::Edge, - <$T as $crate::traits::GraphTopology>::Vertex, - <$T as $crate::traits::GraphTopology>::Vertex, - ); 18], - [Vec<$crate::traits::Incidence< - <$T as $crate::traits::GraphTopology>::Vertex, - <$T as $crate::traits::GraphTopology>::Edge, - >>; 10], - ) { - use $crate::traits::{GraphTopology, GraphTopologyAddition, Incidence}; - let mut graph = <$T>::new(); - let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 10] = - core::array::from_fn(|_| graph.add_vertex()); - let edges = [ - (vertices[0], vertices[1]), - (vertices[0], vertices[1]), - (vertices[1], vertices[2]), - (vertices[1], vertices[3]), - (vertices[1], vertices[4]), - (vertices[2], vertices[2]), - (vertices[2], vertices[4]), - (vertices[2], vertices[4]), - (vertices[2], vertices[5]), - (vertices[2], vertices[6]), - (vertices[3], vertices[6]), - (vertices[4], vertices[4]), - (vertices[4], vertices[7]), - (vertices[4], vertices[8]), - (vertices[5], vertices[9]), - (vertices[6], vertices[9]), - (vertices[7], vertices[8]), - (vertices[7], vertices[9]), - ] - .map(|(v1, v2)| (graph.add_edge(v1, v2), v1, v2)); - let i = |vertex, edge| Incidence { vertex, edge }; - let incidences: [Vec::Vertex, - <$T as GraphTopology>::Edge, - >>; 10] = [ - vec![i(vertices[1], edges[0].0), i(vertices[1], edges[1].0)], - vec![ - i(vertices[0], edges[0].0), - i(vertices[0], edges[1].0), - i(vertices[2], edges[2].0), - i(vertices[3], edges[3].0), - i(vertices[4], edges[4].0), - ], - vec![ - i(vertices[2], edges[5].0), - i(vertices[2], edges[5].0), - i(vertices[1], edges[2].0), - i(vertices[4], edges[6].0), - i(vertices[4], edges[7].0), - i(vertices[5], edges[8].0), - i(vertices[6], edges[9].0), - ], - vec![i(vertices[1], edges[3].0), i(vertices[6], edges[10].0)], - vec![ - i(vertices[1], edges[4].0), - i(vertices[2], edges[6].0), - i(vertices[2], edges[7].0), - i(vertices[4], edges[11].0), - i(vertices[4], edges[11].0), - i(vertices[7], edges[12].0), - i(vertices[8], edges[13].0), - ], - vec![i(vertices[2], edges[8].0), i(vertices[9], edges[14].0)], - vec![ - i(vertices[2], edges[9].0), - i(vertices[3], edges[10].0), - i(vertices[9], edges[15].0), - ], - vec![ - i(vertices[4], edges[12].0), - i(vertices[8], edges[16].0), - i(vertices[9], edges[17].0), - ], - vec![i(vertices[4], edges[13].0), i(vertices[7], edges[16].0)], - vec![ - i(vertices[5], edges[14].0), - i(vertices[6], edges[15].0), - i(vertices[7], edges[17].0), - ], - ]; - (graph, vertices, edges, incidences) - } - - #[allow(dead_code)] - fn make_test_graph_disconnected() - -> ($T, [<$T as $crate::traits::GraphTopology>::Vertex; 3]) { - use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); - let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 3] = - core::array::from_fn(|_| graph.add_vertex()); - graph.add_edge(vertices[1], vertices[2]); - (graph, vertices) - } - }; -} - #[doc(hidden)] #[macro_export] macro_rules! graph_topology_tests { @@ -113,71 +5,62 @@ macro_rules! graph_topology_tests { #[test] fn vertex_count_empty() { use $crate::traits::GraphTopology; - let graph = <$T>::new(); + let graph: $T = $crate::testing::fixtures::MakeTestGraph::empty(); assert_eq!(graph.vertex_count(), 0, "unexpected vertex count"); } #[test] fn vertex_count() { use $crate::traits::GraphTopology; - let (graph, _, _, _) = make_test_graph(); + let (graph, _, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); assert_eq!(graph.vertex_count(), 10, "unexpected vertex count"); } #[test] fn vertex_map() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v1 = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); let mut map = graph.vertex_map(27); - assert_eq!(map[v1], 27, "unexpected value from default map read"); - map[v1] = 9; - assert_eq!(map[v1], 9, "unexpected value from map after write"); - let v2 = graph.add_vertex(); - assert_eq!(map[v2], 27, "unexpected value from default map read for new vertex"); + assert_eq!(map[v], 27, "unexpected value from default map read"); + map[v] = 9; + assert_eq!(map[v], 9, "unexpected value from map after write"); } #[test] fn edge_count_empty() { use $crate::traits::GraphTopology; - let graph = <$T>::new(); + let graph: $T = $crate::testing::fixtures::MakeTestGraph::empty(); assert_eq!(graph.edge_count(), 0, "unexpected edge count"); } #[test] fn edge_count() { use $crate::traits::GraphTopology; - let (graph, _, _, _) = make_test_graph(); + let (graph, _, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); assert_eq!(graph.edge_count(), 18, "unexpected edge count"); } #[test] fn edge_map() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let e1 = graph.add_edge(v1, v2); - let mut map = graph.edge_map(27); - assert_eq!(map[e1], 27, "unexpected value from default map read"); - map[e1] = 9; - assert_eq!(map[e1], 9, "unexpected value from map after write"); - let e2 = graph.add_edge(v1, v2); - assert_eq!(map[e2], 27, "unexpected value from default map read for new vertex"); + let (graph, _, e): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::single_edge(); + let mut map = graph.edge_map(28); + assert_eq!(map[e], 28, "unexpected value from default map read"); + map[e] = 8; + assert_eq!(map[e], 8, "unexpected value from map after write"); } #[test] fn degree_zero() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); assert_eq!(graph.degree(v), 0, "unexpected non-zero degree"); } #[test] fn degree() { use $crate::traits::GraphTopology; - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); let expected_degrees = [2, 5, 7, 2, 7, 2, 3, 3, 2, 3]; for i in 0..graph.vertex_count() { assert_eq!( @@ -192,9 +75,7 @@ macro_rules! graph_topology_tests { #[test] fn loop_edge() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); - graph.add_edge(v, v); + let (graph, v, _): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::loop_edge(); assert_eq!(graph.vertex_count(), 1, "unexpected vertex count"); assert_eq!(graph.edge_count(), 1, "unexpected edge count"); assert_eq!(graph.degree(v), 2, "unexpected degree"); @@ -207,48 +88,34 @@ macro_rules! graph_topology_tests { #[test] fn multiple_edges() { use $crate::traits::GraphTopology; - let k = 3; - let mut graph = <$T>::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - for _ in 0..k { - graph.add_edge(v1, v2); - } + const K: usize = 3; + let (graph, vertices, _): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::multiple_edges::(); assert_eq!(graph.vertex_count(), 2, "unexpected vertex count"); - assert_eq!(graph.edge_count(), k, "unexpected edge count"); - assert_eq!(graph.degree(v1), k, "unexpected degree of vertex {v1:?}"); - assert_eq!(graph.degree(v2), k, "unexpected degree of vertex {v2:?}"); - assert!(graph.are_adjacent(v1, v2), "should be adjacent"); + assert_eq!(graph.edge_count(), K, "unexpected edge count"); + assert_eq!(graph.degree(vertices[0]), K, "unexpected degree of vertex {:?}", vertices[0]); + assert_eq!(graph.degree(vertices[1]), K, "unexpected degree of vertex {:?}", vertices[1]); + assert!(graph.are_adjacent(vertices[0], vertices[1]), "should be adjacent"); } #[test] fn are_adjacent_vertex_self() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); - assert!( - !graph.are_adjacent(v, v), - "should not be adjacent to itself" - ); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); + assert!(!graph.are_adjacent(v, v), "should not be adjacent to itself"); } #[test] fn are_adjacent_single_edge() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - assert!(!graph.are_adjacent(v1, v2), "should not be adjacent"); - assert!(!graph.are_adjacent(v2, v1), "should not be adjacent"); - graph.add_edge(v1, v2); - assert!(graph.are_adjacent(v1, v2), "should be adjacent"); - assert!(graph.are_adjacent(v2, v1), "should be adjacent"); + let (graph, vertices, _): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::single_edge(); + assert!(graph.are_adjacent(vertices[0], vertices[1]), "should be adjacent"); + assert!(graph.are_adjacent(vertices[1], vertices[0]), "should be adjacent"); } #[test] fn are_adjacent() { use $crate::traits::GraphTopology; - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); assert!( graph.are_adjacent(vertices[0], vertices[1]), "expected {:?} and {:?} to be adjacent", @@ -293,7 +160,7 @@ macro_rules! graph_topology_tests { #[test] fn vertices_empty() { use $crate::traits::GraphTopology; - let graph = <$T>::new(); + let graph: $T = $crate::testing::fixtures::MakeTestGraph::empty(); assert_eq!( graph.vertices().count(), 0, @@ -304,7 +171,7 @@ macro_rules! graph_topology_tests { #[test] fn vertices() { use $crate::traits::GraphTopology; - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); assert_eq!(graph.vertices().count(), 10, "unexpected vertex count"); // Expects each vertex to appear exactly once. @@ -320,8 +187,7 @@ macro_rules! graph_topology_tests { #[test] fn adjacent_vertices_empty() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); assert_eq!( graph.adjacent_vertices(v).count(), 0, @@ -332,7 +198,7 @@ macro_rules! graph_topology_tests { #[test] fn adjacent_vertices() { use $crate::traits::GraphTopology; - let (graph, vertices, _, _) = make_test_graph(); + let (graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); // Checks adjacency of vertex 4. assert_eq!( graph.adjacent_vertices(vertices[4]).count(), @@ -370,35 +236,21 @@ macro_rules! graph_topology_tests { #[test] fn adjacent_vertices_loop_edge() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); - graph.add_edge(v, v); + let (graph, v, _): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::loop_edge(); let mut iter = graph.adjacent_vertices(v); assert_eq!(iter.next(), Some(v), "vertex should be adjacent to itself"); - assert_eq!( - iter.next(), - Some(v), - "vertex should be adjacent to itself twice" - ); - assert_eq!( - iter.next(), - None, - "too many adjacent vertices from iterator" - ); + assert_eq!(iter.next(), Some(v), "vertex should be adjacent to itself twice"); + assert_eq!(iter.next(), None, "too many adjacent vertices from iterator"); } #[test] fn adjacent_vertices_multiple_edges() { use $crate::traits::GraphTopology; - let k = 3; - let mut graph = <$T>::new(); - let vertices = [graph.add_vertex(), graph.add_vertex()]; - for _ in 0..k { - graph.add_edge(vertices[0], vertices[1]); - } + const K: usize = 3; + let (graph, vertices, _): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::multiple_edges::(); for i in 0..2 { let mut iter = graph.adjacent_vertices(vertices[i]); - for j in 0..k { + for j in 0..K { assert_eq!( iter.next(), Some(vertices[1 - i]), @@ -418,23 +270,18 @@ macro_rules! graph_topology_tests { #[test] fn incident_vertices_single_edge() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let e = graph.add_edge(v1, v2); - let (u1, u2) = graph.incident_vertices(e); + let (graph, vertices, e): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::single_edge(); + let (u, v) = graph.incident_vertices(e); assert!( - (u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1), - "unexpected incident vertices {u1:?} and {u2:?} for edge {e:?}" + (u == vertices[0] && v == vertices[1]) || (u == vertices[1] && v == vertices[0]), + "unexpected incident vertices {u:?} and {v:?} for edge {e:?}" ); } #[test] fn incident_vertices_loop_edge() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); - let e = graph.add_edge(v, v); + let (graph, v, e): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::loop_edge(); assert_eq!( graph.incident_vertices(e), (v, v), @@ -445,28 +292,26 @@ macro_rules! graph_topology_tests { #[test] fn incident_vertices_multiple_edges() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let e1 = graph.add_edge(v1, v2); - let e2 = graph.add_edge(v1, v2); - assert_ne!(e1, e2, "edges should be distinct"); - let (u1, u2) = graph.incident_vertices(e1); + let (graph, vertices, edges): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::multiple_edges::<2>(); + assert_ne!(edges[0], edges[1], "edges should be distinct"); + let (u, v) = graph.incident_vertices(edges[0]); assert!( - (u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1), - "unexpected incident vertices {u1:?} and {u2:?} for first multi-edge {e1:?}" + (u == vertices[0] && v == vertices[1]) || (u == vertices[1] && v == vertices[0]), + "unexpected incident vertices {u:?} and {v:?} for first multi-edge {:?}", + edges[0] ); - let (u1, u2) = graph.incident_vertices(e2); + let (u, v) = graph.incident_vertices(edges[1]); assert!( - (u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1), - "unexpected incident vertices {u1:?} and {u2:?} for second multi-edge {e2:?}" + (u == vertices[0] && v == vertices[1]) || (u == vertices[1] && v == vertices[0]), + "unexpected incident vertices {u:?} and {v:?} for second multi-edge {:?}", + edges[1] ); } #[test] fn incident_vertices() { use $crate::traits::GraphTopology; - let (graph, _, edges, _) = make_test_graph(); + let (graph, _, edges, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); for &(e, v1, v2) in edges.iter() { let (u1, u2) = graph.incident_vertices(e); assert!( @@ -479,7 +324,7 @@ macro_rules! graph_topology_tests { #[test] fn edges_empty() { use $crate::traits::GraphTopology; - let graph = <$T>::new(); + let graph: $T = $crate::testing::fixtures::MakeTestGraph::empty(); assert_eq!( graph.edges().count(), 0, @@ -490,7 +335,7 @@ macro_rules! graph_topology_tests { #[test] fn edges() { use $crate::traits::GraphTopology; - let (graph, _, edges, _) = make_test_graph(); + let (graph, _, edges, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); assert_eq!(graph.edges().count(), 18, "unexpected edge count"); // Expects each edge to appear exactly once. @@ -506,8 +351,7 @@ macro_rules! graph_topology_tests { #[test] fn incident_edges_empty() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); assert_eq!( graph.incident_edges(v).count(), 0, @@ -518,7 +362,7 @@ macro_rules! graph_topology_tests { #[test] fn incident_edges() { use $crate::traits::GraphTopology; - let (graph, vertices, _, incidences) = make_test_graph(); + let (graph, vertices, _, incidences): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); for i in 0..10 { assert_eq!( graph.incident_edges(vertices[i]).count(), @@ -549,31 +393,20 @@ macro_rules! graph_topology_tests { #[test] fn incident_edges_loop_edge() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); - let e = graph.add_edge(v, v); + let (graph, v, e): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::loop_edge(); let mut iter = graph.incident_edges(v); assert_eq!(iter.next(), Some(e), "loop edge should appear in incident edges"); - assert_eq!( - iter.next(), - Some(e), - "loop edge should appear twice in incident edges" - ); + assert_eq!(iter.next(), Some(e), "loop edge should appear twice in incident edges"); assert_eq!(iter.next(), None, "too many incident edges from iterator"); } #[test] fn incident_edges_multiple_edges() { use $crate::traits::GraphTopology; - let k = 3; - let mut graph = <$T>::new(); - let vertices = [graph.add_vertex(), graph.add_vertex()]; - let mut edges = Vec::new(); - for _ in 0..k { - edges.push(graph.add_edge(vertices[0], vertices[1])); - } + const K: usize = 3; + let (graph, vertices, edges): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::multiple_edges::(); for i in 0..2 { - let mut expected = edges.clone(); + let mut expected = edges.to_vec(); for e in graph.incident_edges(vertices[i]) { let pos = expected .iter() @@ -596,8 +429,7 @@ macro_rules! graph_topology_tests { #[test] fn incidences_empty() { use $crate::traits::GraphTopology; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); assert_eq!( graph.incidences(v).count(), 0, @@ -608,7 +440,7 @@ macro_rules! graph_topology_tests { #[test] fn incidences() { use $crate::traits::GraphTopology; - let (graph, vertices, _, incidences) = make_test_graph(); + let (graph, vertices, _, incidences): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); for i in 0..10 { assert_eq!( graph.incidences(vertices[i]).count(), @@ -641,7 +473,7 @@ macro_rules! graph_topology_tests { use $crate::traits::GraphTopology; // For each incidence (v, e) of u, the same edge e must appear in the incidences of v. // For loop edges (u == v), the edge must appear exactly twice in the incidences of u. - let (graph, _, _, _) = make_test_graph(); + let (graph, _, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); for u in graph.vertices() { for incidence in graph.incidences(u) { if u == incidence.vertex { @@ -667,9 +499,7 @@ macro_rules! graph_topology_tests { #[test] fn incidences_loop_edge() { use $crate::traits::{GraphTopology, Incidence}; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); - let e = graph.add_edge(v, v); + let (graph, v, e): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::loop_edge(); let mut iter = graph.incidences(v); assert_eq!( iter.next(), @@ -681,28 +511,19 @@ macro_rules! graph_topology_tests { Some(Incidence { vertex: v, edge: e }), "vertex should be adjacent to itself twice" ); - assert_eq!( - iter.next(), - None, - "too many adjacent vertices from iterator" - ); + assert_eq!(iter.next(), None, "too many adjacent vertices from iterator"); } #[test] fn incidences_multiple_edges() { use $crate::traits::GraphTopology; - let k = 3; - let mut graph = <$T>::new(); - let vertices = [graph.add_vertex(), graph.add_vertex()]; - let mut edges = Vec::new(); - for _ in 0..k { - edges.push(graph.add_edge(vertices[0], vertices[1])); - } + const K: usize = 3; + let (graph, vertices, edges): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::multiple_edges::(); for i in 0..2 { let mut iter = graph.incidences(vertices[i]); - for j in 0..k { + for j in 0..K { let current = iter.next().expect(&format!( - "incidence {j} missing, expected {k} incidences for vertex {:?}", + "incidence {j} missing, expected {K} incidences for vertex {:?}", vertices[i] )); assert_eq!( @@ -731,8 +552,7 @@ macro_rules! graph_topology_tests { #[test] fn incidence_cursor_empty() { use $crate::traits::{GraphTopology, IncidenceCursor}; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); + let (graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); let mut cursor = graph.incidence_cursor(v); assert_eq!( cursor.next(&graph), @@ -744,7 +564,7 @@ macro_rules! graph_topology_tests { #[test] fn incidence_cursor() { use $crate::traits::{GraphTopology, IncidenceCursor}; - let (graph, vertices, _, incidences) = make_test_graph(); + let (graph, vertices, _, incidences): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); for i in 0..10 { let mut expected = incidences[i].clone(); let mut cursor = graph.incidence_cursor(vertices[i]); @@ -770,9 +590,7 @@ macro_rules! graph_topology_tests { #[test] fn incidence_cursor_loop_edge() { use $crate::traits::{GraphTopology, Incidence, IncidenceCursor}; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); - let e = graph.add_edge(v, v); + let (graph, v, e): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::loop_edge(); let mut cursor = graph.incidence_cursor(v); assert_eq!( cursor.next(&graph), @@ -784,28 +602,19 @@ macro_rules! graph_topology_tests { Some(Incidence { vertex: v, edge: e }), "vertex should be adjacent to itself twice" ); - assert_eq!( - cursor.next(&graph), - None, - "too many incidences from cursor" - ); + assert_eq!(cursor.next(&graph), None, "too many incidences from cursor"); } #[test] fn incidence_cursor_multiple_edges() { use $crate::traits::{GraphTopology, IncidenceCursor}; - let k = 3; - let mut graph = <$T>::new(); - let vertices = [graph.add_vertex(), graph.add_vertex()]; - let mut edges = Vec::new(); - for _ in 0..k { - edges.push(graph.add_edge(vertices[0], vertices[1])); - } + const K: usize = 3; + let (graph, vertices, edges): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::multiple_edges::(); for i in 0..2 { let mut cursor = graph.incidence_cursor(vertices[i]); - for j in 0..k { + for j in 0..K { let current = cursor.next(&graph).expect(&format!( - "incidence {j} missing, expected {k} incidences for vertex {:?}", + "incidence {j} missing, expected {K} incidences for vertex {:?}", vertices[i] )); assert_eq!( @@ -834,13 +643,9 @@ macro_rules! graph_topology_tests { #[test] fn incidence_cursor_copy() { use $crate::traits::{GraphTopology, IncidenceCursor}; - let mut graph = <$T>::new(); - let v = graph.add_vertex(); - for _ in 0..2 { - let u = graph.add_vertex(); - graph.add_edge(u, v); - } - let mut c1 = graph.incidence_cursor(v); + let (graph, vertices, _): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::two_edge_path(); + // Traverses incidences of the middle vertex. + let mut c1 = graph.incidence_cursor(vertices[1]); assert!(c1.next(&graph).is_some(), "expected first incidence"); // Copies cursor mid-traversal. let mut c2 = c1; @@ -855,7 +660,7 @@ macro_rules! graph_topology_tests { #[test] fn incident_vertices_incidences_consistency() { use $crate::traits::GraphTopology; - let (graph, _, _, _) = make_test_graph(); + let (graph, _, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); for u in graph.vertices() { for incidence in graph.incidences(u) { let (w1, w2) = graph.incident_vertices(incidence.edge); @@ -871,7 +676,7 @@ macro_rules! graph_topology_tests { #[test] fn incident_edges_incidences_consistency() { use $crate::traits::GraphTopology; - let (graph, _, _, _) = make_test_graph(); + let (graph, _, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); for u in graph.vertices() { let mut expected: Vec<_> = graph.incidences(u).map(|x| x.edge).collect(); for e in graph.incident_edges(u) { @@ -900,7 +705,7 @@ macro_rules! graph_topology_addition_tests { #[test] fn reserve_vertices_increases_capacity() { use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); + let mut graph = <$T>::default(); let capacity_before = graph.vertex_capacity(); graph.reserve_vertices(capacity_before + 10); assert!( @@ -912,7 +717,7 @@ macro_rules! graph_topology_addition_tests { #[test] fn reserve_vertices_prevents_reallocation_on_add() { use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); + let mut graph = <$T>::default(); graph.reserve_vertices(10); let capacity_before = graph.vertex_capacity(); for _ in 0..10 { @@ -928,7 +733,7 @@ macro_rules! graph_topology_addition_tests { #[test] fn reserve_vertices_does_not_affect_edge_capacity() { use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); + let mut graph = <$T>::default(); let capacity_before = graph.edge_capacity(); graph.reserve_vertices(10); assert_eq!( @@ -941,7 +746,7 @@ macro_rules! graph_topology_addition_tests { #[test] fn reserve_edges_increases_capacity() { use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); + let mut graph = <$T>::default(); let capacity_before = graph.edge_capacity(); graph.reserve_edges(capacity_before + 10); assert!( @@ -953,7 +758,7 @@ macro_rules! graph_topology_addition_tests { #[test] fn reserve_edges_prevents_reallocation_on_add() { use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); + let mut graph = <$T>::default(); let v1 = graph.add_vertex(); let v2 = graph.add_vertex(); graph.reserve_edges(10); @@ -971,7 +776,7 @@ macro_rules! graph_topology_addition_tests { #[test] fn reserve_edges_does_not_affect_vertex_capacity() { use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); + let mut graph = <$T>::default(); let capacity_before = graph.vertex_capacity(); graph.reserve_edges(10); assert_eq!( @@ -984,7 +789,7 @@ macro_rules! graph_topology_addition_tests { #[test] fn add_vertex() { use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); + let mut graph = <$T>::default(); let v = graph.add_vertex(); assert_ne!(graph.add_vertex(), v, "unexpected duplicate vertex"); } @@ -992,12 +797,45 @@ macro_rules! graph_topology_addition_tests { #[test] fn add_edge() { use $crate::traits::GraphTopologyAddition; - let mut graph = <$T>::new(); + let mut graph = <$T>::default(); let v1 = graph.add_vertex(); let v2 = graph.add_vertex(); let e = graph.add_edge(v1, v2); assert_ne!(graph.add_edge(v1, v2), e, "unexpected duplicate edge"); } + + #[test] + fn vertex_map_new_vertex() { + use $crate::traits::{GraphTopology, GraphTopologyAddition}; + let mut graph = <$T>::default(); + let mut map = graph.vertex_map(27); + let v = graph.add_vertex(); + assert_eq!( + map[v], 27, + "unexpected value from default map read for new vertex" + ); + map[v] = 9; + assert_eq!( + map[v], 9, + "unexpected value from map read after write for new vertex" + ); + } + + #[test] + fn edge_map_new_edge() { + use $crate::traits::{GraphTopology, GraphTopologyAddition}; + let mut graph = <$T>::default(); + let v1 = graph.add_vertex(); + let v2 = graph.add_vertex(); + let mut map = graph.edge_map(28); + let e = graph.add_edge(v1, v2); + assert_eq!(map[e], 28,); + map[e] = 8; + assert_eq!( + map[e], 8, + "unexpected value from map read after write for new edge" + ); + } }; } @@ -1007,40 +845,18 @@ macro_rules! graph_topology_deletion_tests { ($T:ty) => { #[test] fn delete_vertex() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let mut graph = Graph::new(); - let v = graph.add_vertex(); - assert_eq!( - graph.vertex_count(), - 1, - "unexpected vertex count before delete" - ); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + let (mut graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); + assert_eq!(graph.vertex_count(), 1, "unexpected vertex count before delete"); graph.delete_vertex(v); - assert_eq!( - graph.vertex_count(), - 0, - "unexpected vertex count after delete" - ); - assert_ne!( - graph.add_vertex(), - v, - "unexpected duplicate vertex after delete" - ); + assert_eq!(graph.vertex_count(), 0, "unexpected vertex count after delete"); } #[test] fn delete_vertex_loop() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let mut graph = Graph::new(); - let v = graph.add_vertex(); - graph.add_edge(v, v); - assert_eq!( - graph.vertex_count(), - 1, - "unexpected vertex count before delete" - ); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + let (mut graph, v, _): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::loop_edge(); + assert_eq!(graph.vertex_count(), 1, "unexpected vertex count before delete"); assert_eq!(graph.edge_count(), 1, "unexpected edge count before delete"); assert!( graph.are_adjacent(v, v), @@ -1048,25 +864,14 @@ macro_rules! graph_topology_deletion_tests { ); assert_eq!(graph.degree(v), 2, "unexpected vertex degree before delete"); graph.delete_vertex(v); - assert_eq!( - graph.vertex_count(), - 0, - "unexpected vertex count after delete" - ); + assert_eq!(graph.vertex_count(), 0, "unexpected vertex count after delete"); assert_eq!(graph.edge_count(), 0, "unexpected edge count after delete"); - assert_ne!( - graph.add_vertex(), - v, - "unexpected duplicate vertex after delete" - ); } #[test] fn delete_vertex_invalid_index() { - use $crate::traits::GraphTopologyAddition; use $crate::traits::GraphTopologyDeletion; - let mut graph = Graph::new(); - let v = graph.add_vertex(); + let (mut graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); graph.delete_vertex(v); let result = std::panic::catch_unwind(move || graph.delete_vertex(v)); assert!(result.is_err(), "second deletion should panic"); @@ -1074,25 +879,12 @@ macro_rules! graph_topology_deletion_tests { #[test] fn delete_vertex_connected() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let (mut graph, vertices, _, _) = make_test_graph(); - assert_eq!( - graph.vertex_count(), - 10, - "unexpected vertex count before delete" - ); - assert_eq!( - graph.edge_count(), - 18, - "unexpected edge count before delete" - ); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + let (mut graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); + assert_eq!(graph.vertex_count(), 10, "unexpected vertex count before delete"); + assert_eq!(graph.edge_count(), 18, "unexpected edge count before delete"); graph.delete_vertex(vertices[2]); - assert_eq!( - graph.vertex_count(), - 9, - "unexpected vertex count after delete" - ); + assert_eq!(graph.vertex_count(), 9, "unexpected vertex count after delete"); assert_eq!(graph.edge_count(), 12, "unexpected edge count after delete"); let expected_edges = [ (vertices[0], vertices[1]), @@ -1124,146 +916,70 @@ macro_rules! graph_topology_deletion_tests { #[test] fn delete_edge() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let mut graph = Graph::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let e = graph.add_edge(v1, v2); - assert_eq!( - graph.vertex_count(), - 2, - "unexpected vertex count before delete" - ); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + let (mut graph, vertices, e): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::single_edge(); + assert_eq!(graph.vertex_count(), 2, "unexpected vertex count before delete"); assert_eq!(graph.edge_count(), 1, "unexpected edge count before delete"); assert!( - graph.are_adjacent(v1, v2), + graph.are_adjacent(vertices[0], vertices[1]), "expected vertices to be adjacent before delete" ); - assert_eq!( - graph.degree(v1), - 1, - "unexpected vertex degree before delete" - ); - assert_eq!( - graph.degree(v2), - 1, - "unexpected vertex degree before delete" - ); + assert_eq!(graph.degree(vertices[0]), 1, "unexpected vertex degree before delete"); + assert_eq!(graph.degree(vertices[1]), 1, "unexpected vertex degree before delete"); graph.delete_edge(e); - assert_eq!( - graph.vertex_count(), - 2, - "unexpected vertex count after delete" - ); + assert_eq!(graph.vertex_count(), 2, "unexpected vertex count after delete"); assert_eq!(graph.edge_count(), 0, "unexpected edge count after delete"); assert!( - !graph.are_adjacent(v1, v2), + !graph.are_adjacent(vertices[0], vertices[1]), "unexpected adjacency after delete" ); - assert_eq!(graph.degree(v1), 0, "unexpected vertex degree after delete"); - assert_eq!(graph.degree(v2), 0, "unexpected vertex degree after delete"); - assert_ne!( - graph.add_edge(v1, v2), - e, - "unexpected duplicate edge after delete" - ); + assert_eq!(graph.degree(vertices[0]), 0, "unexpected vertex degree after delete"); + assert_eq!(graph.degree(vertices[1]), 0, "unexpected vertex degree after delete"); } #[test] fn delete_edge_loop() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let mut graph = Graph::new(); - let v = graph.add_vertex(); - let e = graph.add_edge(v, v); - assert_eq!( - graph.vertex_count(), - 1, - "unexpected vertex count before delete" - ); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + let (mut graph, v, e): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::loop_edge(); + assert_eq!(graph.vertex_count(), 1, "unexpected vertex count before delete"); assert_eq!(graph.edge_count(), 1, "unexpected edge count before delete"); - assert!( - graph.are_adjacent(v, v), - "expected vertex to be self-adjacent before delete" - ); + assert!(graph.are_adjacent(v, v), "expected vertex to be self-adjacent before delete"); assert_eq!(graph.degree(v), 2, "unexpected vertex degree before delete"); graph.delete_edge(e); - assert_eq!( - graph.vertex_count(), - 1, - "unexpected vertex count after delete" - ); + assert_eq!(graph.vertex_count(), 1, "unexpected vertex count after delete"); assert_eq!(graph.edge_count(), 0, "unexpected edge count after delete"); - assert!( - !graph.are_adjacent(v, v), - "unexpected adjacency after delete" - ); + assert!(!graph.are_adjacent(v, v), "unexpected adjacency after delete"); assert_eq!(graph.degree(v), 0, "unexpected vertex degree after delete"); - assert_ne!( - graph.add_edge(v, v), - e, - "unexpected duplicate edge after delete" - ); } #[test] fn delete_edge_multiple() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let mut graph = Graph::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let e = graph.add_edge(v1, v2); - graph.add_edge(v1, v2); - assert_eq!( - graph.vertex_count(), - 2, - "unexpected vertex count before delete" - ); - assert_eq!(graph.edge_count(), 2, "unexpected edge count before delete"); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + const K: usize = 2; + let (mut graph, vertices, edges): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::multiple_edges::(); + assert_eq!(graph.vertex_count(), 2, "unexpected vertex count before delete"); + assert_eq!(graph.edge_count(), K, "unexpected edge count before delete"); assert!( - graph.are_adjacent(v1, v2), + graph.are_adjacent(vertices[0], vertices[1]), "expected vertices to be adjacent before delete" ); - assert_eq!( - graph.degree(v1), - 2, - "unexpected vertex degree before delete" - ); - assert_eq!( - graph.degree(v2), - 2, - "unexpected vertex degree before delete" - ); - graph.delete_edge(e); - assert_eq!( - graph.vertex_count(), - 2, - "unexpected vertex count after delete" - ); - assert_eq!(graph.edge_count(), 1, "unexpected edge count after delete"); + assert_eq!(graph.degree(vertices[0]), K, "unexpected vertex degree before delete"); + assert_eq!(graph.degree(vertices[1]), K, "unexpected vertex degree before delete"); + graph.delete_edge(edges[0]); + assert_eq!(graph.vertex_count(), 2, "unexpected vertex count after delete"); + assert_eq!(graph.edge_count(), K - 1, "unexpected edge count after delete"); assert!( - graph.are_adjacent(v1, v2), + graph.are_adjacent(vertices[0], vertices[1]), "expected vertices to be adjacent after delete" ); - assert_eq!(graph.degree(v1), 1, "unexpected vertex degree after delete"); - assert_eq!(graph.degree(v2), 1, "unexpected vertex degree after delete"); - assert_ne!( - graph.add_edge(v1, v2), - e, - "unexpected duplicate edge after delete" - ); + assert_eq!(graph.degree(vertices[0]), K - 1, "unexpected vertex degree after delete"); + assert_eq!(graph.degree(vertices[1]), K - 1, "unexpected vertex degree after delete"); } #[test] fn delete_edge_invalid_index() { - use $crate::traits::GraphTopologyAddition; use $crate::traits::GraphTopologyDeletion; - let mut graph = Graph::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let e = graph.add_edge(v1, v2); + let (mut graph, _, e): ($T, _, _) = $crate::testing::fixtures::MakeTestGraph::single_edge(); graph.delete_edge(e); let result = std::panic::catch_unwind(move || graph.delete_edge(e)); assert!(result.is_err(), "second deletion should panic"); @@ -1271,15 +987,10 @@ macro_rules! graph_topology_deletion_tests { #[test] fn vertices_after_delete() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let (mut graph, vertices, _, _) = make_test_graph(); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + let (mut graph, vertices, _, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); graph.delete_vertex(vertices[2]); - assert_eq!( - graph.vertex_count(), - 9, - "unexpected vertex count after delete" - ); + assert_eq!(graph.vertex_count(), 9, "unexpected vertex count after delete"); assert_eq!( graph.vertices().count(), 9, @@ -1303,9 +1014,8 @@ macro_rules! graph_topology_deletion_tests { #[test] fn incident_vertices_after_delete_edge() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let (mut graph, _, edges, _) = make_test_graph(); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + let (mut graph, _, edges, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); let e = edges[2].0; graph.delete_edge(e); for &(f, v1, v2) in edges.iter().filter(|&&(f, _, _)| f != e) { @@ -1319,16 +1029,11 @@ macro_rules! graph_topology_deletion_tests { #[test] fn edges_after_delete() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let (mut graph, vertices, edges, _) = make_test_graph(); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + let (mut graph, vertices, edges, _): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); graph.delete_vertex(vertices[2]); assert_eq!(graph.edge_count(), 12, "unexpected edge count after delete"); - assert_eq!( - graph.edges().count(), - 12, - "unexpected edge iterator count after delete" - ); + assert_eq!(graph.edges().count(), 12, "unexpected edge iterator count after delete"); for i in [2, 5, 6, 7, 8, 9] { assert!( !graph.edges().any(|e| e == edges[i].0), @@ -1347,9 +1052,8 @@ macro_rules! graph_topology_deletion_tests { #[test] fn incident_edges_after_delete_edge() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let (mut graph, vertices, edges, incidences) = make_test_graph(); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + let (mut graph, vertices, edges, incidences): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); graph.delete_edge(edges[2].0); for i in 0..10 { let mut expected: Vec<_> = incidences[i] @@ -1380,9 +1084,8 @@ macro_rules! graph_topology_deletion_tests { #[test] fn incident_edges_after_delete_vertex() { - use $crate::traits::GraphTopology; - use $crate::traits::GraphTopologyDeletion; - let (mut graph, vertices, _, incidences) = make_test_graph(); + use $crate::traits::{GraphTopology, GraphTopologyDeletion}; + let (mut graph, vertices, _, incidences): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); graph.delete_vertex(vertices[2]); for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] { let mut expected: Vec<_> = incidences[i] @@ -1414,7 +1117,7 @@ macro_rules! graph_topology_deletion_tests { #[test] fn incidences_after_delete_vertex() { use $crate::traits::GraphTopologyDeletion; - let (mut graph, vertices, _, incidences) = make_test_graph(); + let (mut graph, vertices, _, incidences): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); graph.delete_vertex(vertices[2]); for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] { let remaining = incidences[i] @@ -1429,7 +1132,7 @@ macro_rules! graph_topology_deletion_tests { #[test] fn incidences_after_delete_edge() { use $crate::traits::GraphTopologyDeletion; - let (mut graph, vertices, edges, incidences) = make_test_graph(); + let (mut graph, vertices, edges, incidences): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); // Deletes the edge from vertices[1] to vertices[2]. graph.delete_edge(edges[2].0); for i in 0..10 { @@ -1442,6 +1145,7 @@ macro_rules! graph_topology_deletion_tests { } } + // TODO: Move out of macro. fn assert_vertex_incidences( graph: &$T, v: <$T as $crate::traits::GraphTopology>::Vertex, @@ -1478,7 +1182,7 @@ macro_rules! graph_topology_deletion_tests { #[test] fn incidence_cursor_after_delete_vertex() { use $crate::traits::GraphTopologyDeletion; - let (mut graph, vertices, _, incidences) = make_test_graph(); + let (mut graph, vertices, _, incidences): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); graph.delete_vertex(vertices[2]); for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] { let remaining = incidences[i] @@ -1493,7 +1197,7 @@ macro_rules! graph_topology_deletion_tests { #[test] fn incidence_cursor_after_delete_edge() { use $crate::traits::GraphTopologyDeletion; - let (mut graph, vertices, edges, incidences) = make_test_graph(); + let (mut graph, vertices, edges, incidences): ($T, _, _, _) = $crate::testing::fixtures::MakeTestGraph::standard(); // Deletes the edge from vertices[1] to vertices[2]. graph.delete_edge(edges[2].0); for i in 0..10 { @@ -1506,6 +1210,7 @@ macro_rules! graph_topology_deletion_tests { } } + // TODO: Move out of macro. fn assert_vertex_incidence_cursor( graph: &$T, v: <$T as $crate::traits::GraphTopology>::Vertex, @@ -1514,7 +1219,7 @@ macro_rules! graph_topology_deletion_tests { <$T as $crate::traits::GraphTopology>::Edge, >>, ) { - use $crate::traits::IncidenceCursor; + use $crate::traits::{GraphTopology, IncidenceCursor}; let mut cursor = graph.incidence_cursor(v); while let Some(incidence) = cursor.next(graph) { let pos = expected @@ -1535,3 +1240,46 @@ macro_rules! graph_topology_deletion_tests { } }; } + +#[doc(hidden)] +#[macro_export] +macro_rules! graph_topology_addition_deletion_tests { + ($T:ty) => { + #[test] + fn delete_vertex_add_vertex() { + use $crate::traits::{GraphTopology, GraphTopologyAddition, GraphTopologyDeletion}; + let (mut graph, v): ($T, _) = $crate::testing::fixtures::MakeTestGraph::single_vertex(); + graph.delete_vertex(v); + assert_eq!( + graph.vertex_count(), + 0, + "unexpected vertex count after delete" + ); + assert_ne!( + graph.add_vertex(), + v, + "unexpected duplicate vertex after delete" + ); + assert_eq!( + graph.vertex_count(), + 1, + "unexpected vertex count after re-add" + ); + } + + #[test] + fn delete_edge_add_edge() { + use $crate::traits::{GraphTopology, GraphTopologyAddition, GraphTopologyDeletion}; + let (mut graph, vertices, e): ($T, _, _) = + $crate::testing::fixtures::MakeTestGraph::single_edge(); + graph.delete_edge(e); + assert_eq!(graph.edge_count(), 0, "unexpected edge count after delete"); + assert_ne!( + graph.add_edge(vertices[0], vertices[1]), + e, + "unexpected duplicate edge after re-add" + ); + assert_eq!(graph.edge_count(), 1, "unexpected edge count after re-add"); + } + }; +} diff --git a/tests/bfs.rs b/tests/bfs.rs index 293ea12..babd76a 100644 --- a/tests/bfs.rs +++ b/tests/bfs.rs @@ -1,13 +1,11 @@ mod append_graph_tests { use grapherity::models::AppendGraph; - grapherity::graph_topology_test_fixtures!(AppendGraph); grapherity::bfs_tests!(AppendGraph); } mod graph_tests { use grapherity::models::Graph; - grapherity::graph_topology_test_fixtures!(Graph); grapherity::bfs_tests!(Graph); } diff --git a/tests/dfs.rs b/tests/dfs.rs index ec7e039..fcbbc3b 100644 --- a/tests/dfs.rs +++ b/tests/dfs.rs @@ -1,13 +1,11 @@ mod append_graph_tests { use grapherity::models::AppendGraph; - grapherity::graph_topology_test_fixtures!(AppendGraph); grapherity::dfs_tests!(AppendGraph); } mod graph_tests { use grapherity::models::Graph; - grapherity::graph_topology_test_fixtures!(Graph); grapherity::dfs_tests!(Graph); } diff --git a/tests/dijkstra.rs b/tests/dijkstra.rs index b495546..e655000 100644 --- a/tests/dijkstra.rs +++ b/tests/dijkstra.rs @@ -1,13 +1,11 @@ mod append_graph_tests { use grapherity::models::AppendGraph; - grapherity::graph_topology_test_fixtures!(AppendGraph); grapherity::dijkstra_tests!(AppendGraph); } mod graph_tests { use grapherity::models::Graph; - grapherity::graph_topology_test_fixtures!(Graph); grapherity::dijkstra_tests!(Graph); }