Refactor graph trait tests to minimize macro code, and split into separate files per macro
The tests only declare a list of tests in the macro, no longer the test functions themselves. This allows better tooling support (e.g. IDE and rustfmt).
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
//! Test fixture and test macros for graph topology and algorithm implementations.
|
||||
|
||||
pub mod fixtures;
|
||||
pub(crate) mod graph_topology_addition_deletion_testing;
|
||||
pub(crate) mod graph_topology_addition_testing;
|
||||
pub(crate) mod graph_topology_deletion_testing;
|
||||
pub(crate) mod graph_topology_testing;
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::testing::fixtures::MakeTestGraph;
|
||||
use crate::traits::{GraphTopologyAddition, GraphTopologyDeletion};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! graph_topology_addition_deletion_tests {
|
||||
($T:ty) => {
|
||||
$crate::graph_topology_addition_deletion_tests!(@wrap $T,
|
||||
delete_vertex_add_vertex,
|
||||
delete_edge_add_edge,
|
||||
);
|
||||
};
|
||||
|
||||
(@wrap $T:ty, $($name:ident),* $(,)?) => {
|
||||
$(
|
||||
#[test]
|
||||
fn $name() {
|
||||
$crate::testing::graph_topology_addition_deletion_testing::$name::<$T>();
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn delete_vertex_add_vertex<G: GraphTopologyDeletion + GraphTopologyAddition>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
{
|
||||
let (mut graph, v) = G::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"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn delete_edge_add_edge<G: GraphTopologyDeletion + GraphTopologyAddition>()
|
||||
where
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let (mut graph, vertices, e) = G::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");
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::traits::GraphTopologyAddition;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! graph_topology_addition_tests {
|
||||
($T:ty) => {
|
||||
$crate::graph_topology_addition_tests!(@wrap $T,
|
||||
reserve_vertices_increases_capacity,
|
||||
reserve_vertices_prevents_reallocation_on_add,
|
||||
reserve_vertices_does_not_affect_edge_capacity,
|
||||
reserve_edges_increases_capacity,
|
||||
reserve_edges_prevents_reallocation_on_add,
|
||||
reserve_edges_does_not_affect_vertex_capacity,
|
||||
add_vertex,
|
||||
add_edge,
|
||||
vertex_map_new_vertex,
|
||||
edge_map_new_edge,
|
||||
);
|
||||
};
|
||||
|
||||
(@wrap $T:ty, $($name:ident),* $(,)?) => {
|
||||
$(
|
||||
#[test]
|
||||
fn $name() {
|
||||
$crate::testing::graph_topology_addition_testing::$name::<$T>();
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn reserve_vertices_increases_capacity<G: GraphTopologyAddition>() {
|
||||
let mut graph = G::default();
|
||||
let capacity_before = graph.vertex_capacity();
|
||||
graph.reserve_vertices(capacity_before + 10);
|
||||
assert!(
|
||||
graph.vertex_capacity() > capacity_before,
|
||||
"expected sufficient capacity increase after reserve"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn reserve_vertices_prevents_reallocation_on_add<G: GraphTopologyAddition>() {
|
||||
let mut graph = G::default();
|
||||
graph.reserve_vertices(10);
|
||||
let capacity_before = graph.vertex_capacity();
|
||||
for _ in 0..10 {
|
||||
graph.add_vertex();
|
||||
}
|
||||
assert_eq!(
|
||||
graph.vertex_capacity(),
|
||||
capacity_before,
|
||||
"writes within reserved capacity should not reallocate"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn reserve_vertices_does_not_affect_edge_capacity<G: GraphTopologyAddition>() {
|
||||
let mut graph = G::default();
|
||||
let capacity_before = graph.edge_capacity();
|
||||
graph.reserve_vertices(10);
|
||||
assert_eq!(
|
||||
graph.edge_capacity(),
|
||||
capacity_before,
|
||||
"reserve_vertices must not change edge capacity"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn reserve_edges_increases_capacity<G: GraphTopologyAddition>() {
|
||||
let mut graph = G::default();
|
||||
let capacity_before = graph.edge_capacity();
|
||||
graph.reserve_edges(capacity_before + 10);
|
||||
assert!(
|
||||
graph.edge_capacity() > capacity_before,
|
||||
"expected sufficient capacity increase after reserve"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn reserve_edges_prevents_reallocation_on_add<G: GraphTopologyAddition>() {
|
||||
let mut graph = G::default();
|
||||
let v1 = graph.add_vertex();
|
||||
let v2 = graph.add_vertex();
|
||||
graph.reserve_edges(10);
|
||||
let capacity_before = graph.edge_capacity();
|
||||
for _ in 0..10 {
|
||||
graph.add_edge(v1, v2);
|
||||
}
|
||||
assert_eq!(
|
||||
graph.edge_capacity(),
|
||||
capacity_before,
|
||||
"writes within reserved capacity should not reallocate"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn reserve_edges_does_not_affect_vertex_capacity<G: GraphTopologyAddition>() {
|
||||
let mut graph = G::default();
|
||||
let capacity_before = graph.vertex_capacity();
|
||||
graph.reserve_edges(10);
|
||||
assert_eq!(
|
||||
graph.vertex_capacity(),
|
||||
capacity_before,
|
||||
"reserve_edges must not change vertex capacity"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn add_vertex<G: GraphTopologyAddition>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
{
|
||||
let mut graph = G::default();
|
||||
let v = graph.add_vertex();
|
||||
assert_ne!(graph.add_vertex(), v, "unexpected duplicate vertex");
|
||||
}
|
||||
|
||||
pub(crate) fn add_edge<G: GraphTopologyAddition>()
|
||||
where
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let mut graph = G::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");
|
||||
}
|
||||
|
||||
pub(crate) fn vertex_map_new_vertex<G: GraphTopologyAddition>() {
|
||||
let mut graph = G::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"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn edge_map_new_edge<G: GraphTopologyAddition>() {
|
||||
let mut graph = G::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"
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,542 @@
|
||||
use std::fmt::Debug;
|
||||
|
||||
use crate::testing::fixtures::MakeTestGraph;
|
||||
use crate::traits::{
|
||||
GraphTopology, GraphTopologyAddition, GraphTopologyDeletion, Incidence, IncidenceCursor,
|
||||
};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! graph_topology_deletion_tests {
|
||||
($T:ty) => {
|
||||
$crate::graph_topology_deletion_tests!(@wrap $T,
|
||||
delete_vertex,
|
||||
delete_vertex_loop,
|
||||
delete_vertex_invalid_index,
|
||||
delete_vertex_connected,
|
||||
delete_edge,
|
||||
delete_edge_loop,
|
||||
delete_edge_multiple,
|
||||
delete_edge_invalid_index,
|
||||
vertices_after_delete,
|
||||
incident_vertices_after_delete_edge,
|
||||
edges_after_delete,
|
||||
incident_edges_after_delete_edge,
|
||||
incident_edges_after_delete_vertex,
|
||||
incidences_after_delete_vertex,
|
||||
incidences_after_delete_edge,
|
||||
incidence_cursor_after_delete_vertex,
|
||||
incidence_cursor_after_delete_edge,
|
||||
);
|
||||
};
|
||||
|
||||
(@wrap $T:ty, $($name:ident),* $(,)?) => {
|
||||
$(
|
||||
#[test]
|
||||
fn $name() {
|
||||
$crate::testing::graph_topology_deletion_testing::$name::<$T>();
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) fn delete_vertex<G: GraphTopologyDeletion + GraphTopologyAddition>() {
|
||||
let (mut graph, v) = G::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"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn delete_vertex_loop<G: GraphTopologyDeletion + GraphTopologyAddition>() {
|
||||
let (mut graph, v, _) = G::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_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");
|
||||
}
|
||||
|
||||
pub(crate) fn delete_vertex_invalid_index<G: GraphTopologyDeletion + GraphTopologyAddition>() {
|
||||
let (mut graph, v) = G::single_vertex();
|
||||
graph.delete_vertex(v);
|
||||
let result =
|
||||
std::panic::catch_unwind(std::panic::AssertUnwindSafe(move || graph.delete_vertex(v)));
|
||||
assert!(result.is_err(), "second deletion should panic");
|
||||
}
|
||||
|
||||
pub(crate) fn delete_vertex_connected<G: GraphTopologyDeletion + GraphTopologyAddition>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
{
|
||||
let (mut graph, vertices, _, _) = G::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.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]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn delete_edge<G: GraphTopologyDeletion + GraphTopologyAddition>() {
|
||||
let (mut graph, vertices, e) = G::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(vertices[0], vertices[1]),
|
||||
"expected vertices to be adjacent 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.edge_count(), 0, "unexpected edge count after delete");
|
||||
assert!(
|
||||
!graph.are_adjacent(vertices[0], vertices[1]),
|
||||
"unexpected adjacency 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"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn delete_edge_loop<G: GraphTopologyDeletion + GraphTopologyAddition>() {
|
||||
let (mut graph, v, e) = G::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_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");
|
||||
}
|
||||
|
||||
pub(crate) fn delete_edge_multiple<G: GraphTopologyDeletion + GraphTopologyAddition>() {
|
||||
const K: usize = 2;
|
||||
let (mut graph, vertices, edges) = G::multiple_edges::<K>();
|
||||
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(vertices[0], vertices[1]),
|
||||
"expected vertices to be adjacent before 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(vertices[0], vertices[1]),
|
||||
"expected vertices to be adjacent 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"
|
||||
);
|
||||
}
|
||||
|
||||
pub(crate) fn delete_edge_invalid_index<G: GraphTopologyDeletion + GraphTopologyAddition>() {
|
||||
let (mut graph, _, e) = G::single_edge();
|
||||
graph.delete_edge(e);
|
||||
let result =
|
||||
std::panic::catch_unwind(std::panic::AssertUnwindSafe(move || graph.delete_edge(e)));
|
||||
assert!(result.is_err(), "second deletion should panic");
|
||||
}
|
||||
|
||||
pub(crate) fn vertices_after_delete<G: GraphTopologyDeletion + GraphTopologyAddition>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
{
|
||||
let (mut graph, vertices, _, _) = G::standard();
|
||||
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]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn incident_vertices_after_delete_edge<
|
||||
G: GraphTopologyDeletion + GraphTopologyAddition,
|
||||
>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let (mut graph, _, edges, _) = G::standard();
|
||||
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"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn edges_after_delete<G: GraphTopologyDeletion + GraphTopologyAddition>()
|
||||
where
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let (mut graph, vertices, edges, _) = G::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"
|
||||
);
|
||||
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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn incident_edges_after_delete_edge<G: GraphTopologyDeletion + GraphTopologyAddition>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let (mut graph, vertices, edges, incidences) = G::standard();
|
||||
graph.delete_edge(edges[2].0);
|
||||
for i in 0..10 {
|
||||
let mut expected: Vec<_> = incidences[i]
|
||||
.iter()
|
||||
.filter_map(|x| (x.edge != edges[2].0).then_some(x.edge))
|
||||
.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]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn incident_edges_after_delete_vertex<G: GraphTopologyDeletion + GraphTopologyAddition>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let (mut graph, vertices, _, incidences) = G::standard();
|
||||
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_map(|x| (x.vertex != vertices[2]).then_some(x.edge))
|
||||
.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]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn incidences_after_delete_vertex<G: GraphTopologyDeletion + GraphTopologyAddition>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let (mut graph, vertices, _, incidences) = G::standard();
|
||||
graph.delete_vertex(vertices[2]);
|
||||
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
||||
let remaining = incidences[i]
|
||||
.iter()
|
||||
.filter(|x| x.vertex != vertices[2])
|
||||
.cloned()
|
||||
.collect();
|
||||
assert_vertex_incidences(&graph, vertices[i], remaining);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn incidences_after_delete_edge<G: GraphTopologyDeletion + GraphTopologyAddition>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let (mut graph, vertices, edges, incidences) = G::standard();
|
||||
graph.delete_edge(edges[2].0);
|
||||
for i in 0..10 {
|
||||
let remaining = incidences[i]
|
||||
.iter()
|
||||
.filter(|x| x.edge != edges[2].0)
|
||||
.cloned()
|
||||
.collect();
|
||||
assert_vertex_incidences(&graph, vertices[i], remaining);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn incidence_cursor_after_delete_vertex<
|
||||
G: GraphTopologyDeletion + GraphTopologyAddition,
|
||||
>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let (mut graph, vertices, _, incidences) = G::standard();
|
||||
graph.delete_vertex(vertices[2]);
|
||||
for i in [0, 1, 3, 4, 5, 6, 7, 8, 9] {
|
||||
let remaining = incidences[i]
|
||||
.iter()
|
||||
.filter(|x| x.vertex != vertices[2])
|
||||
.cloned()
|
||||
.collect();
|
||||
assert_vertex_incidence_cursor(&graph, vertices[i], remaining);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn incidence_cursor_after_delete_edge<G: GraphTopologyDeletion + GraphTopologyAddition>()
|
||||
where
|
||||
G::Vertex: Debug,
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let (mut graph, vertices, edges, incidences) = G::standard();
|
||||
graph.delete_edge(edges[2].0);
|
||||
for i in 0..10 {
|
||||
let remaining = incidences[i]
|
||||
.iter()
|
||||
.filter(|x| x.edge != edges[2].0)
|
||||
.cloned()
|
||||
.collect();
|
||||
assert_vertex_incidence_cursor(&graph, vertices[i], remaining);
|
||||
}
|
||||
}
|
||||
|
||||
fn assert_vertex_incidences<G: GraphTopology>(
|
||||
graph: &G,
|
||||
v: G::Vertex,
|
||||
mut expected: Vec<Incidence<G::Vertex, G::Edge>>,
|
||||
) where
|
||||
G::Vertex: Debug,
|
||||
G::Edge: Debug,
|
||||
{
|
||||
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(|x| *x == incidence)
|
||||
.expect(&format!(
|
||||
"unexpected incidence {incidence:?} of vertex {:?} from iterator after delete",
|
||||
v
|
||||
));
|
||||
expected.swap_remove(pos);
|
||||
}
|
||||
assert!(
|
||||
expected.is_empty(),
|
||||
"expected incidences {:?} of vertex {:?} not matched by iterator after delete",
|
||||
expected,
|
||||
v
|
||||
);
|
||||
}
|
||||
|
||||
fn assert_vertex_incidence_cursor<G: GraphTopology>(
|
||||
graph: &G,
|
||||
v: G::Vertex,
|
||||
mut expected: Vec<Incidence<G::Vertex, G::Edge>>,
|
||||
) where
|
||||
G::Vertex: Debug,
|
||||
G::Edge: Debug,
|
||||
{
|
||||
let mut cursor = graph.incidence_cursor(v);
|
||||
while let Some(incidence) = cursor.next(graph) {
|
||||
let pos = expected
|
||||
.iter()
|
||||
.position(|x| *x == incidence)
|
||||
.expect(&format!(
|
||||
"unexpected incidence {incidence:?} of vertex {:?} from cursor after delete",
|
||||
v
|
||||
));
|
||||
expected.swap_remove(pos);
|
||||
}
|
||||
assert!(
|
||||
expected.is_empty(),
|
||||
"expected incidences {:?} of vertex {:?} not matched by cursor after delete",
|
||||
expected,
|
||||
v
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user