use doublets::{decorators::DecoratorsExt, split, unit, Doublets, DoubletsExt, Error, Link};
use mem::Global;
fn delete_all_with_a_middle_hole(mut store: impl Doublets<u32>) -> Result<(), Error<u32>> {
for _ in 0..3 {
store.create_point()?;
}
store.delete(2)?;
assert_eq!(
store.iter().collect::<Vec<_>>(),
[Link::point(1), Link::point(3)]
);
store.delete_all()?;
assert_eq!(store.count(), 0);
assert_eq!(store.iter().next(), None);
Ok(())
}
fn delete_all_with_a_leading_hole(mut store: impl Doublets<u32>) -> Result<(), Error<u32>> {
for _ in 0..3 {
store.create_point()?;
}
store.delete(1)?;
assert_eq!(
store.iter().collect::<Vec<_>>(),
[Link::point(2), Link::point(3)]
);
store.delete_all()?;
assert_eq!(store.count(), 0);
assert_eq!(store.iter().next(), None);
Ok(())
}
fn delete_all_with_every_small_hole_pattern(
mut store: impl Doublets<u32>,
) -> Result<(), Error<u32>> {
for holes in 0..32 {
for expected in 1..=5 {
assert_eq!(store.create_point()?, expected);
}
for index in 1..=5 {
if holes & (1 << (index - 1)) != 0 {
store.delete(index)?;
}
}
store.delete_all()?;
assert_eq!(store.count(), 0, "hole pattern {holes:05b}");
assert_eq!(store.iter().next(), None, "hole pattern {holes:05b}");
for index in 1..=5 {
assert!(
!store.exist(index),
"hole pattern {holes:05b}, index {index}"
);
}
store.delete_all()?;
let point = store.create_point()?;
assert_eq!(point, 1);
assert_eq!(store.get_link(point), Some(Link::point(point)));
store.delete(point)?;
}
Ok(())
}
fn delete_all_preserves_cascading_deletion(
mut store: impl Doublets<u32>,
) -> Result<(), Error<u32>> {
let usage = store.create_point()?;
let hole = store.create_point()?;
let root = store.create_point()?;
store.update(usage, root, usage)?;
store.delete(hole)?;
let mut store = store.with_automatic_uniqueness_and_usages_resolution();
store.delete_all()?;
assert_eq!(store.count(), 0);
assert_eq!(store.iter().next(), None);
store.delete_all()?;
assert_eq!(store.create_point()?, 1);
Ok(())
}
fn delete_all_deletes_dependents_before_dependencies(
mut store: impl Doublets<u32>,
) -> Result<(), Error<u32>> {
let source = store.create_point()?;
let target = store.create_point()?;
let hole = store.create_point()?;
let usage = store.create_link(source, target)?;
store.create_link(usage, usage)?;
store.delete(hole)?;
let mut store = store.with_usages_validation();
store.delete_all()?;
assert_eq!(store.count(), 0);
assert_eq!(store.iter().next(), None);
Ok(())
}
fn delete_all_propagates_deletion_errors(mut store: impl Doublets<u32>) -> Result<(), Error<u32>> {
let usage = store.create_point()?;
let hole = store.create_point()?;
let root = store.create_point()?;
store.update(usage, root, usage)?;
store.delete(hole)?;
let mut store = store.with_usages_validation();
assert!(matches!(store.delete_all(), Err(Error::HasUsages(_))));
assert_eq!(store.count(), 2);
assert!(store.exist(usage));
assert!(store.exist(root));
Ok(())
}
macro_rules! test_both_stores {
($($test:ident),+ $(,)?) => {
$(
mod $test {
use super::*;
#[test]
fn unit() -> Result<(), Error<u32>> {
$test(unit::Store::<u32, _>::new(Global::new())?)
}
#[test]
fn split() -> Result<(), Error<u32>> {
$test(split::Store::<u32, _, _>::new(Global::new(), Global::new())?)
}
}
)+
};
}
test_both_stores!(
delete_all_with_a_middle_hole,
delete_all_with_a_leading_hole,
delete_all_with_every_small_hole_pattern,
delete_all_preserves_cascading_deletion,
delete_all_deletes_dependents_before_dependencies,
delete_all_propagates_deletion_errors,
);