#[doc(hidden)] #[macro_export] macro_rules! dfs_tests { ($T:ty) => { #[test] fn dfs_single_vertex() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_vertex(); let result = $crate::algorithms::dfs(&graph, v); assert!(result.visited[v], "source vertex should be visited"); assert_eq!( result.predecessors[v], None, "unexpected predecessor of source vertex" ); } #[test] fn dfs_disconnected() { let (graph, vertices) = make_test_graph_disconnected(); let result = $crate::algorithms::dfs(&graph, vertices[0]); assert!( result.visited[vertices[0]], "source vertex should be visited" ); assert_eq!( result.predecessors[vertices[0]], None, "unexpected predecessor of source vertex" ); for &v in &vertices[1..3] { assert!( !result.visited[v], "disconnected vertex {v:?} should not be visited" ); assert_eq!( result.predecessors[v], None, "disconnected vertex {v:?} should have no predecessor" ); } } #[test] fn dfs() { let (graph, vertices, _, _) = make_test_graph(); let result = $crate::algorithms::dfs(&graph, vertices[0]); assert_dfs_visited(&result.visited, &vertices); assert_dfs_predecessors(&graph, &result.visited, &result.predecessors, &vertices); } #[test] fn dfs_visited_single_vertex() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_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 visited = $crate::algorithms::dfs_visited(&graph, vertices[0]); assert!(visited[vertices[0]], "source vertex should be visited"); for &v in &vertices[1..3] { assert!( !visited[v], "disconnected vertex {v:?} should not be visited" ); } } #[test] fn dfs_visited() { let (graph, vertices, _, _) = make_test_graph(); let visited = $crate::algorithms::dfs_visited(&graph, vertices[0]); assert_dfs_visited(&visited, &vertices); } #[test] fn dfs_find_source() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_vertex(); assert!( $crate::algorithms::dfs_find(&graph, v, v), "source should find itself" ); } #[test] fn dfs_find_disconnected() { let (graph, vertices) = make_test_graph_disconnected(); assert!( !$crate::algorithms::dfs_find(&graph, vertices[0], vertices[1]), "disconnected target should not be found" ); } #[test] fn dfs_find() { let (graph, vertices, _, _) = make_test_graph(); for i in 0..10 { assert!( $crate::algorithms::dfs_find(&graph, vertices[0], vertices[i]), "vertex {:?} should be reachable from {:?}", vertices[i], vertices[0] ); } } #[test] fn dfs_find_where_source_matches() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_vertex(); assert_eq!( $crate::algorithms::dfs_find_where(&graph, v, |u| u == v), Some(v), "source should find itself" ); } #[test] fn dfs_find_where_disconnected() { let (graph, vertices) = make_test_graph_disconnected(); assert_eq!( $crate::algorithms::dfs_find_where(&graph, vertices[0], |v| v == vertices[1]), None, "disconnected vertex {:?} should not be found", vertices[1] ); } #[test] fn dfs_find_where_no_match() { let (graph, vertices, _, _) = make_test_graph(); assert_eq!( $crate::algorithms::dfs_find_where(&graph, vertices[0], |_| false), None, "no vertex should match an always-false predicate" ); } #[test] fn dfs_find_where_adjacent() { let (graph, vertices, _, _) = make_test_graph(); assert_eq!( $crate::algorithms::dfs_find_where(&graph, vertices[0], |v| v == vertices[1]), Some(vertices[1]), "expected to find adjacent vertex" ); } #[test] fn dfs_find_where() { let (graph, vertices, _, _) = make_test_graph(); assert_eq!( $crate::algorithms::dfs_find_where(&graph, vertices[0], |v| v == vertices[9]), Some(vertices[9]), "expected to find connected vertex" ); } fn assert_dfs_visited( visited: &$crate::maps::VertexMap<<$T as $crate::traits::GraphTopology>::Vertex, bool>, vertices: &[<$T as $crate::traits::GraphTopology>::Vertex], ) { for i in 0..10 { assert!( visited[vertices[i]], "vertex {:?} should be visited", vertices[i] ); } } fn assert_dfs_predecessors( graph: &$T, visited: &$crate::maps::VertexMap<<$T as $crate::traits::GraphTopology>::Vertex, bool>, predecessors: &$crate::maps::VertexMap< <$T as $crate::traits::GraphTopology>::Vertex, Option<<$T as $crate::traits::GraphTopology>::Vertex>, >, vertices: &[<$T as $crate::traits::GraphTopology>::Vertex], ) { use $crate::traits::GraphTopology; assert_eq!( predecessors[vertices[0]], None, "source should have no predecessor" ); for i in 1..10 { let v = vertices[i]; let p = predecessors[v].expect(&format!("vertex {v:?} should have a predecessor")); assert!( visited[p], "predecessor {p:?} of vertex {v:?} should be visited" ); assert!( graph.are_adjacent(v, p), "predecessor {p:?} of vertex {v:?} should be adjacent" ); } } }; }