Extract asserts from Clone tests to be reusable
This commit is contained in:
@@ -338,3 +338,143 @@ where
|
|||||||
}
|
}
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Asserts that the two graphs are isomorphic.
|
||||||
|
///
|
||||||
|
/// `vertices` must contain all vertices of the `original` graph, and `vertex_map` must for any
|
||||||
|
/// vertex in the `original` graph return the corresponding vertex in the `other` graph.
|
||||||
|
///
|
||||||
|
/// `edges` must contain all edges and their endpoints of the `original` graph, and `edge_map` must
|
||||||
|
/// for any edge in the `original` graph return the corresponding edge in the `other` graph.
|
||||||
|
pub fn assert_isomorphic<G: GraphTopology, H: GraphTopology>(
|
||||||
|
original: &G,
|
||||||
|
other: &H,
|
||||||
|
vertices: &[G::Vertex],
|
||||||
|
vertex_map: impl Fn(G::Vertex) -> H::Vertex,
|
||||||
|
edges: &[(G::Edge, G::Vertex, G::Vertex)],
|
||||||
|
edge_map: impl Fn(G::Edge) -> H::Edge,
|
||||||
|
) where
|
||||||
|
G::Vertex: Debug,
|
||||||
|
G::Edge: Debug,
|
||||||
|
H::Vertex: Debug,
|
||||||
|
H::Edge: Debug,
|
||||||
|
{
|
||||||
|
assert_eq!(
|
||||||
|
original.vertex_count(),
|
||||||
|
vertices.len(),
|
||||||
|
"precondition: all vertices of the original must be provided"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
original.edge_count(),
|
||||||
|
edges.len(),
|
||||||
|
"precondition: all edges of the original must be provided"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
other.vertex_count(),
|
||||||
|
original.vertex_count(),
|
||||||
|
"other graph should have the same vertex count as the original"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
other.edge_count(),
|
||||||
|
original.edge_count(),
|
||||||
|
"other graph should have the same edge count as the original"
|
||||||
|
);
|
||||||
|
for &v in vertices.iter() {
|
||||||
|
assert_eq!(
|
||||||
|
other.degree(vertex_map(v)),
|
||||||
|
original.degree(v),
|
||||||
|
"vertex {v:?} should have the same degree in the other graph as in the original"
|
||||||
|
);
|
||||||
|
let mut expected: Vec<_> = original.incidences(v).collect();
|
||||||
|
for incidence in other.incidences(vertex_map(v)) {
|
||||||
|
let pos = expected
|
||||||
|
.iter()
|
||||||
|
.position(|x| {
|
||||||
|
vertex_map(x.vertex) == incidence.vertex && edge_map(x.edge) == incidence.edge
|
||||||
|
})
|
||||||
|
.expect(&format!(
|
||||||
|
"unexpected incidence {incidence:?} of vertex {v:?} in the other graph"
|
||||||
|
));
|
||||||
|
expected.swap_remove(pos);
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
expected.is_empty(),
|
||||||
|
"expected incidences {expected:?} of vertex {v:?} are missing in the other graph"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for &(e, u, v) in edges.iter() {
|
||||||
|
assert_eq!(
|
||||||
|
other.incident_vertices(edge_map(e)),
|
||||||
|
(vertex_map(u), vertex_map(v)),
|
||||||
|
"edge {e:?} should have the same incident vertices in the other graph as in the original"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Asserts that mutation of the two graphs happens independently.
|
||||||
|
///
|
||||||
|
/// `vertices` must contain all vertices of the `original` graph, which must not be empty, and
|
||||||
|
/// `vertex_map` must for any vertex in the `original` graph return the corresponding vertex in the
|
||||||
|
/// `other` graph.
|
||||||
|
pub fn assert_mutation_independent<G: GraphTopologyAddition, H: GraphTopologyAddition>(
|
||||||
|
original: &mut G,
|
||||||
|
other: &mut H,
|
||||||
|
vertices: &[G::Vertex],
|
||||||
|
vertex_map: impl Fn(G::Vertex) -> H::Vertex,
|
||||||
|
) {
|
||||||
|
let edge_count = original.edge_count();
|
||||||
|
assert_eq!(
|
||||||
|
original.vertex_count(),
|
||||||
|
vertices.len(),
|
||||||
|
"precondition: all vertices of the original must be provided"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!vertices.is_empty(),
|
||||||
|
"precondition: at least one vertex must be provided"
|
||||||
|
);
|
||||||
|
let u = other.add_vertex();
|
||||||
|
other.add_edge(vertex_map(vertices[0]), u);
|
||||||
|
assert_eq!(
|
||||||
|
other.vertex_count(),
|
||||||
|
vertices.len() + 1,
|
||||||
|
"precondition: vertex count of other graph"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
other.edge_count(),
|
||||||
|
edge_count + 1,
|
||||||
|
"precondition: edge count of other graph"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
original.vertex_count(),
|
||||||
|
vertices.len(),
|
||||||
|
"mutating the other graph should not affect the vertex count of the original"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
original.edge_count(),
|
||||||
|
edge_count,
|
||||||
|
"mutating the other graph should not affect the edge count of the original"
|
||||||
|
);
|
||||||
|
|
||||||
|
let v = original.add_vertex();
|
||||||
|
original.add_edge(vertices[0], v);
|
||||||
|
assert_eq!(
|
||||||
|
original.vertex_count(),
|
||||||
|
vertices.len() + 1,
|
||||||
|
"precondition: vertex count of original"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
original.edge_count(),
|
||||||
|
edge_count + 1,
|
||||||
|
"precondition: edge count of original"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
other.vertex_count(),
|
||||||
|
vertices.len() + 1,
|
||||||
|
"mutating the original should not affect the vertex count of the other graph"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
other.edge_count(),
|
||||||
|
edge_count + 1,
|
||||||
|
"mutating the original should not affect the edge count of the other graph"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::testing::fixtures;
|
||||||
use crate::testing::fixtures::MakeTestGraph;
|
use crate::testing::fixtures::MakeTestGraph;
|
||||||
use crate::traits::GraphTopologyAddition;
|
use crate::traits::GraphTopologyAddition;
|
||||||
|
|
||||||
@@ -6,7 +7,7 @@ use crate::traits::GraphTopologyAddition;
|
|||||||
macro_rules! graph_topology_addition_clone_tests {
|
macro_rules! graph_topology_addition_clone_tests {
|
||||||
($T:ty) => {
|
($T:ty) => {
|
||||||
$crate::graph_topology_addition_clone_tests!(@wrap $T,
|
$crate::graph_topology_addition_clone_tests!(@wrap $T,
|
||||||
clone_independent,
|
clone_mutation_independent,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -20,37 +21,8 @@ macro_rules! graph_topology_addition_clone_tests {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone_independent<G: Clone + GraphTopologyAddition>() {
|
pub fn clone_mutation_independent<G: Clone + GraphTopologyAddition>() {
|
||||||
let (mut graph, [u, v], _) = G::single_edge();
|
let (mut graph, vertices, _) = G::single_edge();
|
||||||
let mut clone = graph.clone();
|
let mut clone = graph.clone();
|
||||||
|
fixtures::assert_mutation_independent(&mut graph, &mut clone, &vertices, |v| v);
|
||||||
let w = clone.add_vertex();
|
|
||||||
clone.add_edge(u, w);
|
|
||||||
assert_eq!(clone.vertex_count(), 3, "precondition: vertex count of clone");
|
|
||||||
assert_eq!(clone.edge_count(), 2, "precondition: edge count of clone");
|
|
||||||
assert_eq!(
|
|
||||||
graph.vertex_count(),
|
|
||||||
2,
|
|
||||||
"mutating the clone should not affect the vertex count of the original"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
graph.edge_count(),
|
|
||||||
1,
|
|
||||||
"mutating the clone should not affect the edge count of the original"
|
|
||||||
);
|
|
||||||
|
|
||||||
let x = graph.add_vertex();
|
|
||||||
graph.add_edge(v, x);
|
|
||||||
assert_eq!(graph.vertex_count(), 3, "precondition: vertex count of original");
|
|
||||||
assert_eq!(graph.edge_count(), 2, "precondition: edge count of original");
|
|
||||||
assert_eq!(
|
|
||||||
clone.vertex_count(),
|
|
||||||
3,
|
|
||||||
"mutating the original should not affect the vertex count of the clone"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
clone.edge_count(),
|
|
||||||
2,
|
|
||||||
"mutating the original should not affect the edge count of the clone"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
use crate::testing::fixtures;
|
||||||
use crate::testing::fixtures::MakeTestGraph;
|
use crate::testing::fixtures::MakeTestGraph;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@@ -7,7 +8,6 @@ use crate::testing::fixtures::MakeTestGraph;
|
|||||||
macro_rules! graph_topology_clone_tests {
|
macro_rules! graph_topology_clone_tests {
|
||||||
($T:ty) => {
|
($T:ty) => {
|
||||||
$crate::graph_topology_clone_tests!(@wrap $T,
|
$crate::graph_topology_clone_tests!(@wrap $T,
|
||||||
clone_preserves_vertex_and_edge_count,
|
|
||||||
clone_handles_interchangeable,
|
clone_handles_interchangeable,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -22,21 +22,6 @@ macro_rules! graph_topology_clone_tests {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clone_preserves_vertex_and_edge_count<G: Clone + MakeTestGraph>() {
|
|
||||||
let (graph, ..) = G::standard();
|
|
||||||
let clone = graph.clone();
|
|
||||||
assert_eq!(
|
|
||||||
clone.vertex_count(),
|
|
||||||
graph.vertex_count(),
|
|
||||||
"clone should have the same vertex count as the original"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
clone.edge_count(),
|
|
||||||
graph.edge_count(),
|
|
||||||
"clone should have the same edge count as the original"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Queries the clone using vertex and edge handles obtained from the original graph, and asserts
|
/// Queries the clone using vertex and edge handles obtained from the original graph, and asserts
|
||||||
/// that the results are identical to querying the original with those same handles. This is only
|
/// that the results are identical to querying the original with those same handles. This is only
|
||||||
/// meaningful because Vertex and Edge handles are not tied to a particular graph instance.
|
/// meaningful because Vertex and Edge handles are not tied to a particular graph instance.
|
||||||
@@ -47,32 +32,5 @@ where
|
|||||||
{
|
{
|
||||||
let (graph, vertices, edges, _) = G::standard();
|
let (graph, vertices, edges, _) = G::standard();
|
||||||
let clone = graph.clone();
|
let clone = graph.clone();
|
||||||
for &v in vertices.iter() {
|
fixtures::assert_isomorphic(&graph, &clone, &vertices, |v| v, &edges, |e| e);
|
||||||
assert_eq!(
|
|
||||||
clone.degree(v),
|
|
||||||
graph.degree(v),
|
|
||||||
"vertex {v:?} should have the same degree in the clone as in the original"
|
|
||||||
);
|
|
||||||
let mut expected: Vec<_> = graph.incidences(v).collect();
|
|
||||||
for incidence in clone.incidences(v) {
|
|
||||||
let pos = expected
|
|
||||||
.iter()
|
|
||||||
.position(|x| *x == incidence)
|
|
||||||
.expect(&format!(
|
|
||||||
"unexpected incidence {incidence:?} of vertex {v:?} in the clone"
|
|
||||||
));
|
|
||||||
expected.swap_remove(pos);
|
|
||||||
}
|
|
||||||
assert!(
|
|
||||||
expected.is_empty(),
|
|
||||||
"expected incidences {expected:?} of vertex {v:?} are missing in the clone"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
for &(e, u, v) in edges.iter() {
|
|
||||||
assert_eq!(
|
|
||||||
clone.incident_vertices(e),
|
|
||||||
(u, v),
|
|
||||||
"edge {e:?} should have the same incident vertices in the clone as in the original"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user