use reputation_core::{Calculator, BatchOptions};
use reputation_types::{AgentDataBuilder, AgentData};
use std::time::Instant;
fn create_test_agents(count: usize) -> Vec<AgentData> {
(0..count)
.map(|i| {
let reviews = if i == 0 { 0 } else { i as u32 % 100 };
let rating = if reviews == 0 { None } else { Some(3.0 + (i % 3) as f64 * 0.5) };
let interactions = reviews + (i as u32 % 50);
let mut builder = AgentDataBuilder::new(&format!("did:test:agent{}", i))
.total_interactions(interactions)
.mcp_level((i % 4) as u8)
.identity_verified(i % 2 == 0);
if let Some(r) = rating {
builder = builder.with_reviews(reviews, r);
} else {
builder = builder
.total_reviews(0)
.positive_reviews(0)
.negative_reviews(0);
}
builder.build().unwrap()
})
.collect()
}
#[test]
fn test_basic_batch_processing() {
let calculator = Calculator::default();
let agents = create_test_agents(10);
let results = calculator.calculate_batch(&agents);
assert_eq!(results.len(), agents.len());
for result in &results {
assert!(result.is_ok());
}
}
#[test]
fn test_batch_maintains_order() {
let calculator = Calculator::default();
let agents = create_test_agents(20);
let results = calculator.calculate_batch(&agents);
for (_i, result) in results.iter().enumerate() {
assert!(result.is_ok());
let score = result.as_ref().unwrap();
assert!(score.score >= 0.0 && score.score <= 100.0);
}
}
#[test]
fn test_batch_with_errors() {
let calculator = Calculator::default();
let mut agents = create_test_agents(5);
agents[2].did = "invalid-did".to_string();
let results = calculator.calculate_batch(&agents);
assert_eq!(results.len(), 5);
assert!(results[0].is_ok());
assert!(results[1].is_ok());
assert!(results[2].is_err()); assert!(results[3].is_ok());
assert!(results[4].is_ok());
}
#[test]
fn test_batch_performance() {
let calculator = Calculator::default();
let agents = create_test_agents(1000);
let start = Instant::now();
let results = calculator.calculate_batch(&agents);
let duration = start.elapsed();
assert_eq!(results.len(), 1000);
let successful = results.iter().filter(|r| r.is_ok()).count();
assert_eq!(successful, 1000);
assert!(
duration.as_millis() < 100,
"Batch processing took {:?}, expected < 100ms",
duration
);
println!("Processed 1000 agents in {:?}", duration);
}
#[test]
fn test_batch_with_options() {
let calculator = Calculator::default();
let agents = create_test_agents(100);
let options = BatchOptions {
chunk_size: Some(10),
fail_fast: false,
progress_callback: None,
};
let result = calculator.calculate_batch_with_options(&agents, options);
assert_eq!(result.calculations.len(), 100);
assert_eq!(result.successful_count, 100);
assert_eq!(result.failed_count, 0);
assert!(result.total_duration.as_millis() < 50);
}
#[test]
fn test_batch_with_progress_callback() {
use std::sync::{Arc, Mutex};
let calculator = Calculator::default();
let agents = create_test_agents(50);
let progress_calls = Arc::new(Mutex::new(Vec::new()));
let progress_calls_clone = progress_calls.clone();
let options = BatchOptions {
chunk_size: Some(5),
fail_fast: false,
progress_callback: Some(Box::new(move |current, total| {
progress_calls_clone.lock().unwrap().push((current, total));
})),
};
let result = calculator.calculate_batch_with_options(&agents, options);
assert_eq!(result.calculations.len(), 50);
let calls = progress_calls.lock().unwrap();
assert!(!calls.is_empty());
let max_progress = calls.iter().map(|(current, _)| *current).max().unwrap();
assert_eq!(max_progress, 50);
for (_, total) in calls.iter() {
assert_eq!(*total, 50);
}
}
#[test]
fn test_batch_result_metadata() {
let calculator = Calculator::default();
let mut agents = create_test_agents(10);
agents[5].did = "bad-did".to_string();
let options = BatchOptions::default();
let result = calculator.calculate_batch_with_options(&agents, options);
assert_eq!(result.calculations.len(), 10);
assert_eq!(result.successful_count, 9);
assert_eq!(result.failed_count, 1);
for (i, calc) in result.calculations.iter().enumerate() {
assert_eq!(calc.agent_id, agents[i].did);
assert!(calc.duration.as_nanos() > 0);
if i == 5 {
assert!(calc.result.is_err());
} else {
assert!(calc.result.is_ok());
}
}
}
#[test]
fn test_empty_batch() {
let calculator = Calculator::default();
let agents: Vec<AgentData> = vec![];
let results = calculator.calculate_batch(&agents);
assert!(results.is_empty());
let options = BatchOptions::default();
let batch_result = calculator.calculate_batch_with_options(&agents, options);
assert!(batch_result.calculations.is_empty());
assert_eq!(batch_result.successful_count, 0);
assert_eq!(batch_result.failed_count, 0);
}
#[test]
fn test_single_agent_batch() {
let calculator = Calculator::default();
let agents = create_test_agents(1);
let results = calculator.calculate_batch(&agents);
assert_eq!(results.len(), 1);
assert!(results[0].is_ok());
let single_result = calculator.calculate(&agents[0]).unwrap();
let batch_result = results[0].as_ref().unwrap();
assert_eq!(single_result.score, batch_result.score);
assert_eq!(single_result.confidence, batch_result.confidence);
}
#[test]
fn test_large_batch_memory_efficiency() {
let calculator = Calculator::default();
for size in [100, 500, 1000, 5000] {
let agents = create_test_agents(size);
let start = Instant::now();
let results = calculator.calculate_batch(&agents);
let duration = start.elapsed();
assert_eq!(results.len(), size);
let ms_per_agent = duration.as_micros() as f64 / size as f64;
println!("Batch size {}: {:.2}μs per agent", size, ms_per_agent);
assert!(ms_per_agent < 100.0);
}
}