use {
evict::{
EvictError,
EvictionPolicy,
LruKConfig,
LruKReplacer,
replacer::LRUK_REPLACER_REF_PERIOD,
},
std::{thread::sleep, time::Duration},
};
#[test]
fn basic_ops() {
let replacer = LruKReplacer::with_config(LruKConfig {
capacity: 7,
k: 2,
ref_period: 0,
});
assert_eq!(0, replacer.size());
replacer.touch(1).unwrap();
replacer.touch(2).unwrap();
replacer.touch(3).unwrap();
replacer.touch(4).unwrap();
replacer.touch(5).unwrap();
replacer.touch(6).unwrap();
replacer.pin(6).unwrap();
assert_eq!(5, replacer.size());
replacer.touch(1).unwrap();
assert_eq!(Some(2), replacer.evict());
assert_eq!(Some(3), replacer.evict());
assert_eq!(Some(4), replacer.evict());
assert_eq!(2, replacer.size());
replacer.touch(3).unwrap();
replacer.touch(4).unwrap();
replacer.touch(5).unwrap();
replacer.touch(4).unwrap();
replacer.unpin(3).unwrap();
replacer.unpin(4).unwrap();
assert_eq!(4, replacer.size());
assert_eq!(Some(3), replacer.evict());
assert_eq!(3, replacer.size());
replacer.unpin(6).unwrap();
assert_eq!(4, replacer.size());
assert_eq!(Some(6), replacer.evict());
assert_eq!(3, replacer.size());
replacer.pin(1).unwrap();
assert_eq!(2, replacer.size());
assert_eq!(Some(5), replacer.evict());
assert_eq!(1, replacer.size());
replacer.touch(1).unwrap();
replacer.touch(1).unwrap();
replacer.unpin(1).unwrap();
assert_eq!(2, replacer.size());
assert_eq!(Some(4), replacer.evict());
assert_eq!(1, replacer.size());
assert_eq!(Some(1), replacer.evict());
assert_eq!(0, replacer.size());
assert_eq!(None, replacer.evict());
assert_eq!(0, replacer.size());
}
#[test]
fn over_capacity() {
let replacer = LruKReplacer::with_config(LruKConfig {
capacity: 3,
k: 2,
ref_period: 0,
});
assert_eq!(0, replacer.size());
replacer.touch(1).unwrap();
replacer.touch(2).unwrap();
replacer.touch(3).unwrap();
assert_eq!(replacer.touch(4), Err(EvictError::FrameReplacerFull));
}
#[test]
fn pin_frame() {
let replacer = LruKReplacer::with_config(LruKConfig {
capacity: 7,
k: 2,
ref_period: 0,
});
assert_eq!(0, replacer.size());
replacer.touch(1).unwrap();
assert_eq!(1, replacer.size());
replacer.pin(1).unwrap();
assert_eq!(0, replacer.size());
replacer.pin(1).unwrap();
assert_eq!(0, replacer.size());
}
#[test]
fn ref_period_early_eviction() {
let replacer = LruKReplacer::with_config(LruKConfig {
capacity: 7,
k: 2,
ref_period: 100, });
replacer.touch(1).unwrap();
assert_eq!(1, replacer.size());
assert_eq!(None, replacer.evict());
assert_eq!(1, replacer.size());
sleep(Duration::from_millis(101));
assert_eq!(Some(1), replacer.evict());
assert_eq!(0, replacer.size());
}
#[test]
fn correlated_period() {
let replacer = LruKReplacer::with_config(LruKConfig {
capacity: 7,
k: 2,
ref_period: 100_000_000, });
replacer.touch(1).unwrap();
replacer.touch(1).unwrap();
replacer.touch(1).unwrap();
replacer.touch(1).unwrap();
replacer.touch(1).unwrap();
assert_eq!(1, replacer.size());
replacer.touch(2).unwrap();
sleep(Duration::from_millis(100));
replacer.touch(2).unwrap();
sleep(Duration::from_millis(100));
replacer.touch(2).unwrap();
assert_eq!(2, replacer.size());
}
#[test]
fn remove_arbitrary_frame() {
let replacer = LruKReplacer::with_config(LruKConfig {
capacity: 7,
k: 2,
ref_period: LRUK_REPLACER_REF_PERIOD,
});
replacer.touch(1).unwrap();
replacer.touch(2).unwrap();
replacer.touch(1).unwrap();
replacer.touch(1).unwrap();
replacer.touch(2).unwrap();
replacer.touch(1).unwrap();
assert_eq!(2, replacer.size());
assert_eq!(None, replacer.peek());
replacer.remove(1).unwrap();
assert_eq!(1, replacer.size());
replacer.pin(2).unwrap();
assert_eq!(0, replacer.size());
assert_eq!(replacer.remove(2), Err(EvictError::PinnedFrameRemoval(2)));
assert_eq!(0, replacer.size());
replacer.unpin(2).unwrap();
assert_eq!(1, replacer.size());
assert_eq!(None, replacer.peek());
replacer.remove(2).unwrap();
assert_eq!(0, replacer.size());
}