use umi_memory::umi::{Memory, MemoryConfig, RecallOptions, RememberOptions};
#[tokio::test]
async fn test_semantic_search_finds_similar_content() {
let mut memory = Memory::sim(42);
memory
.remember(
"Alice is a software engineer at Acme Corp",
RememberOptions::default(),
)
.await
.unwrap();
memory
.remember("Bob works as a developer at TechCo", RememberOptions::default())
.await
.unwrap();
memory
.remember("The weather today is sunny", RememberOptions::default())
.await
.unwrap();
let results = memory
.recall("Who are the programmers?", RecallOptions::default())
.await
.unwrap();
assert!(
!results.is_empty(),
"Should find engineer-related results via semantic search"
);
let has_engineer_content = results.iter().any(|e| {
e.name.to_lowercase().contains("alice")
|| e.name.to_lowercase().contains("bob")
|| e.content.to_lowercase().contains("engineer")
|| e.content.to_lowercase().contains("developer")
|| e.content.to_lowercase().contains("software")
});
assert!(
has_engineer_content,
"Should find at least one engineer-related entity"
);
}
#[tokio::test]
async fn test_memory_full_workflow() {
let mut memory = Memory::sim(42);
let result1 = memory
.remember("Alice works at Acme Corp", RememberOptions::default())
.await
.unwrap();
assert!(
!result1.entities.is_empty(),
"Should extract entities from first remember"
);
println!("First remember: extracted {} entities", result1.entity_count());
let result2 = memory
.remember("Alice now works at TechCo", RememberOptions::default())
.await
.unwrap();
assert!(
!result2.entities.is_empty(),
"Should extract entities from second remember"
);
println!(
"Second remember: extracted {} entities, {} evolutions",
result2.entity_count(),
result2.evolutions.len()
);
if result2.has_evolutions() {
println!("Evolution detected: {:?}", result2.evolutions);
}
let results = memory
.recall("Alice", RecallOptions::default())
.await
.unwrap();
assert!(
!results.is_empty(),
"Recall should find entities mentioning Alice"
);
println!("Recall found {} results", results.len());
}
#[tokio::test]
async fn test_remember_and_recall_basic() {
let mut memory = Memory::sim(42);
let result = memory
.remember("The sky is blue", RememberOptions::default())
.await
.unwrap();
assert!(!result.entities.is_empty(), "Should extract entities");
let results = memory
.recall("sky", RecallOptions::default())
.await
.unwrap();
assert!(!results.is_empty(), "Should recall stored information");
}
#[tokio::test]
async fn test_multiple_entities_extraction() {
let mut memory = Memory::sim(42);
let result = memory
.remember(
"Alice and Bob work together at Acme Corp on the new project",
RememberOptions::default(),
)
.await
.unwrap();
assert!(
result.entity_count() >= 1,
"Should extract at least one entity from multi-entity text"
);
println!(
"Extracted {} entities from multi-entity text",
result.entity_count()
);
for entity in result.iter_entities() {
println!(" - Entity: {}", entity.name);
}
}
#[tokio::test]
async fn test_entity_extraction_with_relationships() {
let mut memory = Memory::sim(42);
let result = memory
.remember(
"Alice manages the engineering team at Acme Corp",
RememberOptions::default(),
)
.await
.unwrap();
assert!(
!result.entities.is_empty(),
"Should extract entities with relationships"
);
println!(
"Extracted {} entities from relationship text",
result.entity_count()
);
}
#[tokio::test]
async fn test_config_without_embeddings() {
let config = MemoryConfig::default().without_embeddings();
let mut memory = Memory::sim_with_config(42, config);
let result = memory
.remember("Test entity", RememberOptions::default())
.await
.unwrap();
assert!(
!result.entities.is_empty(),
"Should work without embeddings (graceful degradation)"
);
let results = memory
.recall("test", RecallOptions::default())
.await
.unwrap();
println!("Recall found {} results without embeddings", results.len());
}
#[tokio::test]
async fn test_config_custom_recall_limit() {
let config = MemoryConfig::default().with_recall_limit(3);
let mut memory = Memory::sim_with_config(42, config);
for i in 0..10 {
memory
.remember(
&format!("Entity {} is a test item", i),
RememberOptions::default(),
)
.await
.unwrap();
}
let results = memory
.recall("entity", RecallOptions::default())
.await
.unwrap();
println!(
"Recall found {} results (config.default_recall_limit=3)",
results.len()
);
assert!(results.len() <= 10, "Should respect maximum recall limit");
}
#[tokio::test]
async fn test_remember_without_extraction() {
let mut memory = Memory::sim(42);
let result = memory
.remember(
"Test content",
RememberOptions::default().without_extraction(),
)
.await
.unwrap();
println!(
"Remember without extraction: {} entities",
result.entity_count()
);
}
#[tokio::test]
async fn test_remember_without_evolution() {
let mut memory = Memory::sim(42);
memory
.remember("Alice works at Acme", RememberOptions::default())
.await
.unwrap();
let result = memory
.remember(
"Alice works at TechCo",
RememberOptions::default().without_evolution(),
)
.await
.unwrap();
assert!(
!result.has_evolutions(),
"Should not detect evolution when disabled"
);
}
#[tokio::test]
async fn test_recall_with_limit() {
let mut memory = Memory::sim(42);
for i in 0..20 {
memory
.remember(
&format!("Item {} is a test entity", i),
RememberOptions::default(),
)
.await
.unwrap();
}
let results = memory
.recall("item", RecallOptions::default().with_limit(5))
.await
.unwrap();
assert!(
results.len() <= 5,
"Should respect explicit recall limit: got {} results",
results.len()
);
}
#[tokio::test]
async fn test_recall_empty_query() {
let mut memory = Memory::sim(42);
memory
.remember("Test data", RememberOptions::default())
.await
.unwrap();
let result = memory.recall("", RecallOptions::default()).await;
assert!(result.is_err(), "Empty query should return error");
}
#[tokio::test]
async fn test_concurrent_remember() {
let mut memory = Memory::sim(42);
let result1 = memory
.remember("Fact 1", RememberOptions::default())
.await
.unwrap();
let result2 = memory
.remember("Fact 2", RememberOptions::default())
.await
.unwrap();
assert!(!result1.entities.is_empty());
assert!(!result2.entities.is_empty());
}