extern crate quickcheck;
use self::quickcheck::{Arbitrary, Gen, Rng, TestResult, quickcheck};
use super::{Link, Node};
use Map;
#[derive(Clone, Debug)]
enum Op<K> where K: Clone + Ord {
Insert(K),
Remove(usize),
RemoveMax,
RemoveMin,
EntryInsert(K),
EntryRemove(usize),
}
impl<K> Arbitrary for Op<K> where K: Arbitrary + Ord {
fn arbitrary<G: Gen>(gen: &mut G) -> Self {
match gen.gen_range(0, 6) {
0 => Op::Insert(K::arbitrary(gen)),
1 => Op::Remove(usize::arbitrary(gen)),
2 => Op::RemoveMax,
3 => Op::RemoveMin,
4 => Op::EntryInsert(K::arbitrary(gen)),
_ => Op::EntryRemove(usize::arbitrary(gen)),
}
}
fn shrink(&self) -> Box<Iterator<Item=Self>> {
match *self {
Op::Insert(ref key) => Box::new(key.shrink().map(Op::Insert)),
Op::Remove(index) => Box::new(index.shrink().map(Op::Remove)),
Op::RemoveMax | Op::RemoveMin => Box::new(None.into_iter()),
Op::EntryInsert(ref key) => Box::new(key.shrink().map(Op::EntryInsert)),
Op::EntryRemove(index) => Box::new(index.shrink().map(Op::EntryRemove)),
}
}
}
impl<K> Op<K> where K: Clone + Ord {
fn exec(self, map: &mut Map<K, ()>) {
match self {
Op::Insert(key) => { map.insert(key, ()); }
Op::Remove(index) => if !map.is_empty() {
let key = map.iter().nth(index % map.len()).unwrap().0.clone();
map.remove(&key);
},
Op::RemoveMax => { map.remove_max(); }
Op::RemoveMin => { map.remove_min(); }
Op::EntryInsert(key) => { map.entry(key).or_insert(()); }
Op::EntryRemove(index) => if !map.is_empty() {
use map::Entry;
let key = map.iter().nth(index % map.len()).unwrap().0.clone();
match map.entry(key) {
Entry::Occupied(e) => { e.remove(); }
Entry::Vacant(_) => panic!("expected an occupied entry"),
}
},
}
}
}
fn assert_andersson_tree<K, V>(map: &Map<K, V>) where K: Ord {
fn check_left<K, V>(link: &Link<K, V>, parent: &Node<K, V>) where K: Ord {
match *link {
None => assert_eq!(parent.level, 1),
Some(ref node) => {
assert!(node.key < parent.key);
assert_eq!(node.level, parent.level - 1);
check_left(&node.left, node);
check_right(&node.right, node, false);
}
}
}
fn check_right<K, V>(link: &Link<K, V>, parent: &Node<K, V>, parent_red: bool) where K: Ord {
match *link {
None => assert_eq!(parent.level, 1),
Some(ref node) => {
assert!(node.key > parent.key);
let red = node.level == parent.level;
if parent_red { assert!(!red); }
assert!(red || node.level == parent.level - 1);
check_left(&node.left, node);
check_right(&node.right, node, red);
}
}
}
if let Some(ref node) = *map.root() {
check_left(&node.left, node);
check_right(&node.right, node, false);
}
}
#[test]
#[allow(trivial_casts)]
fn test_andersson() {
fn check(ops: Vec<Op<u32>>) -> TestResult {
let mut map = Map::new();
for op in ops { op.exec(&mut map); }
assert_andersson_tree(&map);
TestResult::passed()
}
quickcheck(check as fn(Vec<Op<u32>>) -> TestResult);
}