use alloc::vec::Vec;
use super::{SlotSet, SlotSetInsertError, SlotSetInsertOutcome, SlotSetRemoveOutcome, StableSlot};
#[test]
fn roaring_slots_preserve_sorted_membership() -> Result<(), &'static str> {
let first = StableSlot::new(0);
let mut set = SlotSet::one(first);
for value in [65_537, 3, 4_096, 1] {
let slot = StableSlot::new(value);
assert_eq!(
set.try_prepare_insert(slot)
.map_err(|_| "slot insertion failed")?
.commit(),
SlotSetInsertOutcome::Inserted { slot }
);
}
let collected = set.slots().map(StableSlot::value).collect::<Vec<_>>();
assert_eq!(collected, [0, 1, 3, 4_096, 65_537]);
assert_eq!(set.len(), 5);
let mut slots = set.slots();
assert_eq!(slots.size_hint(), (5, Some(5)));
#[cfg(target_pointer_width = "64")]
assert_eq!(slots.len(), 5);
assert_eq!(slots.next(), Some(StableSlot::new(0)));
assert_eq!(slots.next_back(), Some(StableSlot::new(65_537)));
assert_eq!(slots.size_hint(), (3, Some(3)));
#[cfg(target_pointer_width = "64")]
assert_eq!(slots.len(), 3);
assert_eq!(slots.by_ref().count(), 3);
assert_eq!(slots.next(), None);
assert_eq!(slots.next_back(), None);
Ok(())
}
#[test]
fn abandoned_insertions_publish_nothing() -> Result<(), &'static str> {
let mut set = SlotSet::one(StableSlot::new(0));
{
let prepared = set
.try_prepare_insert(StableSlot::new(1))
.map_err(|_| "preparation failed")?;
assert_eq!(prepared.slot(), StableSlot::new(1));
}
assert!(!set.contains(StableSlot::new(1)));
Ok(())
}
#[test]
fn duplicate_and_remove_outcomes_preserve_the_slot() -> Result<(), &'static str> {
let slot = StableSlot::new(7);
let mut set = SlotSet::one(slot);
assert!(matches!(
set.try_prepare_insert(slot),
Err(SlotSetInsertError::AlreadyPresent { slot: duplicate }) if duplicate == slot
));
assert_eq!(set.remove(slot), SlotSetRemoveOutcome::Removed { slot });
assert!(set.is_empty());
assert_eq!(set.remove(slot), SlotSetRemoveOutcome::Absent { slot });
Ok(())
}
#[test]
fn set_algebra_composes_secondary_memberships() -> Result<(), &'static str> {
let left = set([1, 2, 4])?;
let right = set([2, 3, 4])?;
assert_eq!(values(&left.union(&right)), [1, 2, 3, 4]);
assert_eq!(values(&left.intersection(&right)), [2, 4]);
assert_eq!(values(&left.excluding(&right)), [1]);
assert_eq!(values(&left.union_excluding_overlap(&right)), [1, 3]);
assert!(!left.is_disjoint(&right));
assert!(left.intersection(&right).is_subset(&left));
assert!(set([7])?.is_disjoint(&left));
let mut assigned = set([1, 2, 4])?;
assigned.union_assign(&right);
assert_eq!(values(&assigned), [1, 2, 3, 4]);
assigned = set([1, 2, 4])?;
assigned.intersection_assign(&right);
assert_eq!(values(&assigned), [2, 4]);
assert_eq!(
values(&set([1, 2, 4])?.intersection_reusing(&right)),
[2, 4]
);
assert_eq!(
values(&set([1, 2, 3, 4, 5])?.intersection_reusing(&set([2, 4])?)),
[2, 4]
);
assert_eq!(
values(&set([1, 2, 3, 4, 5])?.intersection_owned(set([2, 4])?)),
[2, 4]
);
assigned = set([1, 2, 4])?;
assigned.exclude_assign(&right);
assert_eq!(values(&assigned), [1]);
assigned = set([1, 2, 4])?;
assigned.union_excluding_overlap_assign(&right);
assert_eq!(values(&assigned), [1, 3]);
Ok(())
}
fn set<const N: usize>(values: [u32; N]) -> Result<SlotSet, &'static str> {
let Some((first, remaining)) = values.split_first() else {
return Err("test set was empty");
};
let mut slots = SlotSet::one(StableSlot::new(*first));
for value in remaining {
let SlotSetInsertOutcome::Inserted { .. } = slots
.try_prepare_insert(StableSlot::new(*value))
.map_err(|_| "test slot was duplicated")?
.commit();
}
Ok(slots)
}
fn values(slots: &SlotSet) -> Vec<u32> {
slots.slots().map(StableSlot::value).collect()
}