Add graph topology test helper macros to deduplicate test code
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
pub mod algorithms;
|
pub mod algorithms;
|
||||||
pub mod models;
|
pub mod models;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
|
|
||||||
|
mod testing;
|
||||||
|
|||||||
+2
-272
@@ -121,276 +121,6 @@ impl GraphTopology for AppendGraph {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
crate::graph_topology_test_fixtures!(AppendGraph);
|
||||||
fn add_vertex() {
|
crate::graph_topology_tests!(AppendGraph);
|
||||||
let mut graph = AppendGraph::new();
|
|
||||||
let v = graph.add_vertex();
|
|
||||||
assert_ne!(graph.add_vertex(), v, "unexpected duplicate vertex");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn vertex_count_empty() {
|
|
||||||
let graph = AppendGraph::new();
|
|
||||||
assert_eq!(graph.vertex_count(), 0, "unexpected vertex count");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn vertex_count() {
|
|
||||||
let (graph, _) = make_test_graph();
|
|
||||||
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn add_edge() {
|
|
||||||
let mut graph = AppendGraph::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() {
|
|
||||||
let graph = AppendGraph::new();
|
|
||||||
assert_eq!(graph.edge_count(), 0, "unexpected edge count");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn edge_count() {
|
|
||||||
let (graph, _) = make_test_graph();
|
|
||||||
assert_eq!(graph.edge_count(), 14, "unexpected edge count");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn degree_zero() {
|
|
||||||
let mut graph = AppendGraph::new();
|
|
||||||
let v = graph.add_vertex();
|
|
||||||
assert_eq!(graph.degree(v), 0, "unexpected non-zero degree");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn degree() {
|
|
||||||
let (graph, vertices) = make_test_graph();
|
|
||||||
let expected_degrees = [1, 4, 4, 2, 4, 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 are_adjacent_vertex_self() {
|
|
||||||
let mut graph = AppendGraph::new();
|
|
||||||
let v = graph.add_vertex();
|
|
||||||
assert!(
|
|
||||||
!graph.are_adjacent(v, v),
|
|
||||||
"should not be adjacent to itself"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn are_adjacent_single_edge() {
|
|
||||||
let mut graph = AppendGraph::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() {
|
|
||||||
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 {
|
|
||||||
2 => continue,
|
|
||||||
1 | 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() {
|
|
||||||
let graph = AppendGraph::new();
|
|
||||||
assert_eq!(
|
|
||||||
graph.vertices().count(),
|
|
||||||
0,
|
|
||||||
"vertex iterator of empty graph should have no elements"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn vertices() {
|
|
||||||
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 neighbors_empty() {
|
|
||||||
let mut graph = AppendGraph::new();
|
|
||||||
let vertex = graph.add_vertex();
|
|
||||||
assert_eq!(
|
|
||||||
graph.neighbors(vertex).count(),
|
|
||||||
0,
|
|
||||||
"neighbor iterator of vertex with degree 0 should have no elements"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn neighbors() {
|
|
||||||
let (graph, vertices) = make_test_graph();
|
|
||||||
// Checks neighbors of vertex 4.
|
|
||||||
assert_eq!(
|
|
||||||
graph.neighbors(vertices[4]).count(),
|
|
||||||
4,
|
|
||||||
"unexpected neighbor count"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Expects each neighbor to appear exactly once. This will not work if there are multiple edges.
|
|
||||||
let neighbors = vec![vertices[1], vertices[2], vertices[7], vertices[8]];
|
|
||||||
for v in graph.neighbors(vertices[4]) {
|
|
||||||
assert_eq!(
|
|
||||||
neighbors.iter().filter(|&x| *x == v).count(),
|
|
||||||
1,
|
|
||||||
"unexpected neighbor {v:?} of {:?} from the iterator",
|
|
||||||
vertices[4]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn loop_edge() {
|
|
||||||
let mut graph = AppendGraph::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"
|
|
||||||
);
|
|
||||||
let mut neighbors = graph.neighbors(v);
|
|
||||||
assert_eq!(
|
|
||||||
neighbors.next(),
|
|
||||||
Some(v),
|
|
||||||
"vertex should be neighbor of itself"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
neighbors.next(),
|
|
||||||
Some(v),
|
|
||||||
"vertex should be neighbor of itself twice"
|
|
||||||
);
|
|
||||||
assert_eq!(neighbors.next(), None, "too many neighbors from iterator");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn multiple_edges() {
|
|
||||||
let k = 3;
|
|
||||||
let mut graph = AppendGraph::new();
|
|
||||||
let vertices = [graph.add_vertex(), graph.add_vertex()];
|
|
||||||
for _ in 0..k {
|
|
||||||
graph.add_edge(vertices[0], vertices[1]);
|
|
||||||
}
|
|
||||||
assert_eq!(
|
|
||||||
graph.vertex_count(),
|
|
||||||
vertices.len(),
|
|
||||||
"unexpected vertex count"
|
|
||||||
);
|
|
||||||
assert_eq!(graph.edge_count(), k, "unexpected edge count");
|
|
||||||
for v in vertices {
|
|
||||||
assert_eq!(graph.degree(v), k, "unexpected degree of {v:?}");
|
|
||||||
}
|
|
||||||
assert!(
|
|
||||||
graph.are_adjacent(vertices[0], vertices[1]),
|
|
||||||
"should be adjacent"
|
|
||||||
);
|
|
||||||
for i in 0..2 {
|
|
||||||
let mut neighbors = graph.neighbors(vertices[i]);
|
|
||||||
for j in 0..k {
|
|
||||||
assert_eq!(
|
|
||||||
neighbors.next(),
|
|
||||||
Some(vertices[1 - i]),
|
|
||||||
"neighbor {j} of vertex {:?} should be {:?}",
|
|
||||||
vertices[i],
|
|
||||||
vertices[1 - i]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
assert_eq!(
|
|
||||||
neighbors.next(),
|
|
||||||
None,
|
|
||||||
"too many neighbors of {:?} from iterator",
|
|
||||||
vertices[i]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_test_graph() -> (AppendGraph, [Vertex; 10]) {
|
|
||||||
let mut graph = AppendGraph::new();
|
|
||||||
let vertices: [Vertex; 10] = core::array::from_fn(|_| graph.add_vertex());
|
|
||||||
graph.add_edge(vertices[0], vertices[1]);
|
|
||||||
graph.add_edge(vertices[1], vertices[2]);
|
|
||||||
graph.add_edge(vertices[1], vertices[3]);
|
|
||||||
graph.add_edge(vertices[1], vertices[4]);
|
|
||||||
graph.add_edge(vertices[2], vertices[4]);
|
|
||||||
graph.add_edge(vertices[2], vertices[5]);
|
|
||||||
graph.add_edge(vertices[2], vertices[6]);
|
|
||||||
graph.add_edge(vertices[3], vertices[6]);
|
|
||||||
graph.add_edge(vertices[4], vertices[7]);
|
|
||||||
graph.add_edge(vertices[4], vertices[8]);
|
|
||||||
graph.add_edge(vertices[5], vertices[9]);
|
|
||||||
graph.add_edge(vertices[6], vertices[9]);
|
|
||||||
graph.add_edge(vertices[7], vertices[8]);
|
|
||||||
graph.add_edge(vertices[7], vertices[9]);
|
|
||||||
(graph, vertices)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-519
@@ -112,7 +112,7 @@ impl Graph {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Updates the source vertex incidence list after the incidence "e" was deleted from the
|
// Updates the source vertex incidence list after the incidence "e" was deleted from the
|
||||||
// incidences arena. "next" is the next incidence after "e" in the source vertex incidence list.
|
// incidence arena. "next" is the next incidence after "e" in the source vertex incidence list.
|
||||||
fn update_incidence_list(
|
fn update_incidence_list(
|
||||||
&mut self,
|
&mut self,
|
||||||
e: Edge,
|
e: Edge,
|
||||||
@@ -237,494 +237,9 @@ impl GraphTopologyDeletion for Graph {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
crate::graph_topology_test_fixtures!(Graph);
|
||||||
fn add_vertex() {
|
crate::graph_topology_tests!(Graph);
|
||||||
let mut graph = Graph::new();
|
crate::graph_topology_deletion_tests!(Graph);
|
||||||
let v = graph.add_vertex();
|
|
||||||
assert_ne!(graph.add_vertex(), v, "unexpected duplicate vertex");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn vertex_count_empty() {
|
|
||||||
let graph = Graph::new();
|
|
||||||
assert_eq!(graph.vertex_count(), 0, "unexpected vertex count");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn vertex_count() {
|
|
||||||
let (graph, _) = make_test_graph();
|
|
||||||
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn add_edge() {
|
|
||||||
let mut graph = Graph::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() {
|
|
||||||
let graph = Graph::new();
|
|
||||||
assert_eq!(graph.edge_count(), 0, "unexpected edge count");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn edge_count() {
|
|
||||||
let (graph, _) = make_test_graph();
|
|
||||||
assert_eq!(graph.edge_count(), 14, "unexpected edge count");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn degree_zero() {
|
|
||||||
let mut graph = Graph::new();
|
|
||||||
let v = graph.add_vertex();
|
|
||||||
assert_eq!(graph.degree(v), 0, "unexpected non-zero degree");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn degree() {
|
|
||||||
let (graph, vertices) = make_test_graph();
|
|
||||||
let expected_degrees = [1, 4, 4, 2, 4, 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 are_adjacent_vertex_self() {
|
|
||||||
let mut graph = Graph::new();
|
|
||||||
let v = graph.add_vertex();
|
|
||||||
assert!(
|
|
||||||
!graph.are_adjacent(v, v),
|
|
||||||
"should not be adjacent to itself"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn are_adjacent_single_edge() {
|
|
||||||
let mut graph = Graph::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() {
|
|
||||||
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 {
|
|
||||||
2 => continue,
|
|
||||||
1 | 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() {
|
|
||||||
let graph = Graph::new();
|
|
||||||
assert_eq!(
|
|
||||||
graph.vertices().count(),
|
|
||||||
0,
|
|
||||||
"vertex iterator of empty graph should have no elements"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn vertices() {
|
|
||||||
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 neighbors_empty() {
|
|
||||||
let mut graph = Graph::new();
|
|
||||||
let vertex = graph.add_vertex();
|
|
||||||
assert_eq!(
|
|
||||||
graph.neighbors(vertex).count(),
|
|
||||||
0,
|
|
||||||
"neighbor iterator of vertex with degree 0 should have no elements"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn neighbors() {
|
|
||||||
let (graph, vertices) = make_test_graph();
|
|
||||||
// Checks neighbors of vertex 4.
|
|
||||||
assert_eq!(
|
|
||||||
graph.neighbors(vertices[4]).count(),
|
|
||||||
4,
|
|
||||||
"unexpected neighbor count"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Expects each neighbor to appear exactly once. This will not work if there are multiple edges.
|
|
||||||
let neighbors = vec![vertices[1], vertices[2], vertices[7], vertices[8]];
|
|
||||||
for v in graph.neighbors(vertices[4]) {
|
|
||||||
assert_eq!(
|
|
||||||
neighbors.iter().filter(|&x| *x == v).count(),
|
|
||||||
1,
|
|
||||||
"unexpected neighbor {v:?} of {:?} from the iterator",
|
|
||||||
vertices[4]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn loop_edge() {
|
|
||||||
let mut graph = Graph::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"
|
|
||||||
);
|
|
||||||
let mut neighbors = graph.neighbors(v);
|
|
||||||
assert_eq!(
|
|
||||||
neighbors.next(),
|
|
||||||
Some(v),
|
|
||||||
"vertex should be neighbor of itself"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
neighbors.next(),
|
|
||||||
Some(v),
|
|
||||||
"vertex should be neighbor of itself twice"
|
|
||||||
);
|
|
||||||
assert_eq!(neighbors.next(), None, "too many neighbors from iterator");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn multiple_edges() {
|
|
||||||
let k = 3;
|
|
||||||
let mut graph = Graph::new();
|
|
||||||
let vertices = [graph.add_vertex(), graph.add_vertex()];
|
|
||||||
for _ in 0..k {
|
|
||||||
graph.add_edge(vertices[0], vertices[1]);
|
|
||||||
}
|
|
||||||
assert_eq!(
|
|
||||||
graph.vertex_count(),
|
|
||||||
vertices.len(),
|
|
||||||
"unexpected vertex count"
|
|
||||||
);
|
|
||||||
assert_eq!(graph.edge_count(), k, "unexpected edge count");
|
|
||||||
for v in vertices {
|
|
||||||
assert_eq!(graph.degree(v), k, "unexpected degree of {v:?}");
|
|
||||||
}
|
|
||||||
assert!(
|
|
||||||
graph.are_adjacent(vertices[0], vertices[1]),
|
|
||||||
"should be adjacent"
|
|
||||||
);
|
|
||||||
for i in 0..2 {
|
|
||||||
let mut neighbors = graph.neighbors(vertices[i]);
|
|
||||||
for j in 0..k {
|
|
||||||
assert_eq!(
|
|
||||||
neighbors.next(),
|
|
||||||
Some(vertices[1 - i]),
|
|
||||||
"neighbor {j} of vertex {:?} should be {:?}",
|
|
||||||
vertices[i],
|
|
||||||
vertices[1 - i]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
assert_eq!(
|
|
||||||
neighbors.next(),
|
|
||||||
None,
|
|
||||||
"too many neighbors of {:?} from iterator",
|
|
||||||
vertices[i]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn delete_vertex() {
|
|
||||||
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() {
|
|
||||||
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() {
|
|
||||||
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() {
|
|
||||||
let (mut graph, vertices) = make_test_graph();
|
|
||||||
assert_eq!(
|
|
||||||
graph.vertex_count(),
|
|
||||||
10,
|
|
||||||
"unexpected vertex count before delete"
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
graph.edge_count(),
|
|
||||||
14,
|
|
||||||
"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(), 10, "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[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.neighbors(v).any(|u| u == vertices[2]),
|
|
||||||
"unexpected adjacency of {v:?} to deleted vertex {:?}",
|
|
||||||
vertices[2]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn delete_edge() {
|
|
||||||
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() {
|
|
||||||
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() {
|
|
||||||
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]
|
#[test]
|
||||||
fn delete_edge_paired_index() {
|
fn delete_edge_paired_index() {
|
||||||
@@ -753,34 +268,4 @@ mod tests {
|
|||||||
assert_eq!(graph.edge_count(), 0, "unexpected edge count after delete");
|
assert_eq!(graph.edge_count(), 0, "unexpected edge count after delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn delete_edge_invalid_index() {
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_test_graph() -> (Graph, [Vertex; 10]) {
|
|
||||||
let mut graph = Graph::new();
|
|
||||||
let vertices: [Vertex; 10] = core::array::from_fn(|_| graph.add_vertex());
|
|
||||||
graph.add_edge(vertices[0], vertices[1]);
|
|
||||||
graph.add_edge(vertices[1], vertices[2]);
|
|
||||||
graph.add_edge(vertices[1], vertices[3]);
|
|
||||||
graph.add_edge(vertices[1], vertices[4]);
|
|
||||||
graph.add_edge(vertices[2], vertices[4]);
|
|
||||||
graph.add_edge(vertices[2], vertices[5]);
|
|
||||||
graph.add_edge(vertices[2], vertices[6]);
|
|
||||||
graph.add_edge(vertices[3], vertices[6]);
|
|
||||||
graph.add_edge(vertices[4], vertices[7]);
|
|
||||||
graph.add_edge(vertices[4], vertices[8]);
|
|
||||||
graph.add_edge(vertices[5], vertices[9]);
|
|
||||||
graph.add_edge(vertices[6], vertices[9]);
|
|
||||||
graph.add_edge(vertices[7], vertices[8]);
|
|
||||||
graph.add_edge(vertices[7], vertices[9]);
|
|
||||||
(graph, vertices)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
pub(crate) mod graph_topology_testing;
|
||||||
@@ -0,0 +1,538 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! graph_topology_test_fixtures {
|
||||||
|
($T:ty) => {
|
||||||
|
fn make_test_graph() -> ($T, [<$T as $crate::traits::GraphTopology>::Vertex; 10]) {
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let vertices: [<$T as $crate::traits::GraphTopology>::Vertex; 10] =
|
||||||
|
core::array::from_fn(|_| graph.add_vertex());
|
||||||
|
graph.add_edge(vertices[0], vertices[1]);
|
||||||
|
graph.add_edge(vertices[1], vertices[2]);
|
||||||
|
graph.add_edge(vertices[1], vertices[3]);
|
||||||
|
graph.add_edge(vertices[1], vertices[4]);
|
||||||
|
graph.add_edge(vertices[2], vertices[4]);
|
||||||
|
graph.add_edge(vertices[2], vertices[5]);
|
||||||
|
graph.add_edge(vertices[2], vertices[6]);
|
||||||
|
graph.add_edge(vertices[3], vertices[6]);
|
||||||
|
graph.add_edge(vertices[4], vertices[7]);
|
||||||
|
graph.add_edge(vertices[4], vertices[8]);
|
||||||
|
graph.add_edge(vertices[5], vertices[9]);
|
||||||
|
graph.add_edge(vertices[6], vertices[9]);
|
||||||
|
graph.add_edge(vertices[7], vertices[8]);
|
||||||
|
graph.add_edge(vertices[7], vertices[9]);
|
||||||
|
(graph, vertices)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! graph_topology_tests {
|
||||||
|
($T:ty) => {
|
||||||
|
#[test]
|
||||||
|
fn add_vertex() {
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let v = graph.add_vertex();
|
||||||
|
assert_ne!(graph.add_vertex(), v, "unexpected duplicate vertex");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vertex_count_empty() {
|
||||||
|
let graph = <$T>::new();
|
||||||
|
assert_eq!(graph.vertex_count(), 0, "unexpected vertex count");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vertex_count() {
|
||||||
|
let (graph, _) = make_test_graph();
|
||||||
|
assert_eq!(graph.vertex_count(), 10, "unexpected vertex count");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn add_edge() {
|
||||||
|
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() {
|
||||||
|
let graph = <$T>::new();
|
||||||
|
assert_eq!(graph.edge_count(), 0, "unexpected edge count");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn edge_count() {
|
||||||
|
let (graph, _) = make_test_graph();
|
||||||
|
assert_eq!(graph.edge_count(), 14, "unexpected edge count");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn degree_zero() {
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let v = graph.add_vertex();
|
||||||
|
assert_eq!(graph.degree(v), 0, "unexpected non-zero degree");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn degree() {
|
||||||
|
let (graph, vertices) = make_test_graph();
|
||||||
|
let expected_degrees = [1, 4, 4, 2, 4, 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 are_adjacent_vertex_self() {
|
||||||
|
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() {
|
||||||
|
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() {
|
||||||
|
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 {
|
||||||
|
2 => continue,
|
||||||
|
1 | 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() {
|
||||||
|
let graph = <$T>::new();
|
||||||
|
assert_eq!(
|
||||||
|
graph.vertices().count(),
|
||||||
|
0,
|
||||||
|
"vertex iterator of empty graph should have no elements"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn vertices() {
|
||||||
|
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 neighbors_empty() {
|
||||||
|
let mut graph = <$T>::new();
|
||||||
|
let vertex = graph.add_vertex();
|
||||||
|
assert_eq!(
|
||||||
|
graph.neighbors(vertex).count(),
|
||||||
|
0,
|
||||||
|
"neighbor iterator of vertex with degree 0 should have no elements"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn neighbors() {
|
||||||
|
let (graph, vertices) = make_test_graph();
|
||||||
|
// Checks neighbors of vertex 4.
|
||||||
|
assert_eq!(
|
||||||
|
graph.neighbors(vertices[4]).count(),
|
||||||
|
4,
|
||||||
|
"unexpected neighbor count"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Expects each neighbor to appear exactly once. This will not work if there are multiple edges.
|
||||||
|
let neighbors = vec![vertices[1], vertices[2], vertices[7], vertices[8]];
|
||||||
|
for v in graph.neighbors(vertices[4]) {
|
||||||
|
assert_eq!(
|
||||||
|
neighbors.iter().filter(|&x| *x == v).count(),
|
||||||
|
1,
|
||||||
|
"unexpected neighbor {v:?} of {:?} from the iterator",
|
||||||
|
vertices[4]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn loop_edge() {
|
||||||
|
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"
|
||||||
|
);
|
||||||
|
let mut neighbors = graph.neighbors(v);
|
||||||
|
assert_eq!(
|
||||||
|
neighbors.next(),
|
||||||
|
Some(v),
|
||||||
|
"vertex should be neighbor of itself"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
neighbors.next(),
|
||||||
|
Some(v),
|
||||||
|
"vertex should be neighbor of itself twice"
|
||||||
|
);
|
||||||
|
assert_eq!(neighbors.next(), None, "too many neighbors from iterator");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multiple_edges() {
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
graph.vertex_count(),
|
||||||
|
vertices.len(),
|
||||||
|
"unexpected vertex count"
|
||||||
|
);
|
||||||
|
assert_eq!(graph.edge_count(), k, "unexpected edge count");
|
||||||
|
for v in vertices {
|
||||||
|
assert_eq!(graph.degree(v), k, "unexpected degree of {v:?}");
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
graph.are_adjacent(vertices[0], vertices[1]),
|
||||||
|
"should be adjacent"
|
||||||
|
);
|
||||||
|
for i in 0..2 {
|
||||||
|
let mut neighbors = graph.neighbors(vertices[i]);
|
||||||
|
for j in 0..k {
|
||||||
|
assert_eq!(
|
||||||
|
neighbors.next(),
|
||||||
|
Some(vertices[1 - i]),
|
||||||
|
"neighbor {j} of vertex {:?} should be {:?}",
|
||||||
|
vertices[i],
|
||||||
|
vertices[1 - i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
neighbors.next(),
|
||||||
|
None,
|
||||||
|
"too many neighbors of {:?} from iterator",
|
||||||
|
vertices[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! graph_topology_deletion_tests {
|
||||||
|
($T:ty) => {
|
||||||
|
#[test]
|
||||||
|
fn delete_vertex() {
|
||||||
|
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() {
|
||||||
|
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() {
|
||||||
|
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() {
|
||||||
|
let (mut graph, vertices) = make_test_graph();
|
||||||
|
assert_eq!(
|
||||||
|
graph.vertex_count(),
|
||||||
|
10,
|
||||||
|
"unexpected vertex count before delete"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
graph.edge_count(),
|
||||||
|
14,
|
||||||
|
"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(), 10, "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[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.neighbors(v).any(|u| u == vertices[2]),
|
||||||
|
"unexpected adjacency of {v:?} to deleted vertex {:?}",
|
||||||
|
vertices[2]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn delete_edge() {
|
||||||
|
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() {
|
||||||
|
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() {
|
||||||
|
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() {
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user