use siumai::error::LlmError;
use siumai::provider::SiumaiBuilder;
use siumai::request_factory::{RequestBuilder, RequestBuilderFactory, StandardRequestBuilder};
use siumai::types::{
ChatMessage, CommonParams, MessageContent, MessageMetadata, MessageRole, ProviderParams,
ProviderType,
};
#[test]
fn test_request_builder_factory_all_providers() {
println!("๐งช Testing RequestBuilder factory for all providers");
let common_params = CommonParams {
model: "test-model".to_string(),
temperature: Some(0.7),
max_tokens: Some(1000),
top_p: Some(0.9),
stop_sequences: Some(vec!["STOP".to_string()]),
seed: Some(42),
};
let provider_types = vec![
ProviderType::OpenAi,
ProviderType::Anthropic,
ProviderType::Gemini,
ProviderType::Ollama,
ProviderType::XAI,
ProviderType::Groq,
ProviderType::Custom("deepseek".to_string()),
ProviderType::Custom("openrouter".to_string()),
];
for provider_type in provider_types {
println!(" ๐ Testing RequestBuilder for {:?}...", provider_type);
let builder =
RequestBuilderFactory::create_builder(&provider_type, common_params.clone(), None);
assert_eq!(builder.get_common_params().model, "test-model");
assert_eq!(builder.get_common_params().temperature, Some(0.7));
assert_eq!(builder.get_common_params().max_tokens, Some(1000));
println!(
" โ
RequestBuilder created successfully for {:?}",
provider_type
);
}
}
#[test]
fn test_request_builder_chat_request_creation() {
println!("๐งช Testing ChatRequest creation via RequestBuilder");
let common_params = CommonParams {
model: "gpt-4".to_string(),
temperature: Some(0.8),
max_tokens: Some(1500),
top_p: Some(0.95),
stop_sequences: None,
seed: Some(123),
};
let builder = StandardRequestBuilder::new(common_params.clone(), None);
let messages = vec![
ChatMessage {
role: MessageRole::System,
content: MessageContent::Text("You are a helpful assistant".to_string()),
metadata: MessageMetadata::default(),
tool_calls: None,
tool_call_id: None,
},
ChatMessage {
role: MessageRole::User,
content: MessageContent::Text("Hello, world!".to_string()),
metadata: MessageMetadata::default(),
tool_calls: None,
tool_call_id: None,
},
];
let request = builder
.build_chat_request(messages.clone(), None, false)
.expect("Should build non-streaming request");
assert_eq!(request.messages.len(), 2);
assert_eq!(request.common_params.model, "gpt-4");
assert_eq!(request.common_params.temperature, Some(0.8));
assert!(!request.stream);
println!(" โ
Non-streaming ChatRequest created successfully");
let streaming_request = builder
.build_chat_request(messages, None, true)
.expect("Should build streaming request");
assert_eq!(streaming_request.messages.len(), 2);
assert_eq!(streaming_request.common_params.model, "gpt-4");
assert!(streaming_request.stream);
println!(" โ
Streaming ChatRequest created successfully");
}
#[test]
fn test_request_builder_parameter_validation() {
println!("๐งช Testing RequestBuilder parameter validation");
let valid_params = CommonParams {
model: "valid-model".to_string(),
temperature: Some(0.7),
max_tokens: Some(1000),
top_p: Some(0.9),
stop_sequences: None,
seed: Some(42),
};
let builder = StandardRequestBuilder::new(valid_params, None);
let messages = vec![ChatMessage {
role: MessageRole::User,
content: MessageContent::Text("Test message".to_string()),
metadata: MessageMetadata::default(),
tool_calls: None,
tool_call_id: None,
}];
let result = builder.build_chat_request(messages.clone(), None, false);
assert!(result.is_ok(), "Valid parameters should succeed");
println!(" โ
Valid parameters accepted");
let invalid_params = CommonParams {
model: "".to_string(), temperature: Some(0.7),
max_tokens: Some(1000),
top_p: Some(0.9),
stop_sequences: None,
seed: Some(42),
};
let invalid_builder = StandardRequestBuilder::new(invalid_params, None);
let invalid_result = invalid_builder.build_chat_request(messages, None, false);
match invalid_result {
Ok(_) => {
println!(" โ ๏ธ Empty model was accepted (validation may be lenient)");
}
Err(e) => {
println!(" โ
Empty model correctly rejected: {}", e);
}
}
}
#[tokio::test]
async fn test_siumai_builder_request_builder_integration() {
println!("๐งช Testing SiumaiBuilder integration with RequestBuilder");
let test_cases = vec![
("openai", "gpt-4"),
("anthropic", "claude-3-sonnet"),
("gemini", "gemini-1.5-flash"),
];
for (provider, model) in test_cases {
println!(" ๐ Testing {} integration...", provider);
let builder = SiumaiBuilder::new()
.api_key("test-key")
.model(model)
.temperature(0.7)
.max_tokens(1000)
.top_p(0.9)
.seed(42);
let result = match provider {
"openai" => builder.openai().build().await,
"anthropic" => builder.anthropic().build().await,
"gemini" => builder.gemini().build().await,
_ => panic!("Unknown provider: {}", provider),
};
match result {
Ok(client) => {
println!(" โ
{} client created successfully", provider);
assert!(client.supports("chat"));
}
Err(e) => match e {
LlmError::ConfigurationError(msg) if msg.contains("parameter") => {
panic!(" โ {} parameter integration error: {}", provider, msg);
}
_ => {
println!(" โ
{} failed with expected error: {}", provider, e);
}
},
}
}
}
#[test]
fn test_request_builder_with_provider_params() {
println!("๐งช Testing RequestBuilder with provider-specific parameters");
let common_params = CommonParams {
model: "test-model".to_string(),
temperature: Some(0.7),
max_tokens: Some(1000),
top_p: Some(0.9),
stop_sequences: None,
seed: Some(42),
};
let openai_provider_params = Some(
ProviderParams::openai()
.with_param("frequency_penalty", 0.1)
.with_param("presence_penalty", 0.2),
);
let openai_builder = RequestBuilderFactory::create_builder(
&ProviderType::OpenAi,
common_params.clone(),
openai_provider_params,
);
let messages = vec![ChatMessage {
role: MessageRole::User,
content: MessageContent::Text("Test with OpenAI params".to_string()),
metadata: MessageMetadata::default(),
tool_calls: None,
tool_call_id: None,
}];
let openai_request = openai_builder
.build_chat_request(messages.clone(), None, false)
.expect("Should build OpenAI request with provider params");
assert!(openai_request.provider_params.is_some());
println!(" โ
OpenAI RequestBuilder with provider params works");
let anthropic_provider_params = Some(
ProviderParams::anthropic()
.with_param("system", "You are Claude")
.with_param("thinking_budget", 5000),
);
let anthropic_builder = RequestBuilderFactory::create_builder(
&ProviderType::Anthropic,
common_params.clone(),
anthropic_provider_params,
);
let anthropic_request = anthropic_builder
.build_chat_request(messages, None, false)
.expect("Should build Anthropic request with provider params");
assert!(anthropic_request.provider_params.is_some());
println!(" โ
Anthropic RequestBuilder with provider params works");
}
#[test]
fn test_request_builder_consistency() {
println!("๐งช Testing RequestBuilder consistency across multiple calls");
let common_params = CommonParams {
model: "consistency-test-model".to_string(),
temperature: Some(0.5),
max_tokens: Some(800),
top_p: Some(0.8),
stop_sequences: Some(vec!["END".to_string()]),
seed: Some(999),
};
let builder = StandardRequestBuilder::new(common_params.clone(), None);
let messages = vec![ChatMessage {
role: MessageRole::User,
content: MessageContent::Text("Consistency test".to_string()),
metadata: MessageMetadata::default(),
tool_calls: None,
tool_call_id: None,
}];
for i in 1..=5 {
let request = builder
.build_chat_request(messages.clone(), None, false)
.unwrap_or_else(|_| panic!("Should build request {}", i));
assert_eq!(request.common_params.model, "consistency-test-model");
assert_eq!(request.common_params.temperature, Some(0.5));
assert_eq!(request.common_params.max_tokens, Some(800));
assert_eq!(request.common_params.top_p, Some(0.8));
assert_eq!(request.common_params.seed, Some(999));
assert!(!request.stream);
println!(" โ
Request {} is consistent", i);
}
println!(" โ
All requests are consistent");
}
#[test]
fn test_request_builder_error_handling() {
println!("๐งช Testing RequestBuilder error handling");
let common_params = CommonParams {
model: "error-test-model".to_string(),
temperature: Some(0.7),
max_tokens: Some(1000),
top_p: Some(0.9),
stop_sequences: None,
seed: Some(42),
};
let builder = StandardRequestBuilder::new(common_params, None);
let empty_messages = vec![];
let result = builder.build_chat_request(empty_messages, None, false);
match result {
Ok(_) => {
println!(" โ
Empty messages accepted (may be valid for some use cases)");
}
Err(e) => {
println!(" โ
Empty messages correctly rejected: {}", e);
}
}
let many_messages: Vec<ChatMessage> = (0..1000)
.map(|i| ChatMessage {
role: MessageRole::User,
content: MessageContent::Text(format!("Message {}", i)),
metadata: MessageMetadata::default(),
tool_calls: None,
tool_call_id: None,
})
.collect();
let large_result = builder.build_chat_request(many_messages, None, false);
match large_result {
Ok(_) => {
println!(" โ
Large number of messages handled successfully");
}
Err(e) => {
println!(" โ
Large number of messages rejected: {}", e);
}
}
}