KeiSeiKit-1.0/_primitives/_rust/kei-memory-redis/tests/redis_smoke.rs
Parfii-bot a4e667de10 KeiSeiKit-public — clean state
Single-commit clean baseline after security scrub of niche-tells,
project codenames, internal jargon, and contributor-email leaks.

Contents:
- 100 Rust crates (_primitives/_rust/)
- 37 agent manifests (_manifests/) + generated specs (_generated/)
- 67 user-invocable skills (skills/)
- 33 hooks (hooks/)
- Composition blocks (_blocks/)
- Documentation (docs/, README.md)
- TS adapter packages (_ts_packages/)
- Assembler (_assembler/)
- Roles (_roles/)
- Templates (_templates/)
- Forgejo CI (.forgejo/)

Author: Denis Parfionovich <info@greendragon.info>

License: see LICENSE.
2026-05-01 12:09:03 +08:00

101 lines
3.1 KiB
Rust

// SPDX-License-Identifier: Apache-2.0
// Copyright 2026 <author org>
//!
//! Live smoke tests. Compile-only by default. Enable with:
//!
//! ```text
//! cargo test -p kei-memory-redis --features live
//! ```
//!
//! The tests assume a reachable Redis 7+ on `REDIS_URL`
//! (default `redis://127.0.0.1:6379`). They isolate themselves under a
//! per-test prefix and clean up at the end.
#![cfg(feature = "live")]
use kei_memory_redis::{RedisBackend, RedisStore};
use kei_runtime_core::traits::memory::{MemoryBackend, MemoryItem, MemoryQuery};
use kei_runtime_core::DnaBuilder;
fn redis_url() -> String {
std::env::var("REDIS_URL").unwrap_or_else(|_| "redis://127.0.0.1:6379".into())
}
fn fresh_prefix(suffix: &str) -> String {
let pid = std::process::id();
let nanos = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_nanos())
.unwrap_or(0);
format!("kei-test:{suffix}:{pid}:{nanos}")
}
fn dummy_item(prefix: &str, kind: &str, key: &str, ts: i64, tags: Vec<String>) -> MemoryItem {
let dna = DnaBuilder::new("primitive")
.cap("RD")
.scope(prefix)
.body(key)
.build()
.unwrap();
MemoryItem {
dna,
parent_dna: None,
kind: kind.into(),
key: key.into(),
value: format!(r#"{{"k":"{key}"}}"#),
tags,
created_at_ms: ts,
}
}
#[tokio::test]
async fn store_then_query_roundtrip() {
let prefix = fresh_prefix("roundtrip");
let store = RedisStore::from_url(&redis_url(), prefix.clone()).unwrap();
let backend = RedisBackend::new(store, None).unwrap();
let it = dummy_item(&prefix, "trace", "session-1", 1_000, vec!["sleep".into()]);
backend.store(&it).await.expect("store");
let q = MemoryQuery {
kind: Some("trace".into()),
..Default::default()
};
let out = backend.query(&q).await.expect("query");
assert_eq!(out.len(), 1);
assert_eq!(out[0].key, "session-1");
// Cleanup: compact past everything.
let _ = backend.compact(i64::MAX).await;
}
#[tokio::test]
async fn compact_drops_old_items() {
let prefix = fresh_prefix("compact");
let store = RedisStore::from_url(&redis_url(), prefix.clone()).unwrap();
let backend = RedisBackend::new(store, None).unwrap();
let old = dummy_item(&prefix, "trace", "old", 100, vec![]);
let new = dummy_item(&prefix, "trace", "new", 5_000, vec![]);
backend.store(&old).await.unwrap();
backend.store(&new).await.unwrap();
let n = backend.compact(1_000).await.expect("compact");
assert_eq!(n, 1, "exactly the old item should be removed");
let q = MemoryQuery::default();
let remaining = backend.query(&q).await.unwrap();
assert_eq!(remaining.len(), 1);
assert_eq!(remaining[0].key, "new");
let _ = backend.compact(i64::MAX).await;
}
#[tokio::test]
async fn mirror_returns_provider_error() {
let prefix = fresh_prefix("mirror");
let store = RedisStore::from_url(&redis_url(), prefix).unwrap();
let backend = RedisBackend::new(store, None).unwrap();
let r = backend.mirror_to_remote("redis://elsewhere").await;
assert!(r.is_err());
}