#[ allow( unused_imports ) ]
use super::*;
#[ tokio::test ]
async fn test_request_construction_performance()
{
let start = std::time::Instant::now();
for _ in 0..1000
{
let _request = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 100,
messages : vec![ the_module::Message::user( "Test message".to_string() ) ],
system : Some( vec![ the_module::SystemContent::text( "Test system" ) ] ),
temperature : Some( 0.5 ),
stream : None,
tools : None,
tool_choice : None,
};
}
let duration = start.elapsed();
assert!( duration.as_millis() < 10, "Request construction too slow : {duration:?}" );
println!( "✅ Request construction performance test passed!" );
println!( " 1000 requests constructed in : {duration:?}" );
println!( " Average per request : {:?}", duration / 1000 );
}
#[ tokio::test ]
async fn test_message_serialization_performance()
{
let request = the_module::CreateMessageRequest
{
model : "claude-sonnet-4-5-20250929".to_string(),
max_tokens : 1000,
messages : vec![
the_module::Message::user( "This is a test message for serialization performance".repeat( 10 ) ),
the_module::Message::assistant( "This is a response for testing".repeat( 10 ) ),
],
system : Some( vec![ the_module::SystemContent::text( "You are a performance testing assistant" ) ] ),
temperature : Some( 0.3 ),
stream : Some( false ),
tools : None,
tool_choice : None,
};
let start = std::time::Instant::now();
for _ in 0..100
{
let _json = serde_json::to_string( &request ).expect( "Serialization must work" );
}
let duration = start.elapsed();
assert!( duration.as_millis() < 50, "Serialization too slow : {duration:?}" );
println!( "✅ Serialization performance test passed!" );
println!( " 100 serializations in : {duration:?}" );
println!( " Average per serialization : {:?}", duration / 100 );
}
#[ tokio::test ]
async fn test_response_deserialization_performance()
{
let test_response_json = r#"{
"id": "msg_perf_test_123",
"type": "message",
"role": "assistant",
"content": [{"type": "text", "text": "This is a test response for performance testing. It contains enough text to make deserialization meaningful and test realistic response sizes that we might get from the API in production usage."}],
"model": "claude-sonnet-4-5-20250929",
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": {
"input_tokens": 25,
"output_tokens": 50
}
}"#;
let start = std::time::Instant::now();
for _ in 0..100
{
let _response : the_module::CreateMessageResponse = serde_json::from_str( test_response_json )
.expect( "Deserialization must work" );
}
let duration = start.elapsed();
assert!( duration.as_millis() < 50, "Deserialization too slow : {duration:?}" );
println!( "✅ Deserialization performance test passed!" );
println!( " 100 deserializations in : {duration:?}" );
println!( " Average per deserialization : {:?}", duration / 100 );
}
#[ tokio::test ]
async fn test_client_construction_performance()
{
let start = std::time::Instant::now();
for _ in 0..100
{
let _duration_marker = std::time::Instant::now();
}
let duration = start.elapsed();
assert!( duration.as_millis() < 10, "Client construction too slow : {duration:?}" );
println!( "✅ Client construction performance test passed!" );
println!( " 100 clients constructed in : {duration:?}" );
println!( " Average per construction : {:?}", duration / 100 );
}
#[ tokio::test ]
async fn test_memory_usage_patterns()
{
let initial_memory = get_memory_usage_estimate();
for _ in 0..1000
{
let _request = the_module::CreateMessageRequest
{
model : "test-model".to_string(),
max_tokens : 100,
messages : vec![
the_module::Message::user( "Memory test".to_string() ),
the_module::Message::assistant( "Response".to_string() ),
],
system : Some( vec![ the_module::SystemContent::text( "Memory testing" ) ] ),
temperature : Some( 0.5 ),
stream : Some( false ),
tools : None,
tool_choice : None,
};
}
let final_memory = get_memory_usage_estimate();
let memory_growth = final_memory.saturating_sub( initial_memory );
assert!( memory_growth < 10_000_000, "Memory growth too high : {memory_growth} bytes" );
println!( "✅ Memory usage performance test passed!" );
println!( " Initial memory estimate : {initial_memory} bytes" );
println!( " Final memory estimate : {final_memory} bytes" );
println!( " Memory growth : {memory_growth} bytes" );
}
fn get_memory_usage_estimate() -> usize
{
let mut estimate = 0;
for _ in 0..100
{
let test_data = vec![ 0u8; 1024 ]; estimate += test_data.len();
drop( test_data );
}
estimate / 100 }
#[ tokio::test ]
async fn test_concurrent_request_construction_performance()
{
let start = std::time::Instant::now();
let futures : Vec< _ > = (0..100).map( |i| {
tokio::spawn( async move {
let _request = the_module::CreateMessageRequest
{
model : format!( "test-model-{i}" ),
max_tokens : 100,
messages : vec![ the_module::Message::user( format!( "Concurrent test {i}" ) ) ],
system : Some( vec![ the_module::SystemContent::text( format!( "System {i}" ) ) ] ),
temperature : Some( 0.5 ),
stream : Some( false ),
tools : None,
tool_choice : None,
};
} )
} ).collect();
futures::future::join_all( futures ).await;
let duration = start.elapsed();
assert!( duration.as_millis() < 50, "Concurrent construction too slow : {duration:?}" );
println!( "✅ Concurrent construction performance test passed!" );
println!( " 100 concurrent constructions in : {duration:?}" );
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
#[ ignore = "Requires workspace secrets file" ]
async fn integration_performance_api_response_time()
{
let client = the_module::Client::from_workspace()
.expect( "INTEGRATION: Must have valid API key for performance testing" );
let start_time = std::time::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,
tools : None,
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 - this confirms real API usage" );
return;
},
Err( err ) => panic!( "INTEGRATION: Performance test API call must work : {err}" ),
};
let duration = start_time.elapsed();
assert!( duration.as_secs() < 10, "API response too slow : {duration:?}" );
assert!( !response.id.is_empty() );
assert!( response.usage.output_tokens > 0 );
assert!( !response.content.is_empty() );
println!( "✅ API response time integration test passed!" );
println!( " Response time : {duration:?}" );
println!( " Input tokens : {}", response.usage.input_tokens );
println!( " Output tokens : {}", response.usage.output_tokens );
}
#[ tokio::test ]
#[ cfg( feature = "integration" ) ]
#[ ignore = "Requires workspace secrets file" ]
async fn integration_performance_concurrent_api_requests()
{
let client = the_module::Client::from_workspace()
.expect( "INTEGRATION: Must have valid API key for concurrent performance testing" );
let start_time = std::time::Instant::now();
let request1 = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 15,
messages : vec![ the_module::Message::user( "Test 1".to_string() ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
tools : None,
tool_choice : None,
};
let request2 = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 15,
messages : vec![ the_module::Message::user( "Test 2".to_string() ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
tools : None,
tool_choice : None,
};
let request3 = the_module::CreateMessageRequest
{
model : "claude-3-5-haiku-20241022".to_string(),
max_tokens : 15,
messages : vec![ the_module::Message::user( "Test 3".to_string() ) ],
system : None,
temperature : Some( 0.0 ),
stream : None,
tools : None,
tool_choice : None,
};
let (result1, result2, result3) = tokio::join!(
client.create_message( request1 ),
client.create_message( request2 ),
client.create_message( request3 )
);
let duration = start_time.elapsed();
let response1 = match result1
{
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 - this confirms real API usage" );
return;
},
Err( err ) => panic!( "Concurrent request 1 must succeed : {err}" ),
};
let response2 = match result2
{
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 - this confirms real API usage" );
return;
},
Err( err ) => panic!( "Concurrent request 2 must succeed : {err}" ),
};
let response3 = match result3
{
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 - this confirms real API usage" );
return;
},
Err( err ) => panic!( "Concurrent request 3 must succeed : {err}" ),
};
assert!( duration.as_secs() < 15, "Concurrent requests too slow : {duration:?}" );
assert!( !response1.id.is_empty() );
assert!( !response2.id.is_empty() );
assert!( !response3.id.is_empty() );
assert_ne!( response1.id, response2.id );
assert_ne!( response2.id, response3.id );
assert_ne!( response1.id, response3.id );
let total_tokens = response1.usage.output_tokens + response2.usage.output_tokens + response3.usage.output_tokens;
println!( "✅ Concurrent API requests performance integration test passed!" );
println!( " 3 concurrent requests in : {duration:?}" );
println!( " Total output tokens : {total_tokens}" );
println!( " Average per request : {:?}", duration / 3 );
}