use super::*;
use crate::wire::Operation;
use crate::wire::secret::tests::a_config_reloads_without_its_credential;
#[test]
fn a_serialized_provider_never_carries_its_key() {
let provider =
AnthropicConfig::new("sk-live-do-not-leak").with_beta("prompt-caching-2024-07-31");
a_config_reloads_without_its_credential(&provider, "sk-live-do-not-leak", |provider| {
&provider.api_key
});
let wire = provider.completion("claude-haiku-4-5");
let json = serde_json::to_string(&wire).expect("the wire serializes");
assert!(!json.contains("sk-live-do-not-leak"));
let restored: Messages = serde_json::from_str(&json).expect("the wire round-trips");
assert_eq!(restored.model, "claude-haiku-4-5");
assert_eq!(restored.provider.dialect, ANTHROPIC);
assert!(restored.provider.api_key.is_empty());
}
#[test]
fn a_dialect_round_trips_by_name_and_rejects_an_unknown_one() {
for dialect in [ANTHROPIC, ZAI, MINIMAX, MOONSHOT, XIAOMIMIMO] {
let json = serde_json::to_string(&dialect).expect("a dialect serializes");
assert_eq!(json, format!("\"{}\"", dialect.name));
let restored: Dialect = serde_json::from_str(&json).expect("a dialect round-trips");
assert_eq!(restored, dialect);
}
assert!(serde_json::from_str::<Dialect>("\"not-a-provider\"").is_err());
}
#[test]
fn a_gateway_defaults_max_tokens_to_its_one_documented_ceiling() {
assert_eq!(
ANTHROPIC.default_max_tokens("claude-haiku-4-5"),
Some(64_000)
);
assert_eq!(ANTHROPIC.default_max_tokens("some-unknown-model"), None);
assert_eq!(ZAI.default_max_tokens("some-unknown-model"), Some(4096));
const _: () = assert!(!ZAI.quirks.strict_tool_schemas);
const _: () = assert!(ANTHROPIC.quirks.strict_tool_schemas);
}
#[test]
fn each_dialect_reads_images_on_its_vision_models() {
use crate::completion::ReplayTarget;
for (dialect, model, images) in [
(&ANTHROPIC, "claude-sonnet-4-6", true),
(&ZAI, "glm-4.6", false),
(&ZAI, "glm-4.5-air", false),
(&ZAI, "glm-4.5v", true),
(&ZAI, "glm-4.6v-flash", true),
(&ZAI, "glm-5v-turbo", true),
(&MOONSHOT, "kimi-k2-thinking", false),
(&MOONSHOT, "kimi-k2-0905-preview", false),
(&MOONSHOT, "moonshot-v1-8k", false),
(&MOONSHOT, "moonshot-v1-8k-vision-preview", true),
(&MOONSHOT, "kimi-k2.6", true),
(&MOONSHOT, "kimi-k3", true),
(&MINIMAX, "MiniMax-M2.7", false),
(&MINIMAX, "MiniMax-M3", true),
(&XIAOMIMIMO, "mimo-v2-flash", false),
(&XIAOMIMIMO, "mimo-v2-pro", false),
(&XIAOMIMIMO, "mimo-v2.5-pro", false),
(&XIAOMIMIMO, "mimo-v2-omni", true),
(&XIAOMIMIMO, "mimo-v2.5", true),
(&XIAOMIMIMO, "mimo-v2.6-flash", true),
] {
let accepts = AnthropicConfig::with_key(dialect, "sk-test")
.completion("another-model")
.accepts(model);
assert_eq!(accepts.user_images, images, "{model}");
assert_eq!(accepts.tool_result_images, images, "{model}");
assert!(!accepts.assistant_images, "{model}");
assert!(accepts.tools, "{model}");
}
}
#[test]
fn every_dialect_defaults_to_eager_tool_input() {
for quirks in [Quirks::anthropic(), Quirks::gateway()] {
assert_eq!(quirks.tool_input_streaming, ToolInputStreaming::Eager);
}
for dialect in all() {
assert_eq!(
dialect.quirks.tool_input_streaming,
ToolInputStreaming::Eager,
"{}",
dialect.name
);
}
assert_eq!(Quirks::gateway().max_tokens, MaxTokens::Fixed(4096));
}
fn messages_path(config: AnthropicConfig) -> String {
let wire = config.completion("a-model");
let mut request = CompletionRequest::new("hello");
request.max_tokens = Some(64);
let request = Completion::prepare(request, &wire.describe()).expect("the request prepares");
let encoded = wire
.encode(request, Mode::Unary)
.expect("the request encodes");
encoded.request.uri().path().to_owned()
}
#[test]
fn every_dialect_posts_to_one_v1_messages() {
for dialect in all() {
let path = messages_path(AnthropicConfig::with_key(dialect, "sk-test"));
assert!(path.ends_with("/v1/messages"), "{}: {path}", dialect.name);
assert_eq!(path.matches("/v1").count(), 1, "{}: {path}", dialect.name);
}
}
#[test]
fn a_dialect_base_url_is_normalized() {
let dialect = compatible(
"custom",
"https://gateway.example/anthropic/v1/",
"CUSTOM_API_KEY",
None,
);
let config = AnthropicConfig::with_key(&dialect, "sk-test");
assert_eq!(config.base_url, "https://gateway.example/anthropic");
assert_eq!(messages_path(config), "/anthropic/v1/messages");
}