#[allow(unused_imports)]
use crate::data::cache::{
CacheConfig, CachePolicy, CacheService, CacheType, create_cache_service,
in_memory::InMemoryCache,
patterns::{cache_aside, write_through},
};
#[allow(unused_imports)]
use std::collections::HashMap;
#[allow(unused_imports)]
use std::time::Duration;
#[tokio::test]
async fn test_in_memory_cache_basic_operations() {
let config = CacheConfig {
cache_type: CacheType::InMemory,
policy: CachePolicy::LRU,
hosts: vec![],
port: None,
connection_timeout_seconds: 5,
operation_timeout_seconds: 2,
default_ttl_seconds: 300,
default_ttl: None,
username: None,
password: None,
pool: Default::default(),
tls_enabled: false,
file_path: None,
max_size_bytes: None,
namespace: Some("test".to_string()),
database: None,
extra_params: HashMap::new(),
};
let cache = InMemoryCache::new(&config);
let key = "test-key";
let value = b"test-value";
cache.set(key, value, None).await.unwrap();
let result = cache.get(key).await.unwrap();
assert_eq!(result, Some(value.to_vec()));
let string_result = cache.get_string(key).await.unwrap();
assert_eq!(string_result, Some("test-value".to_string()));
let exists = cache.exists(key).await.unwrap();
assert!(exists);
let deleted = cache.delete(key).await.unwrap();
assert!(deleted);
let result = cache.get(key).await.unwrap();
assert_eq!(result, None);
let key2 = "test-key2";
let nx_result = cache.set_nx(key2, b"nx-value", None).await.unwrap();
assert!(nx_result);
let nx_result2 = cache.set_nx(key2, b"nx-value2", None).await.unwrap();
assert!(!nx_result2);
let result = cache.get(key2).await.unwrap();
assert_eq!(result, Some(b"nx-value".to_vec()));
}
#[tokio::test]
async fn test_in_memory_cache_expiry() {
let config = CacheConfig {
cache_type: CacheType::InMemory,
policy: CachePolicy::LRU,
hosts: vec![],
port: None,
connection_timeout_seconds: 5,
operation_timeout_seconds: 2,
default_ttl_seconds: 1, default_ttl: None,
username: None,
password: None,
pool: Default::default(),
tls_enabled: false,
file_path: None,
max_size_bytes: None,
namespace: Some("test".to_string()),
database: None,
extra_params: HashMap::new(),
};
let cache = InMemoryCache::new(&config);
let key = "expiring-key";
let value = b"expiring-value";
cache.set(key, value, None).await.unwrap();
let result = cache.get(key).await.unwrap();
assert_eq!(result, Some(value.to_vec()));
tokio::time::sleep(Duration::from_secs(2)).await;
let result = cache.get(key).await.unwrap();
assert_eq!(result, None);
}
#[tokio::test]
async fn test_in_memory_cache_increment() {
let config = CacheConfig {
cache_type: CacheType::InMemory,
policy: CachePolicy::LRU,
hosts: vec![],
port: None,
connection_timeout_seconds: 5,
operation_timeout_seconds: 2,
default_ttl_seconds: 300,
default_ttl: None,
username: None,
password: None,
pool: Default::default(),
tls_enabled: false,
file_path: None,
max_size_bytes: None,
namespace: Some("test".to_string()),
database: None,
extra_params: HashMap::new(),
};
let cache = InMemoryCache::new(&config);
let key = "counter";
let result = cache.increment(key, 5).await.unwrap();
assert_eq!(result, 5);
let result = cache.increment(key, 3).await.unwrap();
assert_eq!(result, 8);
let result = cache.decrement(key, 2).await.unwrap();
assert_eq!(result, 6);
}
#[tokio::test]
async fn test_in_memory_cache_bulk_operations() {
let config = CacheConfig {
cache_type: CacheType::InMemory,
policy: CachePolicy::LRU,
hosts: vec![],
port: None,
connection_timeout_seconds: 5,
operation_timeout_seconds: 2,
default_ttl_seconds: 300,
default_ttl: None,
username: None,
password: None,
pool: Default::default(),
tls_enabled: false,
file_path: None,
max_size_bytes: None,
namespace: Some("test".to_string()),
database: None,
extra_params: HashMap::new(),
};
let cache = InMemoryCache::new(&config);
let mut items = HashMap::new();
items.insert("key1".to_string(), b"value1".to_vec());
items.insert("key2".to_string(), b"value2".to_vec());
items.insert("key3".to_string(), b"value3".to_vec());
cache.set_many(&items, None).await.unwrap();
let keys = vec![
"key1".to_string(),
"key2".to_string(),
"key3".to_string(),
"key4".to_string(),
];
let results = cache.get_many(&keys).await.unwrap();
assert_eq!(results.len(), 3); assert_eq!(results.get("key1").unwrap(), &b"value1".to_vec());
assert_eq!(results.get("key2").unwrap(), &b"value2".to_vec());
assert_eq!(results.get("key3").unwrap(), &b"value3".to_vec());
let keys_to_delete = vec!["key1".to_string(), "key2".to_string(), "key4".to_string()];
let delete_count = cache.delete_many(&keys_to_delete).await.unwrap();
assert_eq!(delete_count, 2);
let exists1 = cache.exists("key1").await.unwrap();
let exists2 = cache.exists("key2").await.unwrap();
let exists3 = cache.exists("key3").await.unwrap();
assert!(!exists1);
assert!(!exists2);
assert!(exists3);
}
#[tokio::test]
async fn test_in_memory_cache_namespacing() {
let config1 = CacheConfig {
cache_type: CacheType::InMemory,
policy: CachePolicy::LRU,
hosts: vec![],
port: None,
connection_timeout_seconds: 5,
operation_timeout_seconds: 2,
default_ttl_seconds: 300,
default_ttl: None,
username: None,
password: None,
pool: Default::default(),
tls_enabled: false,
file_path: None,
max_size_bytes: None,
namespace: Some("ns1".to_string()),
database: None,
extra_params: HashMap::new(),
};
let config2 = CacheConfig {
cache_type: CacheType::InMemory,
policy: CachePolicy::LRU,
hosts: vec![],
port: None,
connection_timeout_seconds: 5,
operation_timeout_seconds: 2,
default_ttl_seconds: 300,
default_ttl: None,
username: None,
password: None,
pool: Default::default(),
tls_enabled: false,
file_path: None,
max_size_bytes: None,
namespace: Some("ns2".to_string()),
database: None,
extra_params: HashMap::new(),
};
let cache1 = InMemoryCache::new(&config1);
let cache2 = InMemoryCache::new(&config2);
let key = "shared-key";
cache1.set(key, b"value1", None).await.unwrap();
cache2.set(key, b"value2", None).await.unwrap();
let result1 = cache1.get(key).await.unwrap();
let result2 = cache2.get(key).await.unwrap();
assert_eq!(result1, Some(b"value1".to_vec()));
assert_eq!(result2, Some(b"value2".to_vec()));
cache1.clear(None).await.unwrap();
let result1 = cache1.get(key).await.unwrap();
let result2 = cache2.get(key).await.unwrap();
assert_eq!(result1, None);
assert_eq!(result2, Some(b"value2".to_vec()));
}
#[tokio::test]
async fn test_in_memory_cache_locking() {
let config = CacheConfig {
cache_type: CacheType::InMemory,
policy: CachePolicy::LRU,
hosts: vec![],
port: None,
connection_timeout_seconds: 5,
operation_timeout_seconds: 2,
default_ttl_seconds: 300,
default_ttl: None,
username: None,
password: None,
pool: Default::default(),
tls_enabled: false,
file_path: None,
max_size_bytes: None,
namespace: Some("test".to_string()),
database: None,
extra_params: HashMap::new(),
};
let cache = InMemoryCache::new(&config);
let lock_key = "my-lock";
let lock_ttl = Duration::from_secs(10);
let lock_token = cache.lock(lock_key, lock_ttl).await.unwrap();
assert!(lock_token.is_some());
let token = lock_token.unwrap();
let lock_token2 = cache.lock(lock_key, lock_ttl).await.unwrap();
assert!(lock_token2.is_none());
let unlock_result = cache.unlock(lock_key, "wrong-token").await.unwrap();
assert!(!unlock_result);
let unlock_result = cache.unlock(lock_key, &token).await.unwrap();
assert!(unlock_result);
let lock_token3 = cache.lock(lock_key, lock_ttl).await.unwrap();
assert!(lock_token3.is_some());
}
#[tokio::test]
async fn test_cache_factory() {
let config = CacheConfig {
cache_type: CacheType::InMemory,
policy: CachePolicy::LRU,
hosts: vec![],
port: None,
connection_timeout_seconds: 5,
operation_timeout_seconds: 2,
default_ttl_seconds: 300,
default_ttl: None,
username: None,
password: None,
pool: Default::default(),
tls_enabled: false,
file_path: None,
max_size_bytes: None,
namespace: Some("test".to_string()),
database: None,
extra_params: HashMap::new(),
};
let cache = create_cache_service(&config).await.unwrap();
let key = "factory-test";
let value = b"factory-value";
cache.set(key, value, None).await.unwrap();
let result = cache.get(key).await.unwrap();
assert_eq!(result, Some(value.to_vec()));
assert_eq!(cache.get_cache_type(), CacheType::InMemory);
}
#[tokio::test]
async fn test_cache_patterns() {
let config = CacheConfig {
cache_type: CacheType::InMemory,
policy: CachePolicy::LRU,
hosts: vec![],
port: None,
connection_timeout_seconds: 5,
operation_timeout_seconds: 2,
default_ttl_seconds: 300,
default_ttl: None,
username: None,
password: None,
pool: Default::default(),
tls_enabled: false,
file_path: None,
max_size_bytes: None,
namespace: Some("test".to_string()),
database: None,
extra_params: HashMap::new(),
};
let cache = InMemoryCache::new(&config);
let key = "cache-aside-key";
let result: String = cache_aside(
&cache,
key,
|| async { Ok("source-value".to_string()) },
None,
)
.await
.unwrap();
assert_eq!(result, "source-value");
let result2: String = cache_aside(
&cache,
key,
|| async {
Ok("new-source-value".to_string())
},
None,
)
.await
.unwrap();
assert_eq!(result2, "source-value");
let write_key = "write-through-key";
let value = "write-value".to_string();
let mut saved_to_source = false;
write_through(
&cache,
write_key,
&value,
|| async {
saved_to_source = true;
Ok(())
},
None,
)
.await
.unwrap();
assert!(saved_to_source);
let cached_value = cache.get_string(write_key).await.unwrap();
assert_eq!(cached_value, Some(value));
}
#[tokio::test]
async fn test_cache_stats() {
let config = CacheConfig {
cache_type: CacheType::InMemory,
policy: CachePolicy::LRU,
hosts: vec![],
port: None,
connection_timeout_seconds: 5,
operation_timeout_seconds: 2,
default_ttl_seconds: 300,
default_ttl: None,
username: None,
password: None,
pool: Default::default(),
tls_enabled: false,
file_path: None,
max_size_bytes: None,
namespace: Some("test".to_string()),
database: None,
extra_params: HashMap::new(),
};
let cache = InMemoryCache::new(&config);
cache.set("key1", b"value1", None).await.unwrap();
cache.set("key2", b"value2", None).await.unwrap();
cache.get("key1").await.unwrap();
cache.get("key2").await.unwrap();
cache.get("key2").await.unwrap();
cache.get("key3").await.unwrap();
cache.get("key4").await.unwrap();
let stats = cache.stats().await.unwrap();
assert_eq!(stats.item_count, Some(2));
assert_eq!(stats.hits, Some(3));
assert_eq!(stats.misses, Some(2));
assert!(stats.memory_used_bytes.unwrap() > 0);
}