#[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<( <$T as $crate::traits::GraphTopology>::Vertex, <$T as $crate::traits::GraphTopology>::Edge, )>; 10], ) { use $crate::traits::GraphTopology; 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 incidences: [Vec<_>; 10] = [ vec![(vertices[1], edges[0].0), (vertices[1], edges[1].0)], vec![ (vertices[0], edges[0].0), (vertices[0], edges[1].0), (vertices[2], edges[2].0), (vertices[3], edges[3].0), (vertices[4], edges[4].0), ], vec![ (vertices[2], edges[5].0), (vertices[2], edges[5].0), (vertices[1], edges[2].0), (vertices[4], edges[6].0), (vertices[4], edges[7].0), (vertices[5], edges[8].0), (vertices[6], edges[9].0), ], vec![(vertices[1], edges[3].0), (vertices[6], edges[10].0)], vec![ (vertices[1], edges[4].0), (vertices[2], edges[6].0), (vertices[2], edges[7].0), (vertices[4], edges[11].0), (vertices[4], edges[11].0), (vertices[7], edges[12].0), (vertices[8], edges[13].0), ], vec![(vertices[2], edges[8].0), (vertices[9], edges[14].0)], vec![ (vertices[2], edges[9].0), (vertices[3], edges[10].0), (vertices[9], edges[15].0), ], vec![ (vertices[4], edges[12].0), (vertices[8], edges[16].0), (vertices[9], edges[17].0), ], vec![(vertices[4], edges[13].0), (vertices[7], edges[16].0)], vec![ (vertices[5], edges[14].0), (vertices[6], edges[15].0), (vertices[7], edges[17].0), ], ]; (graph, vertices, edges, incidences) } }; } #[macro_export] macro_rules! graph_topology_tests { ($T:ty) => { #[test] fn add_vertex() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_vertex(); assert_ne!(graph.add_vertex(), v, "unexpected duplicate vertex"); } #[test] fn vertex_count_empty() { use $crate::traits::GraphTopology; let graph = <$T>::new(); assert_eq!(graph.vertex_count(), 0, "unexpected vertex count"); } #[test] fn vertex_count() { use $crate::traits::GraphTopology; let (graph, _, _, _) = make_test_graph(); assert_eq!(graph.vertex_count(), 10, "unexpected vertex count"); } #[test] fn add_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); assert_ne!(graph.add_edge(v1, v2), e, "unexpected duplicate edge"); } #[test] fn edge_count_empty() { use $crate::traits::GraphTopology; let graph = <$T>::new(); assert_eq!(graph.edge_count(), 0, "unexpected edge count"); } #[test] fn edge_count() { use $crate::traits::GraphTopology; let (graph, _, _, _) = make_test_graph(); assert_eq!(graph.edge_count(), 18, "unexpected edge count"); } #[test] fn degree_zero() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_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 expected_degrees = [2, 5, 7, 2, 7, 2, 3, 3, 2, 3]; for i in 0..graph.vertex_count() { assert_eq!( graph.degree(vertices[i]), expected_degrees[i], "unexpected degree of {:?}", vertices[i] ); } } #[test] fn loop_edge() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_vertex(); graph.add_edge(v, v); 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"); assert!( graph.are_adjacent(v, v), "vertex with loop edge should be adjacent to itself" ); } #[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); } 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"); } #[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" ); } #[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"); } #[test] fn are_adjacent() { use $crate::traits::GraphTopology; let (graph, vertices, _, _) = make_test_graph(); assert!( graph.are_adjacent(vertices[0], vertices[1]), "expected {:?} and {:?} to be adjacent", vertices[0], vertices[1] ); assert!( graph.are_adjacent(vertices[9], vertices[5]), "expected {:?} and {:?} to be adjacent", vertices[9], vertices[5] ); assert!( !graph.are_adjacent(vertices[9], vertices[3]), "unexpected adjacency of {:?} and {:?}", vertices[9], vertices[3] ); for i in 0..graph.vertex_count() { let exp = match i { 1 | 2 | 4 | 5 | 6 => true, _ => false, }; assert_eq!( graph.are_adjacent(vertices[2], vertices[i]), exp, "unexpected adjacency of {:?} and {:?}", vertices[2], vertices[i] ); assert_eq!( graph.are_adjacent(vertices[i], vertices[2]), exp, "unexpected adjacency of {:?} and {:?}", vertices[i], vertices[2] ); } } #[test] fn vertices_empty() { use $crate::traits::GraphTopology; let graph = <$T>::new(); assert_eq!( graph.vertices().count(), 0, "vertex iterator of empty graph should have no elements" ); } #[test] fn vertices() { use $crate::traits::GraphTopology; let (graph, vertices, _, _) = make_test_graph(); assert_eq!(graph.vertices().count(), 10, "unexpected vertex count"); // Expects each vertex to appear exactly once. for v in graph.vertices() { assert_eq!( vertices.iter().filter(|&x| *x == v).count(), 1, "unexpected vertex {v:?} from the iterator" ); } } #[test] fn adjacent_vertices_empty() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_vertex(); assert_eq!( graph.adjacent_vertices(v).count(), 0, "adjacent vertex iterator of vertex with degree 0 should have no elements" ); } #[test] fn adjacent_vertices() { use $crate::traits::GraphTopology; let (graph, vertices, _, _) = make_test_graph(); // Checks adjacency of vertex 4. assert_eq!( graph.adjacent_vertices(vertices[4]).count(), 7, "unexpected adjacency count" ); let mut expected_adjacency = vec![ vertices[1], vertices[2], vertices[2], vertices[4], vertices[4], vertices[7], vertices[8], ]; for v in graph.adjacent_vertices(vertices[4]) { let i = expected_adjacency .iter() .position(|w| *w == v) .expect(&format!( "unexpected adjacent vertex {v:?} of {:?} from the iterator", vertices[4] )); expected_adjacency.swap_remove(i); } assert_eq!( expected_adjacency.len(), 0, "expected adjacent vertices {:?} of {:?} were not matched by the iterator", expected_adjacency, vertices[4] ); } #[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 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" ); } #[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]); } for i in 0..2 { let mut iter = graph.adjacent_vertices(vertices[i]); for j in 0..k { assert_eq!( iter.next(), Some(vertices[1 - i]), "unexpected adjacent vertex {j} of vertex {:?}", vertices[i] ); } assert_eq!( iter.next(), None, "too many adjacent vertices of vertex {:?} from iterator", vertices[i] ); } } #[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); assert!( (u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1), "unexpected incident vertices {u1:?} and {u2:?} 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); assert_eq!( graph.incident_vertices(e), (v, v), "unexpected incident vertices for loop edge {e:?}" ); } #[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); assert!( (u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1), "unexpected incident vertices {u1:?} and {u2:?} for first multi-edge {e1:?}" ); let (u1, u2) = graph.incident_vertices(e2); assert!( (u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1), "unexpected incident vertices {u1:?} and {u2:?} for second multi-edge {e2:?}" ); } #[test] fn incident_vertices() { use $crate::traits::GraphTopology; let (graph, _, edges, _) = make_test_graph(); for &(e, v1, v2) in edges.iter() { let (u1, u2) = graph.incident_vertices(e); assert!( (u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1), "unexpected incident vertices {u1:?} and {u2:?} for edge {e:?}" ); } } #[test] fn edges_empty() { use $crate::traits::GraphTopology; let graph = <$T>::new(); assert_eq!( graph.edges().count(), 0, "edge iterator of empty graph should have no elements" ); } #[test] fn edges() { use $crate::traits::GraphTopology; let (graph, _, edges, _) = make_test_graph(); assert_eq!(graph.edges().count(), 18, "unexpected edge count"); // Expects each edge to appear exactly once. for e in graph.edges() { assert_eq!( edges.iter().filter(|&&(f, _, _)| f == e).count(), 1, "unexpected edge {e:?} from the iterator" ); } } #[test] fn incident_edges_empty() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_vertex(); assert_eq!( graph.incident_edges(v).count(), 0, "incident edge iterator of vertex with degree 0 should have no elements" ); } #[test] fn incident_edges() { use $crate::traits::GraphTopology; let (graph, vertices, _, incidences) = make_test_graph(); for i in 0..10 { assert_eq!( graph.incident_edges(vertices[i]).count(), incidences[i].len(), "unexpected incident edge count for vertex {:?}", vertices[i] ); let mut expected: Vec<_> = incidences[i].iter().map(|(_, e)| *e).collect(); for e in graph.incident_edges(vertices[i]) { let pos = expected .iter() .position(|f| *f == e) .expect(&format!( "unexpected incident edge {e:?} of vertex {:?} from the iterator", vertices[i] )); expected.swap_remove(pos); } assert!( expected.is_empty(), "expected incident edges {:?} of vertex {:?} were not matched by the iterator", expected, vertices[i] ); } } #[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 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(), 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])); } for i in 0..2 { let mut expected = edges.clone(); for e in graph.incident_edges(vertices[i]) { let pos = expected .iter() .position(|f| *f == e) .expect(&format!( "unexpected incident edge {e:?} of vertex {:?}", vertices[i] )); expected.swap_remove(pos); } assert!( expected.is_empty(), "expected incident edges {:?} of vertex {:?} were not matched by the iterator", expected, vertices[i] ); } } #[test] fn incidences_empty() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_vertex(); assert_eq!( graph.incidences(v).count(), 0, "incidence iterator of vertex with degree 0 should have no elements" ); } #[test] fn incidences() { use $crate::traits::GraphTopology; let (graph, vertices, _, incidences) = make_test_graph(); for i in 0..10 { assert_eq!( graph.incidences(vertices[i]).count(), incidences[i].len(), "unexpected incidence count for vertex {:?}", vertices[i] ); let mut expected = incidences[i].clone(); for incidence in graph.incidences(vertices[i]) { let pos = expected .iter() .position(|(v, e)| *v == incidence.0 && *e == incidence.1) .expect(&format!( "unexpected incidence {incidence:?} of vertex {:?} from the iterator", vertices[i] )); expected.swap_remove(pos); } assert!( expected.is_empty(), "expected incidences {:?} of vertex {:?} were not matched by the iterator", expected, vertices[i] ); } } #[test] fn incidences_edge_consistency() { 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(); for u in graph.vertices() { for (v, e) in graph.incidences(u) { if u == v { assert_eq!( graph.incidences(u).filter(|(_, f)| *f == e).count(), 2, "loop edge {e:?} should appear exactly twice in incidences of vertex {u:?}" ); } else { assert!( graph.incidences(v).any(|(w, f)| w == u && f == e), "edge {e:?} from incidences of vertex {u:?} missing in incidences of adjacent vertex {v:?}" ); } } } } #[test] fn incidences_loop_edge() { use $crate::traits::GraphTopology; let mut graph = <$T>::new(); let v = graph.add_vertex(); let e = graph.add_edge(v, v); let mut iter = graph.incidences(v); assert_eq!( iter.next(), Some((v, e)), "vertex should be adjacent to itself" ); assert_eq!( iter.next(), Some((v, e)), "vertex should be adjacent to itself twice" ); 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])); } for i in 0..2 { let mut iter = graph.incidences(vertices[i]); for j in 0..k { let current = iter.next().expect(&format!( "incidence {j} missing, expected {k} incidences for vertex {:?}", vertices[i] )); assert_eq!( current.0, vertices[1 - i], "unexpected adjacent vertex of vertex {:?} in incidence {j}", vertices[i] ); assert_eq!( edges.iter().filter(|e| **e == current.1).count(), 1, "unexpected incident edge {:?} of vertex {:?}", current.1, vertices[i], ); } assert_eq!( iter.next(), None, "too many adjacent vertices of {:?} from iterator", vertices[i] ); } } #[test] fn incident_vertices_incidences_consistency() { use $crate::traits::GraphTopology; let (graph, _, _, _) = make_test_graph(); for u in graph.vertices() { for (v, e) in graph.incidences(u) { let (w1, w2) = graph.incident_vertices(e); assert!( (w1 == u && w2 == v) || (w1 == v && w2 == u), "incident vertices {w1:?} and {w2:?} of edge {e:?} are inconsistent with incidence ({v:?}, {e:?}) of vertex {u:?}" ); } } } #[test] fn incident_edges_incidences_consistency() { use $crate::traits::GraphTopology; let (graph, _, _, _) = make_test_graph(); for u in graph.vertices() { let mut expected: Vec<_> = graph.incidences(u).map(|(_, e)| e).collect(); for e in graph.incident_edges(u) { let pos = expected .iter() .position(|f| *f == e) .expect(&format!( "incident edge {e:?} of vertex {u:?} missing from incidences" )); expected.swap_remove(pos); } assert!( expected.is_empty(), "incidence edges {:?} of vertex {u:?} not matched by incident_edges", expected ); } } }; } #[macro_export] 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" ); 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" ); } #[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" ); 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_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.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::GraphTopology; use $crate::traits::GraphTopologyDeletion; let mut graph = Graph::new(); let v = graph.add_vertex(); graph.delete_vertex(v); let result = std::panic::catch_unwind(move || graph.delete_vertex(v)); assert!(result.is_err(), "second deletion should panic"); } #[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" ); graph.delete_vertex(vertices[2]); 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]), (vertices[1], vertices[3]), (vertices[1], vertices[4]), (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]), ]; for (v, u) in expected_edges { assert!( graph.are_adjacent(v, u), "expected {v:?} and {u:?} to be adjacent after delete" ); } for v in [vertices[1], vertices[4], vertices[5], vertices[6]] { assert!( !graph.adjacent_vertices(v).any(|u| u == vertices[2]), "unexpected adjacency of {v:?} to deleted vertex {:?}", vertices[2] ); } } #[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" ); assert_eq!(graph.edge_count(), 1, "unexpected edge count before delete"); assert!( graph.are_adjacent(v1, v2), "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" ); graph.delete_edge(e); 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), "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" ); } #[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" ); 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_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.edge_count(), 0, "unexpected edge count 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"); assert!( graph.are_adjacent(v1, v2), "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!( graph.are_adjacent(v1, v2), "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" ); } #[test] fn delete_edge_invalid_index() { 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.delete_edge(e); let result = std::panic::catch_unwind(move || graph.delete_edge(e)); assert!(result.is_err(), "second deletion should panic"); } #[test] fn vertices_after_delete() { use $crate::traits::GraphTopology; use $crate::traits::GraphTopologyDeletion; let (mut graph, vertices, _, _) = make_test_graph(); graph.delete_vertex(vertices[2]); assert_eq!( graph.vertex_count(), 9, "unexpected vertex count after delete" ); assert_eq!( graph.vertices().count(), 9, "unexpected vertex iterator count after delete" ); for v in graph.vertices() { assert_ne!( v, vertices[2], "deleted vertex {:?} appeared in iterator", vertices[2] ); } for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] { assert!( graph.vertices().any(|v| v == vertices[i]), "expected vertex {:?} missing from iterator after delete", vertices[i] ); } } #[test] fn incident_vertices_after_delete_edge() { use $crate::traits::GraphTopology; use $crate::traits::GraphTopologyDeletion; let (mut graph, _, edges, _) = make_test_graph(); let e = edges[2].0; graph.delete_edge(e); for &(f, v1, v2) in edges.iter().filter(|&&(f, _, _)| f != e) { let (u1, u2) = graph.incident_vertices(f); assert!( (u1 == v1 && u2 == v2) || (u1 == v2 && u2 == v1), "unexpected incident vertices {u1:?} and {u2:?} for edge {f:?} after delete" ); } } #[test] fn edges_after_delete() { use $crate::traits::GraphTopology; use $crate::traits::GraphTopologyDeletion; let (mut graph, vertices, edges, _) = make_test_graph(); 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" ); for i in [2, 5, 6, 7, 8, 9] { assert!( !graph.edges().any(|e| e == edges[i].0), "deleted edge {:?} appeared in iterator", edges[i].0 ); } for i in [0, 1, 3, 4, 10, 11, 12, 13, 14, 15, 16, 17] { assert!( graph.edges().any(|e| e == edges[i].0), "expected edge {:?} missing from iterator after delete", edges[i].0 ); } } #[test] fn incident_edges_after_delete_edge() { use $crate::traits::GraphTopology; use $crate::traits::GraphTopologyDeletion; let (mut graph, vertices, edges, incidences) = make_test_graph(); graph.delete_edge(edges[2].0); for i in 0..10 { let mut expected: Vec<_> = incidences[i] .iter() .filter(|(_, e)| *e != edges[2].0) .map(|(_, e)| *e) .collect(); assert_eq!( graph.incident_edges(vertices[i]).count(), expected.len(), "unexpected incident edge count for vertex {:?} after delete", vertices[i] ); for e in graph.incident_edges(vertices[i]) { let pos = expected.iter().position(|f| *f == e).expect(&format!( "unexpected incident edge {e:?} of vertex {:?} after delete", vertices[i] )); expected.swap_remove(pos); } assert!( expected.is_empty(), "expected incident edges {:?} of vertex {:?} not matched after delete", expected, vertices[i] ); } } #[test] fn incident_edges_after_delete_vertex() { use $crate::traits::GraphTopology; use $crate::traits::GraphTopologyDeletion; let (mut graph, vertices, _, incidences) = make_test_graph(); graph.delete_vertex(vertices[2]); for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] { let mut expected: Vec<_> = incidences[i] .iter() .filter(|(v, _)| *v != vertices[2]) .map(|(_, e)| *e) .collect(); assert_eq!( graph.incident_edges(vertices[i]).count(), expected.len(), "unexpected incident edge count for vertex {:?} after delete", vertices[i] ); for e in graph.incident_edges(vertices[i]) { let pos = expected.iter().position(|f| *f == e).expect(&format!( "unexpected incident edge {e:?} of vertex {:?} after delete", vertices[i] )); expected.swap_remove(pos); } assert!( expected.is_empty(), "expected incident edges {:?} of vertex {:?} not matched after delete", expected, vertices[i] ); } } #[test] fn incidences_after_delete_vertex() { use $crate::traits::GraphTopologyDeletion; let (mut graph, vertices, _, incidences) = make_test_graph(); graph.delete_vertex(vertices[2]); for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] { let remaining = incidences[i] .iter() .filter(|(v, _)| *v != vertices[2]) .cloned() .collect(); assert_vertex_incidences(&graph, vertices[i], remaining); } } #[test] fn incidences_after_delete_edge() { use $crate::traits::GraphTopologyDeletion; let (mut graph, vertices, edges, incidences) = make_test_graph(); // Deletes the edge from vertices[1] to vertices[2]. graph.delete_edge(edges[2].0); for i in 0..10 { let remaining = incidences[i] .iter() .filter(|(_, e)| *e != edges[2].0) .cloned() .collect(); assert_vertex_incidences(&graph, vertices[i], remaining); } } fn assert_vertex_incidences( graph: &$T, v: <$T as $crate::traits::GraphTopology>::Vertex, mut expected: Vec<( <$T as $crate::traits::GraphTopology>::Vertex, <$T as $crate::traits::GraphTopology>::Edge, )>, ) { use $crate::traits::GraphTopology; assert_eq!( graph.incidences(v).count(), expected.len(), "unexpected incidence count for vertex {:?} after delete", v ); for incidence in graph.incidences(v) { let pos = expected .iter() .position(|(u, e)| *u == incidence.0 && *e == incidence.1) .expect(&format!( "unexpected incidence {incidence:?} of vertex {:?} after delete", v )); expected.swap_remove(pos); } assert!( expected.is_empty(), "expected incidences {:?} of vertex {:?} not matched after delete", expected, v ); } }; }