use crate::common::TestDatabaseManager;
use anyhow::Result;
use codex_memory::Storage;
use serial_test::serial;
use sqlx::Row;
use std::sync::Arc;
#[tokio::test]
#[serial]
#[ignore] async fn test_full_user_journey() -> Result<()> {
println!("🚀 Starting E2E test: Complete user journey");
println!("Step 1: Setting up database...");
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let table_exists: bool = sqlx::query(
"SELECT EXISTS (
SELECT FROM information_schema.tables
WHERE table_name = 'memories'
) as exists",
)
.fetch_one(&pool)
.await?
.get("exists");
assert!(table_exists, "Memories table should exist after setup");
println!("✅ Database setup complete");
println!("\nStep 2: Storing various content types...");
let storage = Arc::new(Storage::new(pool.clone()));
let id1 = storage
.store(
"User's important note without any AI processing",
"Direct user note".to_string(),
"User's important note".to_string(),
Some(vec!["important".to_string(), "note".to_string()]),
)
.await?;
println!(" ✅ Stored plain content: {}", id1);
let id2 = storage
.store(
"Error: Connection timeout at line 42",
"Debug session for production issue".to_string(),
"Connection timeout error during debug".to_string(),
Some(vec!["error".to_string(), "debug".to_string()]),
)
.await?;
println!(" ✅ Stored content with context: {}", id2);
let id3 = storage.store(
"The complete implementation of the authentication system includes JWT token generation,
refresh token handling, session management, and role-based access control.
The system uses RS256 for signing tokens and implements automatic token rotation.",
"Code review discussion about auth system".to_string(),
"Authentication system with JWT, refresh tokens, and RBAC".to_string(),
Some(vec!["auth".to_string(), "security".to_string(), "jwt".to_string()])
).await?;
println!(" ✅ Stored content with context and summary: {}", id3);
println!("\nStep 3: Retrieving stored content...");
let memory1 = storage.get(id1).await?.expect("Memory 1 should exist");
assert_eq!(
memory1.content,
"User's important note without any AI processing"
);
assert_eq!(memory1.context, "Direct user note");
assert_eq!(memory1.summary, "User's important note");
println!(" ✅ Retrieved plain content correctly");
let memory2 = storage.get(id2).await?.expect("Memory 2 should exist");
assert_eq!(memory2.context, "Debug session for production issue");
assert_eq!(memory2.summary, "Connection timeout error during debug");
println!(" ✅ Retrieved content with context correctly");
let memory3 = storage.get(id3).await?.expect("Memory 3 should exist");
assert_eq!(memory3.context, "Code review discussion about auth system");
assert_eq!(
memory3.summary,
"Authentication system with JWT, refresh tokens, and RBAC"
);
assert_eq!(memory3.tags.len(), 3);
println!(" ✅ Retrieved content with all fields correctly");
println!("\nStep 4: Testing deduplication...");
let duplicate_id = storage
.store(
"User's important note without any AI processing", "Different context".to_string(),
"Now with a summary".to_string(),
None,
)
.await?;
assert_eq!(
duplicate_id, id1,
"Should return same ID for duplicate content"
);
let updated = storage.get(id1).await?.expect("Memory should exist");
assert_eq!(updated.context, "Different context");
assert_eq!(updated.summary, "Now with a summary");
println!(" ✅ Deduplication working, context/summary updated");
println!("\nStep 5: Checking statistics...");
let stats = storage.stats().await?;
assert_eq!(stats.total_memories, 3); assert!(stats.last_memory_created.is_some());
println!(" ✅ Statistics: {} memories stored", stats.total_memories);
println!("\nStep 6: Listing recent memories...");
let recent = storage.list_recent(10).await?;
assert_eq!(recent.len(), 3);
println!(" ✅ Listed {} recent memories", recent.len());
println!("\nStep 7: Testing deletion...");
let deleted = storage.delete(id2).await?;
assert!(deleted);
assert!(storage.get(id2).await?.is_none());
println!(" ✅ Successfully deleted memory");
let final_stats = storage.stats().await?;
assert_eq!(final_stats.total_memories, 2);
println!("\n🎉 E2E test completed successfully!");
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_batch_operations() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let batch_size = 50;
let start = std::time::Instant::now();
let mut ids = Vec::new();
for i in 0..batch_size {
let content = format!("Batch test content item #{}", i);
let context = format!("Context for item {}", i);
let summary = format!("Summary for item {}", i);
let tags = Some(vec![format!("batch-{}", i), "test".to_string()]);
let id = storage.store(&content, context, summary, tags).await?;
ids.push((id, content));
}
let duration = start.elapsed();
println!("Stored {} items in {:?}", batch_size, duration);
let stats = storage.stats().await?;
assert_eq!(stats.total_memories as usize, batch_size);
for i in [0, 25, 49] {
let retrieved = storage.get(ids[i].0).await?.expect("Should exist");
assert_eq!(retrieved.content, ids[i].1);
}
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_tag_search_scenarios() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool.clone()));
storage
.store(
"Python code",
"Test context".to_string(),
"Test summary".to_string(),
Some(vec!["python".to_string(), "code".to_string()]),
)
.await?;
storage
.store(
"Rust code",
"Test context".to_string(),
"Test summary".to_string(),
Some(vec!["rust".to_string(), "code".to_string()]),
)
.await?;
storage
.store(
"Python tutorial",
"Test context".to_string(),
"Test summary".to_string(),
Some(vec!["python".to_string(), "tutorial".to_string()]),
)
.await?;
storage
.store(
"No tags content",
"Test context".to_string(),
"Test summary".to_string(),
None,
)
.await?;
let results: Vec<String> =
sqlx::query("SELECT content FROM memories WHERE 'python' = ANY(tags)")
.fetch_all(&pool)
.await?
.into_iter()
.map(|row| row.get("content"))
.collect();
assert_eq!(results.len(), 2);
assert!(results.contains(&"Python code".to_string()));
assert!(results.contains(&"Python tutorial".to_string()));
let results: Vec<String> =
sqlx::query("SELECT content FROM memories WHERE tags @> ARRAY['python', 'code']::text[]")
.fetch_all(&pool)
.await?
.into_iter()
.map(|row| row.get("content"))
.collect();
assert_eq!(results.len(), 1);
assert_eq!(results[0], "Python code");
let results: Vec<String> =
sqlx::query("SELECT content FROM memories WHERE array_length(tags, 1) IS NULL")
.fetch_all(&pool)
.await?
.into_iter()
.map(|row| row.get("content"))
.collect();
assert_eq!(results.len(), 1);
assert_eq!(results[0], "No tags content");
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_real_world_patterns() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let code_snippet = r#"
fn fibonacci(n: u32) -> u32 {
match n {
0 => 0,
1 => 1,
_ => fibonacci(n - 1) + fibonacci(n - 2),
}
}
"#;
let id = storage
.store(
code_snippet,
"Learning Rust: recursive functions".to_string(),
"Recursive Fibonacci implementation in Rust".to_string(),
Some(vec![
"rust".to_string(),
"recursion".to_string(),
"fibonacci".to_string(),
]),
)
.await?;
let retrieved = storage.get(id).await?.expect("Should exist");
assert_eq!(retrieved.content, code_snippet);
let error_log = "2024-01-15 10:23:45 ERROR: Database connection timeout after 30s";
storage
.store(
error_log,
"Production incident on API server".to_string(),
"Database connection timeout error log".to_string(),
Some(vec![
"error".to_string(),
"database".to_string(),
"production".to_string(),
]),
)
.await?;
let meeting_notes = "Discussion points:\n- Q1 roadmap\n- Budget allocation\n- Team expansion";
storage
.store(
meeting_notes,
"Q1 planning meeting with stakeholders".to_string(),
"Q1 planning: roadmap, budget, team expansion".to_string(),
Some(vec![
"meeting".to_string(),
"planning".to_string(),
"q1".to_string(),
]),
)
.await?;
let stats = storage.stats().await?;
assert_eq!(stats.total_memories, 3);
manager.cleanup().await?;
Ok(())
}