use chrono::Duration;
use do_memory_core::TaskType;
use do_memory_core::episode::{ApplicationOutcome, Episode, PatternId};
use do_memory_core::pattern::{Pattern, PatternEffectiveness};
use do_memory_core::types::{ComplexityLevel, TaskContext};
#[test]
#[allow(clippy::float_cmp)]
fn test_pattern_effectiveness_creation() {
let effectiveness = PatternEffectiveness::new();
assert_eq!(effectiveness.times_retrieved, 0);
assert_eq!(effectiveness.times_applied, 0);
assert_eq!(effectiveness.success_when_applied, 0);
assert_eq!(effectiveness.failure_when_applied, 0);
assert_eq!(effectiveness.avg_reward_delta, 0.0);
assert_eq!(effectiveness.application_success_rate(), 0.5); }
#[test]
fn test_pattern_effectiveness_record_retrieval() {
let mut effectiveness = PatternEffectiveness::new();
effectiveness.record_retrieval();
effectiveness.record_retrieval();
assert_eq!(effectiveness.times_retrieved, 2);
}
#[test]
#[allow(clippy::float_cmp)]
fn test_pattern_effectiveness_record_application() {
let mut effectiveness = PatternEffectiveness::new();
effectiveness.record_application(true, 0.2);
assert_eq!(effectiveness.times_applied, 1);
assert_eq!(effectiveness.success_when_applied, 1);
assert_eq!(effectiveness.failure_when_applied, 0);
assert_eq!(effectiveness.avg_reward_delta, 0.2);
assert_eq!(effectiveness.application_success_rate(), 1.0);
effectiveness.record_application(false, -0.1);
assert_eq!(effectiveness.times_applied, 2);
assert_eq!(effectiveness.success_when_applied, 1);
assert_eq!(effectiveness.failure_when_applied, 1);
assert_eq!(effectiveness.application_success_rate(), 0.5);
let expected_avg = (0.2 + (-0.1)) / 2.0;
assert!((effectiveness.avg_reward_delta - expected_avg).abs() < 0.001);
}
#[test]
fn test_pattern_effectiveness_score() {
let mut effectiveness = PatternEffectiveness::new();
let initial_score = effectiveness.effectiveness_score();
assert!(initial_score > 0.0);
assert!(initial_score < 1.0);
effectiveness.record_application(true, 0.3);
effectiveness.record_application(true, 0.2);
effectiveness.record_application(true, 0.25);
let good_score = effectiveness.effectiveness_score();
assert!(good_score > initial_score);
let mut bad_effectiveness = PatternEffectiveness::new();
bad_effectiveness.record_application(false, -0.2);
bad_effectiveness.record_application(false, -0.3);
let bad_score = bad_effectiveness.effectiveness_score();
assert!(bad_score < initial_score);
}
#[test]
#[allow(clippy::float_cmp)]
fn test_pattern_usage_rate() {
let mut effectiveness = PatternEffectiveness::new();
effectiveness.record_retrieval();
effectiveness.record_retrieval();
effectiveness.record_retrieval();
assert_eq!(effectiveness.usage_rate(), 0.0);
effectiveness.record_application(true, 0.1);
assert!((effectiveness.usage_rate() - 0.333).abs() < 0.01);
effectiveness.record_application(true, 0.1);
assert!((effectiveness.usage_rate() - 0.666).abs() < 0.01); }
#[test]
fn test_pattern_record_retrieval() {
let context = TaskContext {
language: Some("rust".to_string()),
framework: Some("tokio".to_string()),
complexity: ComplexityLevel::Moderate,
domain: "web-api".to_string(),
tags: vec!["async".to_string()],
};
let mut pattern = Pattern::ToolSequence {
id: uuid::Uuid::new_v4(),
tools: vec!["planner".to_string(), "executor".to_string()],
context: context.clone(),
success_rate: 0.9,
avg_latency: Duration::milliseconds(100),
occurrence_count: 10,
effectiveness: PatternEffectiveness::new(),
};
pattern.record_retrieval();
assert_eq!(pattern.effectiveness().times_retrieved, 1);
pattern.record_retrieval();
assert_eq!(pattern.effectiveness().times_retrieved, 2);
}
#[test]
#[allow(clippy::float_cmp)]
fn test_pattern_record_application() {
let context = TaskContext {
language: Some("rust".to_string()),
framework: Some("tokio".to_string()),
complexity: ComplexityLevel::Moderate,
domain: "web-api".to_string(),
tags: vec!["async".to_string()],
};
let mut pattern = Pattern::ErrorRecovery {
id: uuid::Uuid::new_v4(),
error_type: "timeout".to_string(),
recovery_steps: vec!["retry".to_string(), "fallback".to_string()],
success_rate: 0.8,
context: context.clone(),
effectiveness: PatternEffectiveness::new(),
};
pattern.record_application(true, 0.15);
let eff = pattern.effectiveness();
assert_eq!(eff.times_applied, 1);
assert_eq!(eff.success_when_applied, 1);
assert_eq!(eff.avg_reward_delta, 0.15);
}
#[test]
fn test_episode_pattern_application() {
let context = TaskContext::default();
let mut episode = Episode::new("Test task".to_string(), context, TaskType::Testing);
let pattern_id: PatternId = uuid::Uuid::new_v4();
episode.record_pattern_application(
pattern_id,
1,
ApplicationOutcome::Helped,
Some("Pattern improved efficiency".to_string()),
);
assert_eq!(episode.applied_patterns.len(), 1);
let application = &episode.applied_patterns[0];
assert_eq!(application.pattern_id, pattern_id);
assert_eq!(application.applied_at_step, 1);
assert_eq!(application.outcome, ApplicationOutcome::Helped);
assert!(application.outcome.is_success());
}
#[test]
fn test_application_outcome_is_success() {
assert!(ApplicationOutcome::Helped.is_success());
assert!(!ApplicationOutcome::NoEffect.is_success());
assert!(!ApplicationOutcome::Hindered.is_success());
assert!(!ApplicationOutcome::Pending.is_success());
}
#[test]
#[allow(clippy::float_cmp)]
fn test_pattern_effectiveness_moving_average() {
let mut effectiveness = PatternEffectiveness::new();
effectiveness.record_application(true, 0.5);
assert_eq!(effectiveness.avg_reward_delta, 0.5);
effectiveness.record_application(true, 0.3);
assert!((effectiveness.avg_reward_delta - 0.4).abs() < 0.001);
effectiveness.record_application(true, 0.2);
assert!((effectiveness.avg_reward_delta - 0.333).abs() < 0.01);
}
#[test]
#[allow(clippy::float_cmp)]
fn test_pattern_effectiveness_with_negative_reward() {
let mut effectiveness = PatternEffectiveness::new();
effectiveness.record_application(true, -0.2);
effectiveness.record_application(false, -0.3);
assert_eq!(effectiveness.times_applied, 2);
assert_eq!(effectiveness.success_when_applied, 1);
assert_eq!(effectiveness.application_success_rate(), 0.5);
let expected_avg = (-0.2 + -0.3) / 2.0;
assert!((effectiveness.avg_reward_delta - expected_avg).abs() < 0.001);
let score = effectiveness.effectiveness_score();
assert!(score < 0.5);
}
#[tokio::test]
async fn test_pattern_retrieval_updates_effectiveness() {
use do_memory_core::SelfLearningMemory;
let memory = SelfLearningMemory::new();
let context = TaskContext::default();
let patterns = memory.retrieve_relevant_patterns(&context, 5).await;
assert!(patterns.is_empty() || patterns.len() <= 5);
}