Files
grapherity/src/testing/graph_topology_testing.rs
T

895 lines
25 KiB
Rust

use std::fmt::Debug;
use crate::testing::fixtures::MakeTestGraph;
use crate::traits::{Incidence, IncidenceCursor};
#[doc(hidden)]
#[macro_export]
macro_rules! graph_topology_tests {
($T:ty) => {
$crate::graph_topology_tests!(@wrap $T,
vertex_count_empty,
vertex_count,
vertex_map,
edge_count_empty,
edge_count,
edge_map,
degree_zero,
degree,
loop_edge,
multiple_edges,
are_adjacent_vertex_self,
are_adjacent_single_edge,
are_adjacent,
vertices_empty,
vertices,
adjacent_vertices_empty,
adjacent_vertices,
adjacent_vertices_loop_edge,
adjacent_vertices_multiple_edges,
incident_vertices_single_edge,
incident_vertices_loop_edge,
incident_vertices_multiple_edges,
incident_vertices,
edges_empty,
edges,
incident_edges_empty,
incident_edges,
incident_edges_loop_edge,
incident_edges_multiple_edges,
incidences_empty,
incidences,
incidences_edge_consistency,
incidences_loop_edge,
incidences_multiple_edges,
incidence_cursor_empty,
incidence_cursor,
incidence_cursor_loop_edge,
incidence_cursor_multiple_edges,
incidence_cursor_copy,
incident_vertices_incidences_consistency,
incident_edges_incidences_consistency,
common_neighbors,
common_neighbors_same_vertex,
common_neighbors_single,
common_neighbors_disconnected,
common_neighbors_multiple_edges,
common_neighbors_loop_edge,
);
};
(@wrap $T:ty, $($name:ident),* $(,)?) => {
$(
#[test]
fn $name() {
$crate::testing::graph_topology_testing::$name::<$T>();
}
)*
};
}
pub fn vertex_count_empty<G: MakeTestGraph>() {
let graph = G::empty();
assert_eq!(graph.vertex_count(), 0, "unexpected vertex count");
}
pub fn vertex_count<G: MakeTestGraph>() {
let (graph, _, _, _) = G::standard();
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
}
pub fn vertex_map<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, vertices, _, _) = G::standard();
let mut map = graph.vertex_map(88);
for (i, &v) in vertices.iter().enumerate() {
assert_eq!(
map[v], 88,
"unexpected value from default map read for vertex {v:?}"
);
map[v] = i;
}
for (i, &v) in vertices.iter().enumerate() {
assert_eq!(map[v], i, "unexpected value after write for vertex {v:?}");
}
}
pub fn edge_count_empty<G: MakeTestGraph>() {
let graph = G::empty();
assert_eq!(graph.edge_count(), 0, "unexpected edge count");
}
pub fn edge_count<G: MakeTestGraph>() {
let (graph, _, _, _) = G::standard();
assert_eq!(graph.edge_count(), 18, "unexpected edge count");
}
pub fn edge_map<G: MakeTestGraph>()
where
G::Edge: Debug,
{
let (graph, _, edges, _) = G::standard();
let mut map = graph.edge_map(99);
for (i, &(e, _, _)) in edges.iter().enumerate() {
assert_eq!(
map[e], 99,
"unexpected value from default map read for edge {e:?}"
);
map[e] = i;
}
for (i, &(e, _, _)) in edges.iter().enumerate() {
assert_eq!(map[e], i, "unexpected value after write for edge {e:?}");
}
}
pub fn degree_zero<G: MakeTestGraph>() {
let (graph, v) = G::single_vertex();
assert_eq!(graph.degree(v), 0, "unexpected non-zero degree");
}
pub fn degree<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, vertices, _, _) = G::standard();
let expected = [2, 5, 7, 2, 7, 2, 3, 3, 2, 3];
assert_eq!(vertices.len(), expected.len());
for (&v, &exp) in vertices.iter().zip(&expected) {
assert_eq!(graph.degree(v), exp, "unexpected degree of {v:?}");
}
}
pub fn loop_edge<G: MakeTestGraph>() {
let (graph, v, _) = G::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");
assert!(
graph.are_adjacent(v, v),
"vertex with loop edge should be adjacent to itself"
);
}
pub fn multiple_edges<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
const K: usize = 3;
let (graph, [v0, v1], _) = G::multiple_edges::<K>();
assert_eq!(graph.vertex_count(), 2, "unexpected vertex count");
assert_eq!(graph.edge_count(), K, "unexpected edge count");
assert_eq!(graph.degree(v0), K, "unexpected degree of vertex {v0:?}");
assert_eq!(graph.degree(v1), K, "unexpected degree of vertex {v1:?}",);
assert!(graph.are_adjacent(v0, v1), "should be adjacent");
}
pub fn are_adjacent_vertex_self<G: MakeTestGraph>() {
let (graph, v) = G::single_vertex();
assert!(
!graph.are_adjacent(v, v),
"should not be adjacent to itself"
);
}
pub fn are_adjacent_single_edge<G: MakeTestGraph>() {
let (graph, [v0, v1], _) = G::single_edge();
assert!(graph.are_adjacent(v0, v1), "should be adjacent");
assert!(graph.are_adjacent(v1, v0), "should be adjacent");
}
pub fn are_adjacent<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, vertices, _, _) = G::standard();
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, &v) in vertices.iter().enumerate() {
let exp = matches!(i, 1 | 2 | 4 | 5 | 6);
assert_eq!(
graph.are_adjacent(vertices[2], v),
exp,
"unexpected adjacency of {:?} and {v:?}",
vertices[2]
);
assert_eq!(
graph.are_adjacent(v, vertices[2]),
exp,
"unexpected adjacency of {v:?} and {:?}",
vertices[2]
);
}
}
pub fn vertices_empty<G: MakeTestGraph>() {
let graph = G::empty();
assert_eq!(
graph.vertices().count(),
0,
"vertex iterator of empty graph should have no elements"
);
}
pub fn vertices<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, vertices, _, _) = G::standard();
assert_eq!(graph.vertices().count(), 10, "unexpected vertex count");
for v in graph.vertices() {
assert_eq!(
vertices.iter().filter(|&x| *x == v).count(),
1,
"unexpected vertex {v:?} from iterator"
);
}
}
pub fn adjacent_vertices_empty<G: MakeTestGraph>() {
let (graph, v) = G::single_vertex();
assert_eq!(
graph.adjacent_vertices(v).count(),
0,
"adjacent vertex iterator of vertex with degree 0 should have no elements"
);
}
pub fn adjacent_vertices<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, vertices, _, _) = G::standard();
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)
.unwrap_or_else(|| {
panic!(
"unexpected adjacent vertex {v:?} of {:?} from iterator",
vertices[4]
)
});
expected_adjacency.swap_remove(i);
}
assert_eq!(
expected_adjacency.len(),
0,
"expected adjacent vertices {expected_adjacency:?} of {:?} were not matched by iterator",
vertices[4]
);
}
pub fn adjacent_vertices_loop_edge<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, v, _) = G::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"
);
}
pub fn adjacent_vertices_multiple_edges<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
const K: usize = 3;
let (graph, vertices, _) = G::multiple_edges::<K>();
for (i, &v) in vertices.iter().enumerate() {
let mut iter = graph.adjacent_vertices(v);
for j in 0..K {
assert_eq!(
iter.next(),
Some(vertices[1 - i]),
"unexpected adjacent vertex {j} of vertex {v:?}"
);
}
assert_eq!(
iter.next(),
None,
"too many adjacent vertices of vertex {v:?} from iterator"
);
}
}
pub fn incident_vertices_single_edge<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, [v0, v1], e) = G::single_edge();
let (u0, u1) = graph.incident_vertices(e);
assert!(
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
"unexpected incident vertices {u0:?} and {u1:?} for edge {e:?}"
);
}
pub fn incident_vertices_loop_edge<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, v, e) = G::loop_edge();
assert_eq!(
graph.incident_vertices(e),
(v, v),
"unexpected incident vertices for loop edge {e:?}"
);
}
pub fn incident_vertices_multiple_edges<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, [v0, v1], edges) = G::multiple_edges::<2>();
assert_ne!(edges[0], edges[1], "edges should be distinct");
for (i, &e) in edges.iter().enumerate() {
let (u0, u1) = graph.incident_vertices(e);
assert!(
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
"unexpected incident vertices {u0:?} and {u1:?} for multi-edge {e:?} (index {i})"
);
}
}
pub fn incident_vertices<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, _, edges, _) = G::standard();
for &(e, v0, v1) in edges.iter() {
let (u0, u1) = graph.incident_vertices(e);
assert!(
(u0 == v0 && u1 == v1) || (u0 == v1 && u1 == v0),
"unexpected incident vertices {u0:?} and {u1:?} for edge {e:?}"
);
}
}
pub fn edges_empty<G: MakeTestGraph>() {
let graph = G::empty();
assert_eq!(
graph.edges().count(),
0,
"edge iterator of empty graph should have no elements"
);
}
pub fn edges<G: MakeTestGraph>()
where
G::Edge: Debug,
{
let (graph, _, edges, _) = G::standard();
assert_eq!(graph.edges().count(), 18, "unexpected edge count");
for e in graph.edges() {
assert_eq!(
edges.iter().filter(|&&(f, _, _)| f == e).count(),
1,
"unexpected edge {e:?} from iterator"
);
}
}
pub fn incident_edges_empty<G: MakeTestGraph>() {
let (graph, v) = G::single_vertex();
assert_eq!(
graph.incident_edges(v).count(),
0,
"incident edge iterator of vertex with degree 0 should have no elements"
);
}
pub fn incident_edges<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, vertices, _, incidences) = G::standard();
assert_eq!(vertices.len(), incidences.len());
for (&v, incs) in vertices.iter().zip(&incidences) {
assert_eq!(
graph.incident_edges(v).count(),
incs.len(),
"unexpected incident edge count for vertex {v:?}"
);
let mut expected: Vec<_> = incs.iter().map(|x| x.edge).collect();
for e in graph.incident_edges(v) {
let pos = expected.iter().position(|&f| f == e).unwrap_or_else(|| {
panic!("unexpected incident edge {e:?} of vertex {v:?} from iterator")
});
expected.swap_remove(pos);
}
assert!(
expected.is_empty(),
"expected incident edges {expected:?} of vertex {v:?} were not matched by iterator"
);
}
}
pub fn incident_edges_loop_edge<G: MakeTestGraph>()
where
G::Edge: Debug,
{
let (graph, v, e) = G::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(), None, "too many incident edges from iterator");
}
pub fn incident_edges_multiple_edges<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
const K: usize = 3;
let (graph, vertices, edges) = G::multiple_edges::<K>();
for &v in &vertices {
let mut expected = edges.to_vec();
for e in graph.incident_edges(v) {
let pos = expected
.iter()
.position(|&f| f == e)
.unwrap_or_else(|| panic!("unexpected incident edge {e:?} of vertex {v:?}"));
expected.swap_remove(pos);
}
assert!(
expected.is_empty(),
"expected incident edges {expected:?} of vertex {v:?} were not matched by iterator"
);
}
}
pub fn incidences_empty<G: MakeTestGraph>() {
let (graph, v) = G::single_vertex();
assert_eq!(
graph.incidences(v).count(),
0,
"incidence iterator of vertex with degree 0 should have no elements"
);
}
pub fn incidences<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, vertices, _, incidences) = G::standard();
assert_eq!(vertices.len(), incidences.len());
for (&v, incs) in vertices.iter().zip(&incidences) {
assert_eq!(
graph.incidences(v).count(),
incs.len(),
"unexpected incidence count for vertex {v:?}"
);
let mut expected = incs.clone();
for incidence in graph.incidences(v) {
let pos = expected
.iter()
.position(|&x| x == incidence)
.unwrap_or_else(|| {
panic!("unexpected incidence {incidence:?} of vertex {v:?} from iterator")
});
expected.swap_remove(pos);
}
assert!(
expected.is_empty(),
"expected incidences {expected:?} of vertex {v:?} were not matched by iterator"
);
}
}
pub fn incidences_edge_consistency<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, _, _, _) = G::standard();
for u in graph.vertices() {
for incidence in graph.incidences(u) {
if u == incidence.vertex {
assert_eq!(
graph
.incidences(u)
.filter(|x| x.edge == incidence.edge)
.count(),
2,
"loop edge {:?} should appear exactly twice in incidences of vertex {u:?}",
incidence.edge
);
} else {
assert!(
graph
.incidences(incidence.vertex)
.any(|x| x.vertex == u && x.edge == incidence.edge),
"edge {:?} from incidences of vertex {u:?} missing in incidences of \
adjacent vertex {:?}",
incidence.edge,
incidence.vertex
);
}
}
}
}
pub fn incidences_loop_edge<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, v, e) = G::loop_edge();
let mut iter = graph.incidences(v);
assert_eq!(
iter.next(),
Some(Incidence { vertex: v, edge: e }),
"vertex should be adjacent to itself"
);
assert_eq!(
iter.next(),
Some(Incidence { vertex: v, edge: e }),
"vertex should be adjacent to itself twice"
);
assert_eq!(
iter.next(),
None,
"too many adjacent vertices from iterator"
);
}
pub fn incidences_multiple_edges<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
const K: usize = 3;
let (graph, vertices, edges) = G::multiple_edges::<K>();
for (i, &v) in vertices.iter().enumerate() {
let mut iter = graph.incidences(v);
for j in 0..K {
let current = iter.next().unwrap_or_else(|| {
panic!("incidence {j} missing, expected {K} incidences for vertex {v:?}")
});
assert_eq!(
current.vertex,
vertices[1 - i],
"unexpected adjacent vertex of vertex {v:?} in incidence {j}"
);
assert_eq!(
edges.iter().filter(|&&e| e == current.edge).count(),
1,
"unexpected incident edge {:?} of vertex {v:?}",
current.edge
);
}
assert_eq!(
iter.next(),
None,
"too many adjacent vertices of {v:?} from iterator"
);
}
}
pub fn incidence_cursor_empty<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, v) = G::single_vertex();
let mut cursor = graph.incidence_cursor(v);
assert_eq!(
cursor.next(&graph),
None,
"incidence cursor of vertex with degree 0 should immediately be exhausted"
);
}
pub fn incidence_cursor<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, vertices, _, incidences) = G::standard();
assert_eq!(vertices.len(), incidences.len());
for (&v, incs) in vertices.iter().zip(&incidences) {
let mut expected = incs.clone();
let mut cursor = graph.incidence_cursor(v);
while let Some(incidence) = cursor.next(&graph) {
let pos = expected
.iter()
.position(|&x| x == incidence)
.unwrap_or_else(|| {
panic!("unexpected incidence {incidence:?} of vertex {v:?} from cursor")
});
expected.swap_remove(pos);
}
assert!(
expected.is_empty(),
"expected incidences {expected:?} of vertex {v:?} were not matched by cursor"
);
}
}
pub fn incidence_cursor_loop_edge<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, v, e) = G::loop_edge();
let mut cursor = graph.incidence_cursor(v);
assert_eq!(
cursor.next(&graph),
Some(Incidence { vertex: v, edge: e }),
"vertex should be adjacent to itself"
);
assert_eq!(
cursor.next(&graph),
Some(Incidence { vertex: v, edge: e }),
"vertex should be adjacent to itself twice"
);
assert_eq!(cursor.next(&graph), None, "too many incidences from cursor");
}
pub fn incidence_cursor_multiple_edges<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
const K: usize = 3;
let (graph, vertices, edges) = G::multiple_edges::<K>();
for (i, &v) in vertices.iter().enumerate() {
let mut cursor = graph.incidence_cursor(v);
for j in 0..K {
let current = cursor.next(&graph).unwrap_or_else(|| {
panic!("incidence {j} missing, expected {K} incidences for vertex {v:?}")
});
assert_eq!(
current.vertex,
vertices[1 - i],
"unexpected adjacent vertex of vertex {v:?} in incidence {j}"
);
assert_eq!(
edges.iter().filter(|&&e| e == current.edge).count(),
1,
"unexpected incident edge {:?} of vertex {v:?}",
current.edge
);
}
assert_eq!(
cursor.next(&graph),
None,
"too many incidences of {v:?} from cursor"
);
}
}
pub fn incidence_cursor_copy<G: MakeTestGraph>() {
let (graph, [_, v, _], _) = G::two_edge_path();
let mut c1 = graph.incidence_cursor(v);
assert!(c1.next(&graph).is_some(), "expected first incidence");
let mut c2 = c1;
assert!(
c1.next(&graph).is_some(),
"expected second incidence from original cursor"
);
assert!(
c1.next(&graph).is_none(),
"expected original cursor to be exhausted"
);
assert!(
c2.next(&graph).is_some(),
"expected second incidence from copied cursor"
);
assert!(
c2.next(&graph).is_none(),
"expected copied cursor to be exhausted"
);
}
pub fn incident_vertices_incidences_consistency<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, _, _, _) = G::standard();
for u in graph.vertices() {
for incidence in graph.incidences(u) {
let (w1, w2) = graph.incident_vertices(incidence.edge);
assert!(
(w1 == u && w2 == incidence.vertex) || (w1 == incidence.vertex && w2 == u),
"edge endpoints {w1:?} and {w2:?} are inconsistent with incidence \
({:?}, {:?}) of vertex {u:?}",
incidence.vertex,
incidence.edge
);
}
}
}
pub fn incident_edges_incidences_consistency<G: MakeTestGraph>()
where
G::Vertex: Debug,
G::Edge: Debug,
{
let (graph, _, _, _) = G::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) {
let pos = expected.iter().position(|&f| f == e).unwrap_or_else(|| {
panic!("incident edge {e:?} of vertex {u:?} missing from incidences")
});
expected.swap_remove(pos);
}
assert!(
expected.is_empty(),
"incidence edges {expected:?} of vertex {u:?} not matched by incident_edges"
);
}
}
pub fn common_neighbors<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, vertices, _, _) = G::standard();
// Pairs of vertex indices with the indices of their expected common neighbors.
let cases: [(usize, usize, &[usize]); _] = [
(0, 3, &[1]),
(1, 6, &[2, 3]),
(5, 8, &[]),
(2, 9, &[5, 6]),
(7, 3, &[]),
(0, 1, &[]),
(6, 7, &[9]),
// Loop only on one side, adjacent.
(2, 6, &[2]),
// Loop only on one side, not adjacent.
(2, 7, &[4]),
// Adjacent through a double edge, and both have a loop.
(2, 4, &[1, 2, 4]),
];
for (i, j, expected) in cases {
let expected: Vec<_> = expected.iter().map(|&k| vertices[k]).collect();
assert_common_neighbors(&graph, vertices[i], vertices[j], &expected);
}
}
pub fn common_neighbors_same_vertex<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, vertices, _, _) = G::standard();
// Vertex 1 has a double edge to vertex 0, but no loop.
assert_common_neighbors(
&graph,
vertices[1],
vertices[1],
&[vertices[0], vertices[2], vertices[3], vertices[4]],
);
// Vertex 4 has a loop, and is therefore its own common neighbor with itself.
assert_common_neighbors(
&graph,
vertices[4],
vertices[4],
&[
vertices[1],
vertices[2],
vertices[4],
vertices[7],
vertices[8],
],
);
}
pub fn common_neighbors_single<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, v) = G::single_vertex();
assert_common_neighbors(&graph, v, v, &[]);
}
pub fn common_neighbors_disconnected<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, v) = G::disconnected();
assert_common_neighbors(&graph, v[0], v[0], &[]);
assert_common_neighbors(&graph, v[0], v[1], &[]);
}
pub fn common_neighbors_multiple_edges<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, [v0, v1], _) = G::multiple_edges::<3>();
assert_common_neighbors(&graph, v0, v1, &[]);
assert_common_neighbors(&graph, v1, v1, &[v0]);
}
pub fn common_neighbors_loop_edge<G: MakeTestGraph>()
where
G::Vertex: Debug,
{
let (graph, v, _) = G::loop_edge();
assert_common_neighbors(&graph, v, v, &[v]);
}
/// Asserts that `u` and `v` have exactly the `expected` common neighbors, each yielded once, for
/// both argument orders.
fn assert_common_neighbors<G: MakeTestGraph>(
graph: &G,
u: G::Vertex,
v: G::Vertex,
expected: &[G::Vertex],
) where
G::Vertex: Debug,
{
for (a, b) in [(u, v), (v, u)] {
let mut remaining = expected.to_vec();
for w in graph.common_neighbors(a, b) {
let pos = remaining.iter().position(|&x| x == w).unwrap_or_else(|| {
panic!(
"unexpected or repeated common neighbor {w:?} of vertices {a:?} and {b:?} from iterator"
)
});
remaining.swap_remove(pos);
}
assert!(
remaining.is_empty(),
"expected common neighbors {remaining:?} of vertices {a:?} and {b:?} were not matched by iterator"
);
}
}