diff --git a/src/generators.rs b/src/generators.rs index 5dc36e7..5eb62b7 100644 --- a/src/generators.rs +++ b/src/generators.rs @@ -84,37 +84,128 @@ where #[cfg(test)] mod tests { + use std::fmt::Debug; + use super::*; + use crate::models::{FrozenGraph, Graph}; #[test] - fn petersen() { - let mut graph = AppendGraph::new(); - let (vertices, edges) = super::petersen(&mut graph); - assert_eq!( - graph.vertex_count(), - 10, - "unexpected number of added vertices" - ); - assert_eq!(graph.edge_count(), 15, "unexpected number of added edges"); + fn petersen_append_graph() { + petersen_add::(); + } + + #[test] + fn petersen_graph() { + petersen_add::(); + } + + #[test] + fn petersen_frozen_graph() { + petersen_generate_as::(); + } + + fn petersen_generate_as() + where + G::Vertex: Debug, + G::Edge: Debug, + { + let (graph, vertices, edges) = generate_as::(petersen); + assert_petersen(&graph, &vertices, &edges); + } + + fn petersen_add() + where + G::Vertex: Debug, + G::Edge: Debug, + { + let mut graph = G::default(); + let (vertices, edges) = petersen(&mut graph); + assert_petersen(&graph, &vertices, &edges); + } + + fn assert_petersen(graph: &G, vertices: &[G::Vertex], edges: &[G::Edge]) + where + G::Vertex: Debug, + G::Edge: Debug, + { + assert_element_counts(graph, 10, 15); + assert_handles(graph.vertices(), vertices, "vertex"); + assert_handles(graph.edges(), edges, "edge"); + assert_no_loops_no_multi_edges(graph); assert!( graph.vertices().all(|v| graph.degree(v) == 3), "all vertices should have degree 3" ); - assert_handles_in_graph(&graph, &vertices, &edges); + // Checks that each pair of vertices (u, v) has no common neighbor if they are adjacent, and + // exactly one common neighbor otherwise. + for (i, &v) in vertices.iter().enumerate() { + for &u in &vertices[i + 1..] { + if graph.are_adjacent(v, u) { + assert!( + graph.common_neighbors(u, v).next().is_none(), + "adjacent vertices {u:?} and {v:?} should not have a common neighbor" + ); + } else { + assert_eq!( + graph.common_neighbors(u, v).count(), + 1, + "non-adjacent vertices {u:?} and {v:?} should have exactly one common neighbor" + ); + } + } + } } - fn assert_handles_in_graph( + fn assert_element_counts( graph: &G, - vertices: &[G::Vertex], - edges: &[G::Edge], + expected_vertex_count: usize, + expected_edge_count: usize, ) { - assert!( - vertices.iter().all(|&v| graph.vertices().any(|u| u == v)), - "all returned vertices should be in the graph" + assert_eq!( + graph.vertex_count(), + expected_vertex_count, + "unexpected number of vertices" ); - assert!( - edges.iter().all(|&e| graph.edges().any(|f| f == e)), - "all returned edges should be in the graph" + assert_eq!( + graph.edge_count(), + expected_edge_count, + "unexpected number of edges" ); } + + /// Asserts that every handle in `returned` is unique and in `all`. + fn assert_handles( + all: impl Iterator, + returned: &[T], + kind: &str, + ) { + let mut remaining: Vec = all.collect(); + for e in returned { + let Some(position) = remaining.iter().position(|x| x == e) else { + panic!("returned {kind} {e:?} is not in the graph or appears more than once"); + }; + remaining.swap_remove(position); + } + } + + fn assert_no_loops_no_multi_edges(graph: &G) + where + G::Vertex: Debug, + G::Edge: Debug, + { + for e in graph.edges() { + let (u, v) = graph.incident_vertices(e); + assert_ne!(u, v, "unexpected loop edge {e:?}"); + } + for v in graph.vertices() { + let mut neighbors = Vec::new(); + for u in graph.adjacent_vertices(v) { + assert!( + !neighbors.contains(&u), + "unexpected multi-edge between {v:?} and {u:?}" + ); + neighbors.push(u); + } + } + } }