use std::sync::Arc;
use priority_lfu::{Cache, CacheKey, DeepSizeOf};
#[derive(Hash, Eq, PartialEq, Clone, Debug)]
struct AsyncKey(u64);
impl CacheKey for AsyncKey {
type Value = AsyncValue;
fn policy(&self) -> priority_lfu::CachePolicy {
priority_lfu::CachePolicy::Standard
}
}
#[derive(Clone, Debug, PartialEq, DeepSizeOf)]
struct AsyncValue {
data: String,
}
#[tokio::test]
async fn test_get_clone_in_async() {
let cache = Arc::new(Cache::new(10240));
let key = AsyncKey(1);
let value = AsyncValue {
data: "async test".to_string(),
};
cache.insert(key.clone(), value.clone());
if let Some(cloned_value) = cache.get_clone(&key) {
tokio::time::sleep(tokio::time::Duration::from_millis(1)).await;
assert_eq!(cloned_value, value);
}
}
#[tokio::test]
async fn test_get_clone_with_arc_value() {
let cache = Arc::new(Cache::new(10240));
let key = AsyncKey(2);
let value = AsyncValue {
data: "clone test".to_string(),
};
cache.insert(key.clone(), value.clone());
if let Some(cloned_value) = cache.get_clone(&key) {
tokio::time::sleep(tokio::time::Duration::from_millis(1)).await;
assert_eq!(cloned_value, value);
}
}
#[tokio::test]
async fn test_guard_scoped_correctly() {
let cache = Arc::new(Cache::new(10240));
let key = AsyncKey(3);
let value = AsyncValue {
data: "scoped test".to_string(),
};
cache.insert(key.clone(), value.clone());
let extracted_data = {
let guard = cache.get(&key).expect("key should exist");
guard.data.clone()
};
tokio::time::sleep(tokio::time::Duration::from_millis(1)).await;
assert_eq!(extracted_data, "scoped test");
}
#[tokio::test]
async fn test_concurrent_async_tasks() {
let cache = Arc::new(Cache::new(102400));
for i in 0..100 {
cache.insert(
AsyncKey(i),
AsyncValue {
data: format!("value-{}", i),
},
);
}
let mut handles = vec![];
for task_id in 0..10 {
let cache = cache.clone();
handles.push(tokio::spawn(async move {
for i in 0..100 {
let key = AsyncKey((task_id * 100 + i) % 100);
if let Some(value) = cache.get_clone(&key) {
tokio::time::sleep(tokio::time::Duration::from_micros(1)).await;
assert!(!value.data.is_empty());
}
}
}));
}
for handle in handles {
handle.await.expect("task should not panic");
}
}
#[tokio::test]
async fn test_async_insert_and_get() {
let cache = Arc::new(Cache::new(10240));
let tasks: Vec<_> = (0..20)
.map(|i| {
let cache = cache.clone();
tokio::spawn(async move {
let key = AsyncKey(i);
let value = AsyncValue {
data: format!("async-{}", i),
};
cache.insert(key.clone(), value.clone());
tokio::time::sleep(tokio::time::Duration::from_micros(10)).await;
if let Some(retrieved) = cache.get_clone(&key) {
assert_eq!(retrieved, value);
}
})
})
.collect();
for task in tasks {
task.await.expect("task should not panic");
}
}