mod expiry;
mod cache;
pub use cache::*;
mod test {
#[allow(unused_imports)]
use super::expiry::DataExpiry;
#[allow(unused_imports)]
use std::sync::Arc;
#[allow(unused_imports)]
use std::sync::atomic::{AtomicBool, Ordering};
#[tokio::test]
async fn test_cache_size_eviction() {
let cache = moka::future::Cache::builder()
.max_capacity(3)
.time_to_live(tokio::time::Duration::from_secs(5))
.eviction_listener(|k: std::sync::Arc<&'static str>, _v, _cause| {
println!("Evicting key: {}", k);
assert_eq!(*k, "key2");
})
.build();
cache.insert("key1", "value1").await;
cache.insert("key2", "value2").await;
cache.insert("key3", "value3").await;
assert_eq!(cache.iter().count(), 3);
for _ in 0..100 {
cache.get("key3").await;
}
for _ in 0..50 {
cache.get("key1").await;
}
cache.insert("key4", "value4").await;
for i in 0..10 {
cache.get("key4").await; print!("{},", i + 1);
}
println!("");
cache.run_pending_tasks().await;
assert_eq!(cache.iter().count(), 3);
}
#[tokio::test]
async fn test_immediate_eviction() {
let cache = moka::future::Cache::builder()
.max_capacity(3)
.time_to_live(tokio::time::Duration::from_secs(5))
.eviction_listener(|k: std::sync::Arc<&'static str>, _v, _cause| {
println!("Evicting key: {}", k);
})
.build();
cache.insert("key1", "value1").await;
cache.invalidate("key1").await;
assert_eq!(cache.iter().count(), 0);
}
#[tokio::test]
async fn test_cache_expiry() {
let cache = moka::future::Cache::builder()
.max_capacity(3)
.expire_after(DataExpiry)
.eviction_listener(|k, v, c| match c {
moka::notification::RemovalCause::Expired => {
println!("Evicting expired key: {}, value: {}", k.0, v)
}
_ => println!("Evicting key: {}, value: {}, cause: {:?}", k.0, v, c),
})
.build();
type Key<K, V> = Arc<(Arc<K>, Arc<V>)>;
let k1 = Key::from((Arc::new("key1").to_owned(), Arc::new("value1").to_owned()));
cache.insert(k1.clone(), 2).await;
cache.insert(Key::from((Arc::new("key2").to_owned(), Arc::new("value2").to_owned())), 2).await;
cache.insert(Key::from((Arc::new("key3").to_owned(), Arc::new("value3").to_owned())), 2).await;
assert_eq!(cache.iter().count(), 3);
cache.insert(k1.clone(), 5).await;
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
println!("Running pending tasks to trigger expiry");
cache.run_pending_tasks().await;
assert_eq!(cache.iter().count(), 1);
}
#[tokio::test]
async fn test_eviction_laziness() {
let flag = Arc::new(AtomicBool::new(false));
let cache = moka::future::Cache::builder()
.max_capacity(3)
.time_to_live(tokio::time::Duration::from_secs(2))
.eviction_listener({
let flag = Arc::clone(&flag);
move |_k: std::sync::Arc<&'static str>, _v: u32, _cause| {
println!("Evicting key: {}", _k);
flag.store(true, Ordering::Relaxed);
}
})
.build();
cache.insert("key1", 2).await;
tokio::time::sleep(tokio::time::Duration::from_secs(4)).await;
assert!(!flag.load(Ordering::Relaxed));
}
#[tokio::test]
async fn test_eviction_laziness_2() {
let flag = Arc::new(AtomicBool::new(false));
let cache = moka::future::Cache::builder()
.max_capacity(1)
.time_to_live(tokio::time::Duration::from_secs(5))
.eviction_listener({
let flag = Arc::clone(&flag);
move |_k: std::sync::Arc<&'static str>, _v: u32, _cause| {
println!("Evicting key: {}", _k);
flag.store(true, Ordering::Relaxed);
}
})
.build();
cache.insert("key1", 2).await;
cache.insert("key2", 2).await;
cache.insert("key3", 2).await;
assert!(!flag.load(Ordering::Relaxed));
}
}