diff --git a/src/maps.rs b/src/maps.rs index 0c123bb..f79d4a8 100644 --- a/src/maps.rs +++ b/src/maps.rs @@ -49,115 +49,18 @@ impl IndexMut for VertexMap { } #[cfg(test)] -mod tests { +mod append_graph_tests { use crate::models::append_graph::AppendGraph; + use crate::traits::GraphTopology; + + crate::vertex_map_tests!(AppendGraph); +} + +#[cfg(test)] +mod graph_tests { use crate::models::graph::Graph; use crate::traits::{GraphTopology, GraphTopologyDeletion}; - #[test] - fn initial_values_are_default() { - let mut graph = AppendGraph::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let map = graph.vertex_map(42); - assert_eq!(map[v1], 42); - assert_eq!(map[v2], 42); - } - - #[test] - fn write_and_read() { - let mut graph = AppendGraph::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let mut map = graph.vertex_map(0); - map[v1] = 7; - assert_eq!(map[v1], 7); - assert_eq!(map[v2], 0); - } - - #[test] - fn lazy_growth_on_read() { - let mut graph = AppendGraph::new(); - graph.add_vertex(); - let map = graph.vertex_map(99); - let v = graph.add_vertex(); - assert_eq!(map[v], 99); - } - - #[test] - fn lazy_growth_on_write() { - let mut graph = AppendGraph::new(); - let v1 = graph.add_vertex(); - let mut map = graph.vertex_map(0); - let v2 = graph.add_vertex(); - map[v2] = 7; - assert_eq!(map[v1], 0); - assert_eq!(map[v2], 7); - } - - #[test] - fn sync_expands_to_new_vertices() { - let mut graph = AppendGraph::new(); - graph.add_vertex(); - let mut map = graph.vertex_map(42); - graph.add_vertex(); - graph.add_vertex(); - assert!( - map.data.len() < graph.vertex_capacity(), - "precondition: map is stale before sync" - ); - map.sync(&graph); - assert_eq!(map.data.len(), graph.vertex_capacity()); - } - - #[test] - fn sync_does_not_overwrite_existing_values() { - let mut graph = AppendGraph::new(); - let v = graph.add_vertex(); - let mut map = graph.vertex_map(0); - map[v] = 5; - graph.add_vertex(); - map.sync(&graph); - assert_eq!(map[v], 5); - } - - #[test] - fn surviving_vertex_readable_after_delete() { - let mut graph = Graph::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let mut map = graph.vertex_map(0); - map[v1] = 1; - map[v2] = 2; - graph.delete_vertex(v2); - assert_eq!(map[v1], 1); - } - - #[test] - fn capacity_does_not_shrink_after_delete() { - let mut graph = Graph::new(); - let v1 = graph.add_vertex(); - let v2 = graph.add_vertex(); - let mut map = graph.vertex_map(0); - let capacity_before = graph.vertex_capacity(); - graph.delete_vertex(v2); - map.sync(&graph); - assert_eq!(map.data.len(), capacity_before); - assert_eq!(map[v1], 0); - } - - #[test] - fn reused_slot_returns_old_value() { - let mut graph = Graph::new(); - graph.add_vertex(); - let v1 = graph.add_vertex(); - let mut map = graph.vertex_map(0); - map[v1] = 99; - graph.delete_vertex(v1); - let v2 = graph.add_vertex(); - // VertexMap uses raw indices, not vertex identity. A new vertex v2 reusing the slot of - // previously deleted vertex v1 sees the old value. Callers must reinitialize stale - // slots after deletion. - assert_eq!(map[v2], 99); - } + crate::vertex_map_tests!(Graph); + crate::vertex_map_deletion_tests!(Graph); } diff --git a/src/testing.rs b/src/testing.rs index ecf3963..7975b1f 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -1 +1,2 @@ pub(crate) mod graph_topology_testing; +pub(crate) mod vertex_map_testing; diff --git a/src/testing/vertex_map_testing.rs b/src/testing/vertex_map_testing.rs new file mode 100644 index 0000000..e97df88 --- /dev/null +++ b/src/testing/vertex_map_testing.rs @@ -0,0 +1,120 @@ +#[cfg(test)] +#[macro_export] +macro_rules! vertex_map_tests { + ($T:ty) => { + #[test] + fn initial_values_are_default() { + let mut graph = <$T>::new(); + let v1 = graph.add_vertex(); + let v2 = graph.add_vertex(); + let map = graph.vertex_map(42); + assert_eq!(map[v1], 42); + assert_eq!(map[v2], 42); + } + + #[test] + fn write_and_read() { + let mut graph = <$T>::new(); + let v1 = graph.add_vertex(); + let v2 = graph.add_vertex(); + let mut map = graph.vertex_map(0); + map[v1] = 7; + assert_eq!(map[v1], 7); + assert_eq!(map[v2], 0); + } + + #[test] + fn lazy_growth_on_read() { + let mut graph = <$T>::new(); + graph.add_vertex(); + let map = graph.vertex_map(99); + let v = graph.add_vertex(); + assert_eq!(map[v], 99); + } + + #[test] + fn lazy_growth_on_write() { + let mut graph = <$T>::new(); + let v1 = graph.add_vertex(); + let mut map = graph.vertex_map(0); + let v2 = graph.add_vertex(); + map[v2] = 7; + assert_eq!(map[v1], 0); + assert_eq!(map[v2], 7); + } + + #[test] + fn sync_expands_to_new_vertices() { + let mut graph = <$T>::new(); + graph.add_vertex(); + let mut map = graph.vertex_map(42); + let initial_len = map.data.len(); + while graph.vertex_capacity() <= initial_len { + graph.add_vertex(); + } + assert!( + map.data.len() < graph.vertex_capacity(), + "precondition: map is stale before sync" + ); + map.sync(&graph); + assert_eq!(map.data.len(), graph.vertex_capacity()); + } + + #[test] + fn sync_does_not_overwrite_existing_values() { + let mut graph = <$T>::new(); + let v = graph.add_vertex(); + let mut map = graph.vertex_map(0); + map[v] = 5; + graph.add_vertex(); + map.sync(&graph); + assert_eq!(map[v], 5); + } + }; +} + +#[cfg(test)] +#[macro_export] +macro_rules! vertex_map_deletion_tests { + ($T:ty) => { + #[test] + fn surviving_vertex_readable_after_delete() { + let mut graph = <$T>::new(); + let v1 = graph.add_vertex(); + let v2 = graph.add_vertex(); + let mut map = graph.vertex_map(0); + map[v1] = 1; + map[v2] = 2; + graph.delete_vertex(v2); + assert_eq!(map[v1], 1); + } + + #[test] + fn capacity_does_not_shrink_after_delete() { + let mut graph = <$T>::new(); + let v1 = graph.add_vertex(); + let v2 = graph.add_vertex(); + let mut map = graph.vertex_map(0); + let capacity_before = graph.vertex_capacity(); + graph.delete_vertex(v2); + map.sync(&graph); + assert_eq!(map.data.len(), capacity_before); + assert_eq!(map[v1], 0); + } + + #[test] + fn reused_slot_returns_old_value() { + let mut graph = <$T>::new(); + graph.add_vertex(); + let v1 = graph.add_vertex(); + let mut map = graph.vertex_map(0); + map[v1] = 99; + graph.delete_vertex(v1); + let v2 = graph.add_vertex(); + // VertexMap uses raw indices, not vertex identity. A new vertex v2 reusing the slot + // of previously deleted v1 sees the old value. Callers must reinitialize stale slots + // after deletion. + assert_eq!(map[v2], 99); + } + }; +}