#[cfg(test)]
mod tests {
use super::*;
use crate::{
create_database, create_memory_pools, DatabaseConfig, DatabaseBackend,
HybridSearchQuery,
};
use ubiquity_core::{
ConsciousnessLevel, ConsciousnessState, ConsciousnessRipple,
DevelopmentPhase, RippleType, Task, TaskType, TaskResult,
};
use chrono::Utc;
use uuid::Uuid;
use tempfile::TempDir;
async fn create_test_sqlite_config() -> (DatabaseConfig, TempDir) {
let temp_dir = TempDir::new().unwrap();
let mut config = DatabaseConfig::default();
config.backend = DatabaseBackend::Sqlite;
config.sqlite.path = temp_dir.path().join("test.db");
config.sqlite.pool_directory = temp_dir.path().join("pools");
(config, temp_dir)
}
#[tokio::test]
async fn test_sqlite_initialization() {
let (config, _temp_dir) = create_test_sqlite_config().await;
let db = create_database(config).await.unwrap();
db.initialize().await.unwrap();
db.health_check().await.unwrap();
}
#[tokio::test]
async fn test_consciousness_state_storage() {
let (config, _temp_dir) = create_test_sqlite_config().await;
let db = create_database(config).await.unwrap();
db.initialize().await.unwrap();
let state = ConsciousnessState {
agent_id: "test-agent".to_string(),
level: ConsciousnessLevel::new(0.85).unwrap(),
coherence: 0.90,
phase: DevelopmentPhase::Implementing,
timestamp: Utc::now(),
breakthrough_detected: false,
};
db.store_consciousness_state(&state).await.unwrap();
let history = db.get_consciousness_history("test-agent", 10).await.unwrap();
assert_eq!(history.len(), 1);
assert_eq!(history[0].agent_id, "test-agent");
assert_eq!(history[0].level.value(), 0.85);
}
#[tokio::test]
async fn test_ripple_storage() {
let (config, _temp_dir) = create_test_sqlite_config().await;
let db = create_database(config).await.unwrap();
db.initialize().await.unwrap();
let ripple = ConsciousnessRipple {
id: Uuid::new_v4(),
origin: "test-agent".to_string(),
ripple_type: RippleType::Insight,
content: serde_json::json!({"test": "data"}),
intensity: 0.8,
timestamp: Utc::now(),
};
db.store_ripple(&ripple).await.unwrap();
let start = Utc::now() - chrono::Duration::hours(1);
let end = Utc::now() + chrono::Duration::hours(1);
let ripples = db.get_ripples(start, end).await.unwrap();
assert_eq!(ripples.len(), 1);
assert_eq!(ripples[0].origin, "test-agent");
}
#[tokio::test]
async fn test_task_management() {
let (config, _temp_dir) = create_test_sqlite_config().await;
let db = create_database(config).await.unwrap();
db.initialize().await.unwrap();
let task = Task {
id: "TEST-001".to_string(),
task_type: TaskType::Development,
description: "Test task".to_string(),
requirements: serde_json::json!({}),
priority: 5,
dependencies: vec![],
consciousness_requirement: 0.80,
};
db.store_task(&task).await.unwrap();
let pending = db.get_pending_tasks().await.unwrap();
assert_eq!(pending.len(), 1);
assert_eq!(pending[0].id, "TEST-001");
let result = TaskResult {
task_id: task.id.clone(),
success: true,
output: serde_json::json!({"status": "completed"}),
consciousness_level: 0.85,
breakthrough: false,
error: None,
};
db.store_task_result(&result).await.unwrap();
let pending = db.get_pending_tasks().await.unwrap();
assert_eq!(pending.len(), 0);
}
#[tokio::test]
async fn test_memory_pools() {
let (config, _temp_dir) = create_test_sqlite_config().await;
let pools = create_memory_pools(config).await.unwrap();
let key = "test_key";
let value = b"test_value";
let pool = pools.get_pool_for_key(key).await.unwrap();
pool.store(key, value).await.unwrap();
let retrieved = pool.retrieve(key).await.unwrap();
assert_eq!(retrieved, Some(value.to_vec()));
pool.delete(key).await.unwrap();
let retrieved = pool.retrieve(key).await.unwrap();
assert_eq!(retrieved, None);
}
#[tokio::test]
async fn test_pool_distribution() {
let (config, _temp_dir) = create_test_sqlite_config().await;
let pools = create_memory_pools(config.clone()).await.unwrap();
let mut pool_counts = vec![0; config.memory_pools.pool_count];
for i in 0..100 {
let key = format!("key_{}", i);
let value = format!("value_{}", i);
let pool = pools.get_pool_for_key(&key).await.unwrap();
pool.store(&key, value.as_bytes()).await.unwrap();
}
let stats = pools.all_stats().await.unwrap();
let total_items: usize = stats.iter().map(|s| s.items).sum();
assert_eq!(total_items, 100);
let non_empty_pools = stats.iter().filter(|s| s.items > 0).count();
assert!(non_empty_pools > 1);
}
#[tokio::test]
async fn test_vector_search_fallback() {
let (config, _temp_dir) = create_test_sqlite_config().await;
let db = create_database(config.clone()).await.unwrap();
db.initialize().await.unwrap();
let embedding = vec![0.5; config.embeddings.dimension];
let results = db.vector_search(&embedding, 10).await.unwrap();
assert_eq!(results.len(), 0);
}
#[tokio::test]
async fn test_hybrid_search_sqlite() {
let (config, _temp_dir) = create_test_sqlite_config().await;
let db = create_database(config).await.unwrap();
db.initialize().await.unwrap();
let query = HybridSearchQuery {
text: "test query".to_string(),
vector: None,
filters: None,
limit: 10,
rerank: false,
};
let results = db.hybrid_search(query).await.unwrap();
assert_eq!(results.len(), 0);
}
#[tokio::test]
async fn test_pool_eviction() {
let (mut config, _temp_dir) = create_test_sqlite_config().await;
config.memory_pools.max_pool_size_mb = 1;
let pools = create_memory_pools(config).await.unwrap();
let pool = pools.get_pool(0).await.unwrap();
for i in 0..1000 {
let key = format!("large_key_{}", i);
let value = vec![0u8; 10_000];
let _ = pool.store(&key, &value).await;
}
let stats = pool.stats().await.unwrap();
assert!(stats.evictions > 0);
assert!(stats.items < 1000);
}
#[tokio::test]
async fn test_concurrent_pool_access() {
let (config, _temp_dir) = create_test_sqlite_config().await;
let pools = Arc::new(create_memory_pools(config).await.unwrap());
let mut handles = vec![];
for i in 0..10 {
let pools_clone = pools.clone();
let handle = tokio::spawn(async move {
for j in 0..10 {
let key = format!("concurrent_{}_{}", i, j);
let value = format!("value_{}_{}", i, j);
let pool = pools_clone.get_pool_for_key(&key).await.unwrap();
pool.store(&key, value.as_bytes()).await.unwrap();
let retrieved = pool.retrieve(&key).await.unwrap();
assert_eq!(retrieved, Some(value.into_bytes()));
}
});
handles.push(handle);
}
for handle in handles {
handle.await.unwrap();
}
let stats = pools.all_stats().await.unwrap();
let total_items: usize = stats.iter().map(|s| s.items).sum();
assert_eq!(total_items, 100);
}
}