Commit 88c765e2 authored by SirBlueRabbit's avatar SirBlueRabbit
Browse files

rewrite collection tests

parent 0d16d106
......@@ -4,7 +4,7 @@ use std::{
ops::{Index, IndexMut},
};
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
enum Element<T: Copy> {
Object(T),
Hole(usize),
......@@ -175,6 +175,7 @@ impl<T: Copy> Bag<T> {
self.labels[self.size] = None;
}
// todo: replace this sampling withan index impl
pub fn sample(&self) -> Label<T> {
let seed = fastrand::usize(0..(self.size));
self.labels[seed].unwrap()
......@@ -206,133 +207,103 @@ mod tests {
struct Foo;
#[test]
fn pool_insert_cap() {
let mut pool = Pool::with_capacity(50);
(0..50).for_each(|_| {
let _ = pool.insert(Foo);
});
}
#[test]
#[should_panic]
fn pool_insert_cap_panic() {
let mut pool = Pool::with_capacity(50);
(0..51).for_each(|_| {
let _ = pool.insert(Foo);
});
}
#[test]
fn consistency_check() {
let mut pool = Pool::with_capacity(10);
let mut bag = Bag::with_capacity(10);
(0..10).for_each(|_| {
let label = pool_insert_checked(&mut pool);
bag_insert_checked(&mut bag, label);
assert_consistent(&pool, &bag);
});
(0..8).for_each(|_| {
let label = bag.sample();
pool_remove_checked(&mut pool, label);
bag_remove_checked(&mut bag, label);
assert_consistent(&pool, &bag);
});
(0..6).for_each(|_| {
let label = pool_insert_checked(&mut pool);
bag_insert_checked(&mut bag, label);
assert_consistent(&pool, &bag);
});
}
fn pool_insert_checked(pool: &mut Pool<Foo>) -> Label<Foo> {
let predicted_label = Label::from(pool.next_label_value());
fn it_works() {
// create pool with capacity 1
let mut pool = Pool::with_capacity(1);
assert_eq!(pool.elements[0], Element::Hole(1));
assert_eq!(pool.current_hole, 0);
assert_eq!(pool.size, 0);
// create bag with capacity 1
let mut bag = Bag::with_capacity(1);
assert_eq!(bag.indices[0], None);
assert_eq!(bag.labels[0], None);
assert_eq!(bag.size, 0);
// insert object into pool
let label = pool.insert(Foo);
assert_eq!(predicted_label, label);
assert_eq!(pool.elements[0], Element::Object(Foo));
assert_eq!(pool.current_hole, 1);
assert_eq!(pool.size, 1);
assert!(pool.contains(label));
label
}
fn pool_remove_checked(pool: &mut Pool<Foo>, label: Label<Foo>) {
assert!(pool.contains(label));
pool.remove(label);
assert!(!pool.contains(label));
}
fn bag_insert_checked(bag: &mut Bag<Foo>, label: Label<Foo>) {
assert!(!bag.contains(label));
// insert label into bag
bag.insert(label);
assert_eq!(bag.indices[0], Some(0));
assert_eq!(bag.labels[0], Some(label));
assert_eq!(bag.size, 1);
assert!(bag.contains(label));
}
fn bag_remove_checked(bag: &mut Bag<Foo>, label: Label<Foo>) {
assert!(bag.contains(label));
dbg!(bag.clone());
// remove label from bag
bag.remove(label);
dbg!(bag.clone());
dbg!(label);
assert_eq!(bag.indices[0], None);
assert_eq!(bag.labels[0], None);
assert_eq!(bag.size, 0);
assert!(!bag.contains(label));
}
fn assert_consistent(pool: &Pool<Foo>, bag: &Bag<Foo>) {
assert_pool_size(pool);
assert_pool_hole(pool);
assert_bag_size(bag);
assert_bag_indices(bag);
assert_pool_contains_bag(pool, bag);
}
fn assert_pool_size(pool: &Pool<Foo>) {
let mut observed_size = 0;
pool.elements.iter().for_each(|element| match element {
Element::Object(_) => observed_size += 1,
Element::Hole(_) => (),
});
assert_eq!(observed_size, pool.size);
}
fn assert_pool_hole(pool: &Pool<Foo>) {
if pool.size < pool.elements.len() {
assert!(matches!(pool.elements[pool.current_hole], Element::Hole(_)));
}
// remove object from pool
pool.remove(label);
assert_eq!(pool.elements[0], Element::Hole(1));
assert_eq!(pool.current_hole, 0);
assert_eq!(pool.size, 0);
assert!(!pool.contains(label));
}
fn assert_bag_size(bag: &Bag<Foo>) {
let mut indices_size = 0;
let mut labels_size = 0;
bag.indices.iter().for_each(|index| {
if index.is_some() {
indices_size += 1;
}
});
bag.labels.iter().for_each(|label| {
if label.is_some() {
labels_size += 1;
}
});
assert_eq!(indices_size, labels_size);
assert_eq!(indices_size, bag.size);
#[test]
fn insert_remove() {
// create pool and bag
let mut pool = Pool::with_capacity(3);
let mut bag = Bag::with_capacity(3);
// insert 3 objects into pool
let label1 = pool.insert(Foo);
let label2 = pool.insert(Foo);
let label3 = pool.insert(Foo);
// insert 3 labels into bag
bag.insert(label1);
bag.insert(label2);
bag.insert(label3);
// remove second label from bag
bag.remove(label2);
assert_eq!(bag.indices[0], Some(0));
assert_eq!(bag.indices[1], None);
assert_eq!(bag.indices[2], Some(1));
assert_eq!(bag.labels[0], Some(label1));
assert_eq!(bag.labels[1], Some(label3));
assert_eq!(bag.labels[2], None);
assert_eq!(bag.size, 2);
assert!(bag.contains(label1));
assert!(!bag.contains(label2));
assert!(bag.contains(label3));
// remove second object from pool
pool.remove(label2);
assert_eq!(pool.elements[1], Element::Hole(3));
assert_eq!(pool.current_hole, 1);
assert_eq!(pool.size, 2);
assert!(pool.contains(label1));
assert!(!pool.contains(label2));
assert!(pool.contains(label3));
}
fn assert_bag_indices(bag: &Bag<Foo>) {
bag.labels.iter().enumerate().for_each(|(i, &label)| {
if i < bag.size {
assert!(label.is_some());
} else {
assert!(label.is_none());
}
});
bag.labels
.iter()
.take(bag.size)
.enumerate()
.for_each(|(i, &label)| {
assert_eq!(bag.indices[label.unwrap().value].unwrap(), i);
})
#[test]
#[should_panic]
fn pool_cap() {
let mut pool = Pool::with_capacity(1);
let _ = pool.insert(Foo);
let _ = pool.insert(Foo);
}
fn assert_pool_contains_bag(pool: &Pool<Foo>, bag: &Bag<Foo>) {
bag.labels.iter().take(bag.size).for_each(|&label| {
assert!(pool.contains(label.unwrap()));
})
#[test]
#[should_panic]
fn bag_cap() {
let mut pool = Pool::with_capacity(2);
let mut bag = Bag::with_capacity(1);
let label1 = pool.insert(Foo);
let label2 = pool.insert(Foo);
bag.insert(label1);
bag.insert(label2);
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment