1mod expiry;
2mod cache;
3
4pub use cache::*;
5
6mod test {
7 #[allow(unused_imports)]
8 use super::expiry::DataExpiry;
9 #[allow(unused_imports)]
10 use std::sync::Arc;
11 #[allow(unused_imports)]
12 use std::sync::atomic::{AtomicBool, Ordering};
13
14 #[tokio::test]
15 async fn test_cache_size_eviction() {
16 let cache = moka::future::Cache::builder()
17 .max_capacity(3)
18 .time_to_live(tokio::time::Duration::from_secs(5))
19 .eviction_listener(|k: std::sync::Arc<&'static str>, _v, _cause| {
20 println!("Evicting key: {}", k);
22 assert_eq!(*k, "key2");
23 })
24 .build();
25 cache.insert("key1", "value1").await;
26 cache.insert("key2", "value2").await;
27 cache.insert("key3", "value3").await;
28 assert_eq!(cache.iter().count(), 3);
29 for _ in 0..100 {
31 cache.get("key3").await;
32 }
33 for _ in 0..50 {
34 cache.get("key1").await;
35 }
36 cache.insert("key4", "value4").await;
38
39 for i in 0..10 {
41 cache.get("key4").await; print!("{},", i + 1);
43 }
44 println!("");
45 cache.run_pending_tasks().await;
47 assert_eq!(cache.iter().count(), 3);
48 }
49
50 #[tokio::test]
51 async fn test_immediate_eviction() {
52 let cache = moka::future::Cache::builder()
53 .max_capacity(3)
54 .time_to_live(tokio::time::Duration::from_secs(5))
55 .eviction_listener(|k: std::sync::Arc<&'static str>, _v, _cause| {
56 println!("Evicting key: {}", k);
58 })
59 .build();
60 cache.insert("key1", "value1").await;
61 cache.invalidate("key1").await;
62 assert_eq!(cache.iter().count(), 0);
63 }
64
65 #[tokio::test]
66 async fn test_cache_expiry() {
67 let cache = moka::future::Cache::builder()
68 .max_capacity(3)
69 .expire_after(DataExpiry)
70 .eviction_listener(|k, v, c| match c {
71 moka::notification::RemovalCause::Expired => {
72 println!("Evicting expired key: {}, value: {}", k.0, v)
73 }
74 _ => println!("Evicting key: {}, value: {}, cause: {:?}", k.0, v, c),
75 })
76 .build();
77
78 type Key<K, V> = Arc<(Arc<K>, Arc<V>)>;
79 let k1 = Key::from((Arc::new("key1").to_owned(), Arc::new("value1").to_owned()));
80 cache.insert(k1.clone(), 2).await;
81 cache.insert(Key::from((Arc::new("key2").to_owned(), Arc::new("value2").to_owned())), 2).await;
82 cache.insert(Key::from((Arc::new("key3").to_owned(), Arc::new("value3").to_owned())), 2).await;
83 assert_eq!(cache.iter().count(), 3);
84
85 cache.insert(k1.clone(), 5).await;
87
88 tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
90
91 println!("Running pending tasks to trigger expiry");
93 cache.run_pending_tasks().await;
94
95 assert_eq!(cache.iter().count(), 1);
96 }
97
98 #[tokio::test]
99 async fn test_eviction_laziness() {
100 let flag = Arc::new(AtomicBool::new(false));
101 let cache = moka::future::Cache::builder()
102 .max_capacity(3)
103 .time_to_live(tokio::time::Duration::from_secs(2))
104 .eviction_listener({
105 let flag = Arc::clone(&flag);
106 move |_k: std::sync::Arc<&'static str>, _v: u32, _cause| {
107 println!("Evicting key: {}", _k);
108 flag.store(true, Ordering::Relaxed);
109 }
110 })
111 .build();
112
113 cache.insert("key1", 2).await;
114 tokio::time::sleep(tokio::time::Duration::from_secs(4)).await;
115
116 assert!(!flag.load(Ordering::Relaxed));
118 }
119
120 #[tokio::test]
121 async fn test_eviction_laziness_2() {
122 let flag = Arc::new(AtomicBool::new(false));
123 let cache = moka::future::Cache::builder()
124 .max_capacity(1)
125 .time_to_live(tokio::time::Duration::from_secs(5))
126 .eviction_listener({
127 let flag = Arc::clone(&flag);
128 move |_k: std::sync::Arc<&'static str>, _v: u32, _cause| {
129 println!("Evicting key: {}", _k);
130 flag.store(true, Ordering::Relaxed);
131 }
132 })
133 .build();
134
135 cache.insert("key1", 2).await;
136 cache.insert("key2", 2).await;
137 cache.insert("key3", 2).await;
138
139 assert!(!flag.load(Ordering::Relaxed));
142 }
143}