#[cfg(test)]
mod tests {
use anyhow::Result;
use oxcache::{Cache, CacheBackend};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::RwLock;
#[derive(Debug, Clone, Serialize, Deserialize)]
struct TestData {
id: u64,
value: String,
}
#[tokio::test]
async fn test_cache_backend_interchangeability() -> Result<()> {
let mem_cache: Arc<dyn CacheBackend<String, TestData>> =
Arc::new(Cache::memory().await?);
let data = TestData {
id: 1,
value: "memory".to_string(),
};
mem_cache.set("key:1", &data).await?;
let retrieved: Option<TestData> = mem_cache.get("key:1").await?;
assert!(retrieved.is_some());
assert_eq!(retrieved.unwrap().value, "memory");
test_backend_polymorphism(mem_cache).await?;
Ok(())
}
async fn test_backend_polymorphism(
backend: Arc<dyn CacheBackend<String, TestData>>
) -> Result<()> {
let test_data = TestData {
id: 42,
value: "polymorphic".to_string(),
};
backend.set("poly:key", &test_data).await?;
let result: Option<TestData> = backend.get("poly:key").await?;
assert!(result.is_some());
assert_eq!(result.unwrap().id, 42);
backend.delete("poly:key").await?;
let after_delete: Option<TestData> = backend.get("poly:key").await?;
assert!(after_delete.is_none());
Ok(())
}
#[tokio::test]
async fn test_config_backend_interchangeability() -> Result<()> {
use confers::{Config, sources::*};
let file_config = Config::builder()
.add_source(File::new("test_config.toml", FileFormat::Toml))
.build()
.await?;
let env_config = Config::builder()
.add_source(Environment::default())
.build()
.await?;
let merged = Config::builder()
.add_source(File::new("test_config.toml", FileFormat::Toml))
.add_source(Environment::default())
.build()
.await?;
verify_config_interface(&file_config).await?;
verify_config_interface(&env_config).await?;
verify_config_interface(&merged).await?;
Ok(())
}
async fn verify_config_interface(config: &Config) -> Result<()> {
let _has_values = !config.collect::<Vec<_>>().await.is_empty() || true;
let _value: Option<String> = config.get("test").cloned();
Ok(())
}
#[tokio::test]
async fn test_database_session_interchangeability() -> Result<()> {
use dbnexus::{Pool, Session};
Ok(())
}
#[tokio::test]
async fn test_trait_object_polymorphism() -> Result<()> {
let mut backends: Vec<Box<dyn CacheBackend<String, TestData>>> = Vec::new();
let mem_cache = Cache::memory().await?;
backends.push(Box::new(mem_cache));
for (idx, backend) in backends.iter_mut().enumerate() {
let test_data = TestData {
id: idx as u64,
value: format!("backend_{}", idx),
};
let key = format!("key:{}", idx);
backend.set(&key, &test_data).await?;
let retrieved: Option<TestData> = backend.get(&key).await?;
assert!(retrieved.is_some());
}
Ok(())
}
#[tokio::test]
async fn test_dynamic_dispatch_cache_operations() -> Result<()> {
let cache: Arc<RwLock<Box<dyn CacheBackend<String, TestData>>>> =
Arc::new(RwLock::new(Box::new(Cache::memory().await?)));
{
let mut guard = cache.write().await;
let data = TestData {
id: 1,
value: "dynamic".to_string(),
};
guard.set("dynamic:key", &data).await?;
}
{
let guard = cache.read().await;
let result: Option<TestData> = guard.get("dynamic:key").await?;
assert!(result.is_some());
}
Ok(())
}
#[tokio::test]
async fn test_async_trait_methods() -> Result<()> {
let cache = Cache::memory().await?;
let data = TestData {
id: 1,
value: "async".to_string(),
};
cache.set_with_ttl("ttl:key", &data, std::time::Duration::from_secs(60)).await?;
let items = vec![
("batch:1", TestData { id: 1, value: "batch1".to_string() }),
("batch:2", TestData { id: 2, value: "batch2".to_string() }),
];
cache.set_many(items).await?;
let keys = vec!["batch:1", "batch:2"];
let results: Vec<Option<TestData>> = cache.get_many(keys).await?;
assert_eq!(results.len(), 2);
let _stats = cache.stats().await?;
cache.clear().await?;
let len = cache.len().await?;
assert_eq!(len, 0);
Ok(())
}
}