use crate::common::TestDatabaseManager;
use anyhow::Result;
use codex_memory::Storage;
use serial_test::serial;
use std::sync::Arc;
#[tokio::test]
#[serial]
async fn test_empty_content() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let result = storage
.store(
"",
"Test context".to_string(),
"Test summary".to_string(),
None,
)
.await;
assert!(result.is_ok(), "Empty content should be allowed");
let id = result?;
let retrieved = storage
.get(id)
.await?
.expect("Should retrieve empty content");
assert_eq!(retrieved.content, "");
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_whitespace_only_content() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let whitespace_variations = [
" ", " ", "\t", "\n", "\r\n", " \t\n\r ", ];
for (i, content) in whitespace_variations.iter().enumerate() {
let id = storage
.store(
content,
format!("Whitespace test #{}", i),
"Test summary".to_string(),
None,
)
.await?;
let retrieved = storage
.get(id)
.await?
.expect("Should retrieve whitespace content");
assert_eq!(
retrieved.content, *content,
"Whitespace should be preserved exactly"
);
}
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_unicode_and_emoji_content() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let unicode_tests = [
"Hello 世界", "🎉 🚀 💾 🔥 ⭐", "Ñoño ñoño ÑOÑO", "Здравствуй мир", "مرحبا بالعالم", "🏳️🌈 🏳️⚧️ 👨👩👧👦", "Test\u{0000}null", "Test\u{FEFF}BOM", ];
for (i, content) in unicode_tests.iter().enumerate() {
let result = storage
.store(
content,
format!("Unicode test #{}", i),
"Test summary".to_string(),
None,
)
.await;
match result {
Ok(id) => {
let retrieved = storage
.get(id)
.await?
.expect("Should retrieve unicode content");
assert_eq!(
retrieved.content, *content,
"Unicode content should be preserved exactly"
);
}
Err(e) => {
println!(
"Content '{}' failed as expected: {}",
content.escape_debug(),
e
);
}
}
}
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_large_content_1mb() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let chunk = "This is a test string that will be repeated many times to create large content. ";
let target_size = 1024 * 1024; let repeats = target_size / chunk.len() + 1;
let large_content = chunk.repeat(repeats);
let large_content = &large_content[..target_size];
println!("Testing {}KB content", large_content.len() / 1024);
let start = std::time::Instant::now();
let result = storage
.store(
large_content,
"1MB content test".to_string(),
"Large content performance test".to_string(),
Some(vec!["large".to_string(), "performance".to_string()]),
)
.await;
let storage_time = start.elapsed();
println!("Storage took: {:?}", storage_time);
match result {
Ok(id) => {
let start = std::time::Instant::now();
let retrieved = storage
.get(id)
.await?
.expect("Should retrieve large content");
let retrieval_time = start.elapsed();
println!("Retrieval took: {:?}", retrieval_time);
assert_eq!(retrieved.content.len(), large_content.len());
assert_eq!(retrieved.content, large_content);
assert!(
storage_time < std::time::Duration::from_secs(10),
"Storage should complete within 10 seconds"
);
assert!(
retrieval_time < std::time::Duration::from_secs(5),
"Retrieval should complete within 5 seconds"
);
}
Err(e) => {
println!("Large content failed (may be expected): {}", e);
}
}
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_extremely_large_content_10mb() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let chunk = "Large content test data - this will be repeated to create a very large payload for testing database limits and performance characteristics. ";
let target_size = 10 * 1024 * 1024; let repeats = target_size / chunk.len() + 1;
let huge_content = chunk.repeat(repeats);
let huge_content = &huge_content[..target_size];
println!("Testing {}MB content", huge_content.len() / (1024 * 1024));
let start = std::time::Instant::now();
let result = storage
.store(
huge_content,
"10MB content stress test".to_string(),
"Extremely large content for database limit testing".to_string(),
Some(vec!["stress".to_string(), "limit".to_string()]),
)
.await;
let storage_time = start.elapsed();
println!("Storage attempt took: {:?}", storage_time);
match result {
Ok(id) => {
println!("Successfully stored 10MB content");
let start = std::time::Instant::now();
let retrieved = storage
.get(id)
.await?
.expect("Should retrieve huge content");
let retrieval_time = start.elapsed();
println!("Retrieval took: {:?}", retrieval_time);
assert_eq!(retrieved.content.len(), huge_content.len());
assert_eq!(&retrieved.content[..1000], &huge_content[..1000]);
assert_eq!(
&retrieved.content[retrieved.content.len() - 1000..],
&huge_content[huge_content.len() - 1000..]
);
}
Err(e) => {
println!(
"10MB content failed (may be expected due to database limits): {}",
e
);
}
}
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_binary_data_handling() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let binary_patterns = [
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"89504e470d0a1a0a0000000d494844520000000100000001080200000090773645000000",
"\x00\x01\x02\x03invalid", r#"{"data": "binary_data_here", "encoding": "base64"}"#,
];
for (i, content) in binary_patterns.iter().enumerate() {
let result = storage
.store(
content,
format!("Binary test #{}", i),
"Test summary".to_string(),
None,
)
.await;
match result {
Ok(id) => {
let retrieved = storage
.get(id)
.await?
.expect("Should retrieve binary content");
assert_eq!(
retrieved.content, *content,
"Binary content should be preserved"
);
println!("Binary pattern #{} stored successfully", i);
}
Err(e) => {
println!(
"Binary pattern #{} failed (may be expected for invalid UTF-8): {}",
i, e
);
}
}
}
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_content_with_sql_like_patterns() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let sql_patterns = [
"'; DROP TABLE memories; --",
"SELECT * FROM memories WHERE id = '1'",
"INSERT INTO memories VALUES ('evil', 'content')",
"' OR '1'='1",
"'; DELETE FROM memories; --",
"UNION SELECT password FROM users",
r#"{"key": "'; DROP TABLE memories; --"}"#,
"Content with single ' quotes",
r#"Content with "double quotes""#,
"Content with `backticks`",
"Content with $1 parameter-like $$ strings",
];
for (i, content) in sql_patterns.iter().enumerate() {
let id = storage
.store(
content,
format!("SQL injection test #{}", i),
"Testing content that might cause SQL issues".to_string(),
Some(vec!["sql".to_string(), "security".to_string()]),
)
.await?;
let retrieved = storage
.get(id)
.await?
.expect("Should retrieve SQL-like content");
assert_eq!(
retrieved.content, *content,
"SQL-like content should be stored safely"
);
}
let stats = storage.stats().await?;
assert_eq!(stats.total_memories, sql_patterns.len() as i64);
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_extremely_long_single_line() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let word = "supercalifragilisticexpialidocious";
let long_line = word.repeat(10000);
println!("Testing single line of {} characters", long_line.len());
let result = storage
.store(
&long_line,
"Extremely long single line test".to_string(),
"Testing single line content limits".to_string(),
Some(vec!["long".to_string(), "line".to_string()]),
)
.await;
match result {
Ok(id) => {
let retrieved = storage.get(id).await?.expect("Should retrieve long line");
assert_eq!(retrieved.content.len(), long_line.len());
assert_eq!(retrieved.content, long_line);
println!("Long single line stored and retrieved successfully");
}
Err(e) => {
println!("Long single line failed: {}", e);
}
}
manager.cleanup().await?;
Ok(())
}
#[tokio::test]
#[serial]
async fn test_content_hash_collision_simulation() -> Result<()> {
let mut manager = TestDatabaseManager::new()?;
let pool = manager.setup_test_database().await?;
let storage = Arc::new(Storage::new(pool));
let content = "This content will be stored multiple times to test hash collision handling";
let id1 = storage
.store(
content,
"First instance".to_string(),
"First summary".to_string(),
None,
)
.await?;
let id2 = storage
.store(
content,
"Second instance".to_string(),
"Second summary".to_string(),
None,
)
.await?;
assert_eq!(id1, id2, "Identical content should deduplicate to same ID");
let retrieved = storage
.get(id1)
.await?
.expect("Should retrieve deduplicated content");
assert_eq!(retrieved.content, content);
assert_eq!(retrieved.context, "Second instance".to_string());
assert_eq!(retrieved.summary, "Second summary".to_string());
manager.cleanup().await?;
Ok(())
}