use std::sync::Arc;
use std::time::Duration;
use oxcache::backend::{BackendKind, CacheConnector, CacheReader, CacheWriter, DragonflyBackend};
#[path = "../../common/mod.rs"]
mod common;
use common::test_containers::DragonflyContainer;
fn set_allow_insecure() {
unsafe { std::env::set_var("OXCACHE_ALLOW_INSECURE_REDIS", "I_UNDERSTAND_THE_RISKS") };
}
async fn make_dragonfly_backend(url: &str) -> Option<DragonflyBackend> {
set_allow_insecure();
DragonflyBackend::new(url, 4).await.ok()
}
async fn setup() -> Option<DragonflyBackend> {
let container = DragonflyContainer::start().await.ok()?;
container.wait_ready().await.ok()?;
let backend = make_dragonfly_backend(&container.url()).await?;
backend.health_check().await.ok()?;
Some(backend)
}
#[tokio::test]
async fn test_dragonfly_backend_kind() {
let Some(backend) = setup().await else { return };
assert_eq!(backend.backend_kind(), BackendKind::Dragonfly);
}
#[tokio::test]
async fn test_dragonfly_atomic_writer_is_none() {
let Some(backend) = setup().await else { return };
assert!(backend.as_atomic_writer().is_none());
}
#[tokio::test]
async fn test_dragonfly_cache_writer_operations() {
let Some(backend) = setup().await else { return };
if backend
.set(Arc::from("df:key1"), Arc::new(b"value1".to_vec()), None)
.await
.is_err()
{
return;
}
if backend
.set(
Arc::from("df:key2"),
Arc::new(b"value2".to_vec()),
Some(Duration::from_secs(60)),
)
.await
.is_err()
{
return;
}
let items = vec![
(Arc::from("df:batch1"), Arc::new(b"b1".to_vec()), None),
(Arc::from("df:batch2"), Arc::new(b"b2".to_vec()), None),
];
if backend.set_many(&items).await.is_err() {
return;
}
if backend.delete("df:key1").await.is_err() {
return;
}
let keys = vec!["df:batch1".to_string(), "df:batch2".to_string()];
if backend.delete_many(&keys).await.is_err() {
return;
}
}
#[tokio::test]
async fn test_dragonfly_cache_reader_operations() {
let Some(backend) = setup().await else { return };
if backend
.set(Arc::from("df:read1"), Arc::new(b"hello".to_vec()), None)
.await
.is_err()
{
return;
}
if backend
.set(
Arc::from("df:read2"),
Arc::new(b"world".to_vec()),
Some(Duration::from_secs(120)),
)
.await
.is_err()
{
return;
}
let Ok(Some(val)) = backend.get("df:read1").await else {
return;
};
assert_eq!(val, b"hello".to_vec());
let Ok(val) = backend.get("df:nonexistent").await else {
return;
};
assert_eq!(val, None);
let Ok(exists) = backend.exists("df:read1").await else {
return;
};
assert!(exists);
let Ok(exists) = backend.exists("df:nonexistent").await else {
return;
};
assert!(!exists);
let Ok(Some(ttl)) = backend.ttl("df:read2").await else {
return;
};
assert!(ttl > Duration::from_secs(100));
let Ok(result) = backend.expire("df:read1", Duration::from_secs(60)).await else {
return;
};
assert!(result);
let Ok(result) = backend.expire("df:nonexistent", Duration::from_secs(60)).await else {
return;
};
assert!(!result);
}
#[tokio::test]
async fn test_dragonfly_cache_connector_operations() {
let Some(backend) = setup().await else { return };
assert_eq!(backend.backend_kind(), BackendKind::Dragonfly);
backend.shutdown().await;
}
#[tokio::test]
async fn test_dragonfly_chain_cache_basic() {
use oxcache::backend::MokaMemoryBackend;
use oxcache::cache::chain::{ChainCacheBuilder, ChainLink};
let Some(dragonfly) = setup().await else { return };
let moka = MokaMemoryBackend::new();
let chain = ChainCacheBuilder::default()
.link(ChainLink::new(moka, 100, false, "moka"))
.link(ChainLink::new(dragonfly, 50, true, "dragonfly"))
.build();
if chain.set("chain:df_key1", b"chain_value".to_vec(), None).await.is_err() {
return;
}
let Ok(Some(val)) = chain.get("chain:df_key1").await else {
return;
};
assert_eq!(val, b"chain_value".to_vec());
if chain.health_check().await.is_err() {
return;
}
}