#[cfg(test)]
mod tests {
use oxcache::Cache;
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize)]
struct User {
id: u64,
name: String,
}
#[tokio::test]
async fn test_cache_set_and_get() -> Result<(), Box<dyn std::error::Error>> {
let cache: Cache<String, User> = Cache::memory().await?;
let user = User {
id: 1,
name: "Alice".to_string(),
};
let key = "user:1".to_string();
cache.set(&key, &user).await?;
let retrieved: Option<User> = cache.get(&key).await?;
assert!(retrieved.is_some());
assert_eq!(retrieved.unwrap().name, "Alice");
Ok(())
}
#[tokio::test]
async fn test_cache_delete() -> Result<(), Box<dyn std::error::Error>> {
let cache: Cache<String, User> = Cache::memory().await?;
let user = User {
id: 1,
name: "Alice".to_string(),
};
let key = "user:1".to_string();
cache.set(&key, &user).await?;
let exists = cache.exists(&key).await?;
assert!(exists);
cache.delete(&key).await?;
let retrieved: Option<User> = cache.get(&key).await?;
assert!(retrieved.is_none());
Ok(())
}
#[tokio::test]
async fn test_cache_expiration() -> Result<(), Box<dyn std::error::Error>> {
let cache: Cache<String, User> = Cache::memory().await?;
let user = User {
id: 1,
name: "Alice".to_string(),
};
let key = "user:1".to_string();
cache.set_with_ttl(&key, &user, Some(Duration::from_secs(1))).await?;
let exists = cache.exists(&key).await?;
assert!(exists);
tokio::time::sleep(Duration::from_secs(2)).await;
let retrieved: Option<User> = cache.get(&key).await?;
assert!(retrieved.is_none());
Ok(())
}
#[tokio::test]
async fn test_cache_get_or_fallback() -> Result<(), Box<dyn std::error::Error>> {
let cache: Cache<String, User> = Cache::memory().await?;
let key = "user:999".to_string();
let user: User = cache
.get_or(&key, || async {
Ok(User {
id: 999,
name: "Fallback".to_string(),
})
})
.await?;
assert_eq!(user.name, "Fallback");
let user = User {
id: 999,
name: "Updated".to_string(),
};
cache.set(&key, &user).await?;
let cached: User = cache
.get_or(&key, || async {
Ok(User {
id: 999,
name: "Fallback".to_string(),
})
})
.await?;
assert_eq!(cached.name, "Updated");
Ok(())
}
#[tokio::test]
async fn test_cache批量_operations() -> Result<(), Box<dyn std::error::Error>> {
let cache: Cache<String, User> = Cache::memory().await?;
let users = [
(
"user:1".to_string(),
User {
id: 1,
name: "Alice".to_string(),
},
),
(
"user:2".to_string(),
User {
id: 2,
name: "Bob".to_string(),
},
),
(
"user:3".to_string(),
User {
id: 3,
name: "Charlie".to_string(),
},
),
];
cache.set_many(users.iter().map(|(k, v)| (k, v))).await?;
let keys: Vec<String> = vec!["user:1", "user:2", "user:3"]
.into_iter()
.map(String::from)
.collect();
let results: std::collections::HashMap<String, User> = cache.get_many(keys.iter()).await?;
assert_eq!(results.len(), 3);
assert_eq!(results.get("user:1").unwrap().name, "Alice");
assert_eq!(results.get("user:2").unwrap().name, "Bob");
assert_eq!(results.get("user:3").unwrap().name, "Charlie");
Ok(())
}
#[tokio::test]
async fn test_cache_clear() -> Result<(), Box<dyn std::error::Error>> {
let cache: Cache<String, User> = Cache::memory().await?;
let users = [
(
"user:1".to_string(),
User {
id: 1,
name: "Alice".to_string(),
},
),
(
"user:2".to_string(),
User {
id: 2,
name: "Bob".to_string(),
},
),
];
cache.set_many(users.iter().map(|(k, v)| (k, v))).await?;
cache.clear().await?;
let len = cache.len().await?;
assert_eq!(len, 0);
Ok(())
}
#[tokio::test]
async fn test_cache_stats() -> Result<(), Box<dyn std::error::Error>> {
let cache: Cache<String, User> = Cache::memory().await?;
let users = [
(
"user:1".to_string(),
User {
id: 1,
name: "Alice".to_string(),
},
),
(
"user:2".to_string(),
User {
id: 2,
name: "Bob".to_string(),
},
),
];
cache.set_many(users.iter().map(|(k, v)| (k, v))).await?;
let stats = cache.stats().await?;
assert!(!stats.is_empty());
Ok(())
}
}