#[ allow( unused_imports ) ]
use super::*;
use std::time::{ Duration, Instant };
#[ test ]
fn test_performance_metrics_creation()
{
let metrics = the_module::PerformanceMetrics::new();
assert!( metrics.is_empty() );
assert_eq!( metrics.operation_count(), 0 );
}
#[ test ]
fn test_performance_metrics_record_operation()
{
let mut metrics = the_module::PerformanceMetrics::new();
let start = Instant::now();
std::thread::sleep( Duration::from_millis( 10 ) );
let duration = start.elapsed();
metrics.record_operation( "test_operation", duration );
assert!( !metrics.is_empty() );
assert_eq!( metrics.operation_count(), 1 );
}
#[ test ]
fn test_performance_metrics_multiple_operations()
{
let mut metrics = the_module::PerformanceMetrics::new();
for i in 0..10
{
metrics.record_operation( "operation_type_1", Duration::from_millis( i * 10 ) );
}
for i in 0..5
{
metrics.record_operation( "operation_type_2", Duration::from_millis( i * 5 ) );
}
assert_eq!( metrics.operation_count(), 2 ); }
#[ test ]
fn test_performance_metrics_get_stats()
{
let mut metrics = the_module::PerformanceMetrics::new();
metrics.record_operation( "test_op", Duration::from_millis( 100 ) );
metrics.record_operation( "test_op", Duration::from_millis( 200 ) );
metrics.record_operation( "test_op", Duration::from_millis( 150 ) );
let stats = metrics.get_stats( "test_op" ).expect( "Stats must exist" );
assert_eq!( stats.count(), 3 );
assert_eq!( stats.total_duration(), Duration::from_millis( 450 ) );
assert_eq!( stats.average_duration(), Duration::from_millis( 150 ) );
assert_eq!( stats.min_duration(), Duration::from_millis( 100 ) );
assert_eq!( stats.max_duration(), Duration::from_millis( 200 ) );
}
#[ test ]
fn test_performance_metrics_aggregation()
{
let mut metrics1 = the_module::PerformanceMetrics::new();
let mut metrics2 = the_module::PerformanceMetrics::new();
metrics1.record_operation( "op_a", Duration::from_millis( 100 ) );
metrics1.record_operation( "op_a", Duration::from_millis( 200 ) );
metrics2.record_operation( "op_a", Duration::from_millis( 150 ) );
metrics2.record_operation( "op_b", Duration::from_millis( 50 ) );
metrics1.merge( metrics2 );
assert_eq!( metrics1.operation_count(), 2 ); assert_eq!( metrics1.get_stats( "op_a" ).unwrap().count(), 3 );
assert_eq!( metrics1.get_stats( "op_b" ).unwrap().count(), 1 );
}
#[ test ]
fn test_performance_metrics_percentiles()
{
let mut metrics = the_module::PerformanceMetrics::new();
for i in 0..100
{
metrics.record_operation( "test_op", Duration::from_millis( i ) );
}
let stats = metrics.get_stats( "test_op" ).unwrap();
assert_eq!( stats.p50(), Duration::from_millis( 50 ) ); assert_eq!( stats.p95(), Duration::from_millis( 95 ) ); assert_eq!( stats.p99(), Duration::from_millis( 99 ) ); }
#[ test ]
fn test_performance_metrics_throughput()
{
let mut metrics = the_module::PerformanceMetrics::new();
let start_time = Instant::now();
for _ in 0..100
{
metrics.record_operation( "throughput_test", Duration::from_millis( 10 ) );
}
let elapsed = start_time.elapsed();
let throughput = metrics.calculate_throughput( "throughput_test", elapsed );
assert!( throughput > 0.0 );
println!( "Throughput : {} ops/sec", throughput );
}
#[ test ]
fn test_performance_metrics_report_generation()
{
let mut metrics = the_module::PerformanceMetrics::new();
metrics.record_operation( "api_call", Duration::from_millis( 250 ) );
metrics.record_operation( "api_call", Duration::from_millis( 300 ) );
metrics.record_operation( "serialization", Duration::from_millis( 5 ) );
let report = metrics.generate_report();
assert!( !report.is_empty() );
assert!( report.contains( "api_call" ) );
assert!( report.contains( "serialization" ) );
}
#[ test ]
fn test_performance_metrics_json_export()
{
let mut metrics = the_module::PerformanceMetrics::new();
metrics.record_operation( "test_op", Duration::from_millis( 100 ) );
let json = metrics.to_json().expect( "JSON export must work" );
assert!( json.contains( "test_op" ) );
assert!( json.contains( "count" ) );
assert!( json.contains( "average_duration" ) );
}
#[ test ]
fn test_performance_monitoring_zero_overhead_disabled()
{
let start = Instant::now();
for _ in 0..10000
{
let _result = simple_operation();
}
let duration_without_monitoring = start.elapsed();
let start = Instant::now();
for _ in 0..10000
{
let _result = simple_operation();
the_module::PerformanceMonitor::record_if_enabled( "operation", Duration::ZERO );
}
let duration_with_disabled_monitoring = start.elapsed();
let overhead_ratio = duration_with_disabled_monitoring.as_micros() as f64 / duration_without_monitoring.as_micros() as f64;
assert!( overhead_ratio < 2.0, "Disabled monitoring has too much overhead : {overhead_ratio}x" );
println!( "✅ Zero overhead test passed!" );
println!( " Without monitoring : {:?}", duration_without_monitoring );
println!( " With disabled monitoring : {:?}", duration_with_disabled_monitoring );
println!( " Overhead ratio : {:.2}x", overhead_ratio );
}
fn simple_operation() -> u64
{
( 1..100 ).sum()
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
#[ ignore = "Requires workspace secrets file" ]
async fn integration_performance_monitoring_api_request()
{
let client = the_module::Client::from_workspace()
.expect( "INTEGRATION: Must have valid API key" );
let mut monitor = the_module::PerformanceMonitor::new();
let start = Instant::now();
let request = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 20,
messages : vec![ the_module::Message::user( "Hello!".to_string() ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
#[ cfg( feature = "tools" ) ]
tools : None,
#[ cfg( feature = "tools" ) ]
tool_choice : None,
};
let response = match client.create_message( request ).await
{
Ok( response ) => response,
Err( the_module::AnthropicError::Api( ref api_err ) ) if api_err.message.contains( "credit balance is too low" ) =>
{
println!( "INTEGRATION TEST SKIPPED: Credit balance exhausted" );
return;
},
Err( err ) => panic!( "INTEGRATION: API call must work : {err}" ),
};
let duration = start.elapsed();
monitor.record_api_call( "create_message", duration, true );
let stats = monitor.get_stats( "create_message" ).expect( "Stats must exist" );
assert_eq!( stats.count(), 1 );
assert!( stats.total_duration() > Duration::ZERO );
assert!( !response.id.is_empty() );
println!( "✅ API request monitoring integration test passed!" );
println!( " Request duration : {:?}", duration );
println!( " Monitored stats : {} calls, avg {:?}", stats.count(), stats.average_duration() );
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
#[ ignore = "Requires workspace secrets file" ]
async fn integration_performance_monitoring_multiple_requests()
{
let client = the_module::Client::from_workspace()
.expect( "INTEGRATION: Must have valid API key" );
let mut monitor = the_module::PerformanceMonitor::new();
for i in 0..3
{
let start = Instant::now();
let request = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 15,
messages : vec![ the_module::Message::user( format!( "Test {i}" ) ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
#[ cfg( feature = "tools" ) ]
tools : None,
#[ cfg( feature = "tools" ) ]
tool_choice : None,
};
let result = client.create_message( request ).await;
let duration = start.elapsed();
let success = result.is_ok();
match result
{
Ok( response ) => {
assert!( !response.id.is_empty() );
monitor.record_api_call( "create_message", duration, success );
},
Err( the_module::AnthropicError::Api( ref api_err ) ) if api_err.message.contains( "credit balance is too low" ) =>
{
println!( "INTEGRATION TEST SKIPPED: Credit balance exhausted on request {i}" );
return;
},
Err( err ) => panic!( "Request {i} failed : {err}" ),
}
}
let stats = monitor.get_stats( "create_message" ).expect( "Stats must exist" );
assert_eq!( stats.count(), 3 );
assert!( stats.total_duration() > Duration::ZERO );
let report = monitor.generate_report();
assert!( report.contains( "create_message" ) );
assert!( report.contains( '3' ) );
println!( "✅ Multiple requests monitoring integration test passed!" );
println!( " Total requests : {}", stats.count() );
println!( " Average duration : {:?}", stats.average_duration() );
println!( " Min duration : {:?}", stats.min_duration() );
println!( " Max duration : {:?}", stats.max_duration() );
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
#[ ignore = "Requires workspace secrets file" ]
async fn integration_performance_monitoring_throughput_measurement()
{
let client = the_module::Client::from_workspace()
.expect( "INTEGRATION: Must have valid API key" );
let mut monitor = the_module::PerformanceMonitor::new();
let overall_start = Instant::now();
for i in 0..5
{
let start = Instant::now();
let request = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 10,
messages : vec![ the_module::Message::user( format!( "Throughput test {i}" ) ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
#[ cfg( feature = "tools" ) ]
tools : None,
#[ cfg( feature = "tools" ) ]
tool_choice : None,
};
let result = client.create_message( request ).await;
let duration = start.elapsed();
match result
{
Ok( _response ) => {
monitor.record_api_call( "create_message", duration, true );
},
Err( the_module::AnthropicError::Api( ref api_err ) ) if api_err.message.contains( "credit balance is too low" ) =>
{
println!( "INTEGRATION TEST SKIPPED: Credit balance exhausted on request {i}" );
return;
},
Err( err ) => panic!( "Request {i} failed : {err}" ),
}
}
let total_elapsed = overall_start.elapsed();
let throughput = monitor.calculate_throughput( "create_message", total_elapsed );
assert!( throughput > 0.0 );
assert!( throughput < 100.0 );
println!( "✅ Throughput measurement integration test passed!" );
println!( " Total time : {:?}", total_elapsed );
println!( " Throughput : {:.2} requests/sec", throughput );
println!( " Average latency : {:?}", monitor.get_stats( "create_message" ).unwrap().average_duration() );
}