use super::*;
use crate::config::constants::models;
#[test]
fn test_model_string_conversion() {
assert_eq!(
ModelId::Gemini3FlashPreview.as_str(),
models::google::GEMINI_3_FLASH_PREVIEW
);
assert_eq!(
ModelId::Gemini31ProPreview.as_str(),
models::google::GEMINI_3_1_PRO_PREVIEW
);
assert_eq!(ModelId::GPT5.as_str(), models::GPT_5);
assert_eq!(ModelId::GPT52Codex.as_str(), models::openai::GPT_5_2_CODEX);
assert_eq!(ModelId::GPT51Codex.as_str(), models::openai::GPT_5_1_CODEX);
assert_eq!(
ModelId::GPT51CodexMax.as_str(),
models::openai::GPT_5_1_CODEX_MAX
);
assert_eq!(ModelId::GPT5Codex.as_str(), models::openai::GPT_5_CODEX);
assert_eq!(ModelId::GPT5Mini.as_str(), models::GPT_5_MINI);
assert_eq!(ModelId::GPT5Nano.as_str(), models::GPT_5_NANO);
assert_eq!(ModelId::ClaudeOpus47.as_str(), models::CLAUDE_OPUS_4_7);
assert_eq!(ModelId::ClaudeSonnet46.as_str(), models::CLAUDE_SONNET_4_6);
assert_eq!(ModelId::ClaudeHaiku45.as_str(), models::CLAUDE_HAIKU_4_5);
assert_eq!(ModelId::DeepSeekChat.as_str(), models::DEEPSEEK_CHAT);
assert_eq!(
ModelId::DeepSeekReasoner.as_str(),
models::DEEPSEEK_REASONER
);
assert_eq!(
ModelId::HuggingFaceGlm5Novita.as_str(),
models::huggingface::ZAI_GLM_5_NOVITA
);
assert_eq!(
ModelId::HuggingFaceQwen3CoderNextNovita.as_str(),
models::huggingface::QWEN3_CODER_NEXT_NOVITA
);
assert_eq!(ModelId::ZaiGlm5.as_str(), models::zai::GLM_5);
assert_eq!(
ModelId::OpenCodeZenGPT54.as_str(),
models::opencode_zen::GPT_5_4
);
assert_eq!(
ModelId::OpenCodeGoKimiK25.as_str(),
models::opencode_go::KIMI_K2_5
);
}
#[test]
fn test_model_from_string() {
assert_eq!(
models::google::GEMINI_3_FLASH_PREVIEW
.parse::<ModelId>()
.unwrap(),
ModelId::Gemini3FlashPreview
);
assert_eq!(
models::google::GEMINI_3_1_PRO_PREVIEW
.parse::<ModelId>()
.unwrap(),
ModelId::Gemini31ProPreview
);
assert_eq!(models::GPT_5.parse::<ModelId>().unwrap(), ModelId::GPT5);
assert_eq!(
models::openai::GPT_5_2_CODEX.parse::<ModelId>().unwrap(),
ModelId::GPT52Codex
);
assert_eq!(
models::openai::GPT_5_1_CODEX.parse::<ModelId>().unwrap(),
ModelId::GPT51Codex
);
assert_eq!(
models::openai::GPT_5_1_CODEX_MAX
.parse::<ModelId>()
.unwrap(),
ModelId::GPT51CodexMax
);
assert_eq!(
models::openai::GPT_5_CODEX.parse::<ModelId>().unwrap(),
ModelId::GPT5Codex
);
assert_eq!(
models::GPT_5_MINI.parse::<ModelId>().unwrap(),
ModelId::GPT5Mini
);
assert_eq!(
models::GPT_5_NANO.parse::<ModelId>().unwrap(),
ModelId::GPT5Nano
);
assert_eq!(
models::openai::GPT_OSS_20B.parse::<ModelId>().unwrap(),
ModelId::OpenAIGptOss20b
);
assert_eq!(
models::openai::GPT_OSS_120B.parse::<ModelId>().unwrap(),
ModelId::OpenAIGptOss120b
);
assert_eq!(
models::CLAUDE_SONNET_4_6.parse::<ModelId>().unwrap(),
ModelId::ClaudeSonnet46
);
assert_eq!(
models::CLAUDE_HAIKU_4_5.parse::<ModelId>().unwrap(),
ModelId::ClaudeHaiku45
);
assert_eq!(
models::CLAUDE_OPUS_4_7.parse::<ModelId>().unwrap(),
ModelId::ClaudeOpus47
);
assert_eq!(
models::CLAUDE_SONNET_4_6.parse::<ModelId>().unwrap(),
ModelId::ClaudeSonnet46
);
assert_eq!(
models::DEEPSEEK_CHAT.parse::<ModelId>().unwrap(),
ModelId::DeepSeekChat
);
assert_eq!(
models::DEEPSEEK_REASONER.parse::<ModelId>().unwrap(),
ModelId::DeepSeekReasoner
);
assert_eq!(
models::huggingface::ZAI_GLM_5_NOVITA
.parse::<ModelId>()
.unwrap(),
ModelId::HuggingFaceGlm5Novita
);
assert_eq!(
models::huggingface::QWEN3_CODER_NEXT_NOVITA
.parse::<ModelId>()
.unwrap(),
ModelId::HuggingFaceQwen3CoderNextNovita
);
assert_eq!(
models::zai::GLM_5.parse::<ModelId>().unwrap(),
ModelId::ZaiGlm5
);
assert_eq!(
models::zai::GLM_5_LEGACY.parse::<ModelId>().unwrap(),
ModelId::ZaiGlm5
);
assert_eq!(
"opencode/gpt-5.4".parse::<ModelId>().unwrap(),
ModelId::OpenCodeZenGPT54
);
assert_eq!(
"opencode-go/kimi-k2.5".parse::<ModelId>().unwrap(),
ModelId::OpenCodeGoKimiK25
);
assert!("invalid-model".parse::<ModelId>().is_err());
}
#[test]
fn test_provider_parsing() {
assert_eq!("gemini".parse::<Provider>().unwrap(), Provider::Gemini);
assert_eq!("openai".parse::<Provider>().unwrap(), Provider::OpenAI);
assert_eq!(
"anthropic".parse::<Provider>().unwrap(),
Provider::Anthropic
);
assert_eq!("deepseek".parse::<Provider>().unwrap(), Provider::DeepSeek);
assert_eq!(
"openrouter".parse::<Provider>().unwrap(),
Provider::OpenRouter
);
assert_eq!("zai".parse::<Provider>().unwrap(), Provider::ZAI);
assert_eq!("moonshot".parse::<Provider>().unwrap(), Provider::Moonshot);
assert_eq!(
"opencode-zen".parse::<Provider>().unwrap(),
Provider::OpenCodeZen
);
assert_eq!(
"opencode-go".parse::<Provider>().unwrap(),
Provider::OpenCodeGo
);
assert_eq!("lmstudio".parse::<Provider>().unwrap(), Provider::LmStudio);
assert!("invalid-provider".parse::<Provider>().is_err());
}
#[test]
fn test_model_providers() {
assert_eq!(ModelId::Gemini3FlashPreview.provider(), Provider::Gemini);
assert_eq!(ModelId::GPT5.provider(), Provider::OpenAI);
assert_eq!(ModelId::ClaudeOpus47.provider(), Provider::Anthropic);
assert_eq!(ModelId::ClaudeSonnet46.provider(), Provider::Anthropic);
assert_eq!(ModelId::ClaudeHaiku45.provider(), Provider::Anthropic);
assert_eq!(ModelId::DeepSeekChat.provider(), Provider::DeepSeek);
assert_eq!(ModelId::ZaiGlm5.provider(), Provider::ZAI);
assert_eq!(ModelId::OpenCodeZenGPT54.provider(), Provider::OpenCodeZen);
assert_eq!(ModelId::OpenCodeGoKimiK25.provider(), Provider::OpenCodeGo);
assert_eq!(ModelId::OllamaGptOss20b.provider(), Provider::Ollama);
assert_eq!(ModelId::OllamaGptOss120bCloud.provider(), Provider::Ollama);
assert_eq!(ModelId::OllamaQwen317b.provider(), Provider::Ollama);
}
#[test]
fn test_provider_defaults() {
assert_eq!(
ModelId::default_orchestrator_for_provider(Provider::Gemini),
ModelId::Gemini31ProPreview
);
assert_eq!(
ModelId::default_orchestrator_for_provider(Provider::OpenAI),
ModelId::GPT5
);
assert_eq!(
ModelId::default_orchestrator_for_provider(Provider::Anthropic),
ModelId::ClaudeOpus47
);
assert_eq!(
ModelId::default_orchestrator_for_provider(Provider::DeepSeek),
ModelId::DeepSeekReasoner
);
assert_eq!(
ModelId::default_orchestrator_for_provider(Provider::Ollama),
ModelId::OllamaGptOss20b
);
assert_eq!(
ModelId::default_orchestrator_for_provider(Provider::ZAI),
ModelId::ZaiGlm5
);
assert_eq!(
ModelId::default_orchestrator_for_provider(Provider::OpenCodeZen),
ModelId::OpenCodeZenGPT54
);
assert_eq!(
ModelId::default_orchestrator_for_provider(Provider::OpenCodeGo),
ModelId::OpenCodeGoKimiK25
);
assert_eq!(
ModelId::default_single_for_provider(Provider::DeepSeek),
ModelId::DeepSeekReasoner
);
assert_eq!(
ModelId::default_single_for_provider(Provider::Ollama),
ModelId::OllamaGptOss20b
);
assert_eq!(
ModelId::default_single_for_provider(Provider::ZAI),
ModelId::ZaiGlm5
);
assert_eq!(
ModelId::default_single_for_provider(Provider::OpenCodeZen),
ModelId::OpenCodeZenGPT54
);
assert_eq!(
ModelId::default_single_for_provider(Provider::OpenCodeGo),
ModelId::OpenCodeGoKimiK25
);
}
#[test]
fn test_provider_service_tier_support() {
assert!(Provider::OpenAI.supports_service_tier(models::GPT_5));
assert!(Provider::OpenAI.supports_service_tier(models::openai::O3));
assert!(!Provider::OpenAI.supports_service_tier(models::openai::GPT_OSS_20B));
assert!(!Provider::Anthropic.supports_service_tier(models::GPT_5));
}
#[test]
fn test_model_defaults() {
assert_eq!(ModelId::default(), ModelId::Gemini3FlashPreview);
assert_eq!(ModelId::default_orchestrator(), ModelId::Gemini31ProPreview);
}
#[test]
fn test_model_variants() {
assert!(ModelId::Gemini3FlashPreview.is_flash_variant());
assert!(!ModelId::GPT5.is_flash_variant());
assert!(ModelId::GPT5.is_pro_variant());
assert!(ModelId::GPT52Codex.is_pro_variant());
assert!(ModelId::GPT51CodexMax.is_pro_variant());
assert!(ModelId::ClaudeOpus47.is_pro_variant());
assert!(ModelId::ClaudeSonnet46.is_pro_variant());
assert!(ModelId::DeepSeekReasoner.is_pro_variant());
assert!(ModelId::ZaiGlm5.is_pro_variant());
assert!(!ModelId::Gemini3FlashPreview.is_pro_variant());
assert!(ModelId::Gemini3FlashPreview.is_efficient_variant());
assert!(ModelId::GPT5Mini.is_efficient_variant());
assert!(ModelId::ClaudeHaiku45.is_efficient_variant());
assert!(ModelId::DeepSeekChat.is_efficient_variant());
assert!(!ModelId::GPT5.is_efficient_variant());
assert!(ModelId::GPT5.is_top_tier());
assert!(ModelId::GPT52Codex.is_top_tier());
assert!(ModelId::GPT5Codex.is_top_tier());
assert!(ModelId::ClaudeOpus47.is_top_tier());
assert!(ModelId::ClaudeSonnet46.is_top_tier());
assert!(ModelId::DeepSeekReasoner.is_top_tier());
assert!(ModelId::ZaiGlm5.is_top_tier());
assert!(ModelId::Gemini3FlashPreview.is_top_tier());
assert!(!ModelId::ClaudeHaiku45.is_top_tier());
}
#[test]
fn test_model_generation() {
assert_eq!(ModelId::Gemini3FlashPreview.generation(), "3");
assert_eq!(ModelId::GPT5.generation(), "5");
assert_eq!(ModelId::GPT52Codex.generation(), "5.2");
assert_eq!(ModelId::GPT51Codex.generation(), "5.1");
assert_eq!(ModelId::GPT5Codex.generation(), "5");
assert_eq!(ModelId::GPT5Mini.generation(), "5");
assert_eq!(ModelId::GPT5Nano.generation(), "5");
assert_eq!(ModelId::ClaudeOpus47.generation(), "4.7");
assert_eq!(ModelId::ClaudeSonnet46.generation(), "4.6");
assert_eq!(ModelId::ClaudeHaiku45.generation(), "4.5");
assert_eq!(ModelId::DeepSeekChat.generation(), "V3.2-Exp");
assert_eq!(ModelId::DeepSeekReasoner.generation(), "V3.2-Exp");
assert_eq!(ModelId::ZaiGlm5.generation(), "5");
}
#[test]
fn test_models_for_provider() {
let gemini_models = ModelId::models_for_provider(Provider::Gemini);
assert!(gemini_models.contains(&ModelId::Gemini3FlashPreview));
assert!(!gemini_models.contains(&ModelId::GPT5));
let openai_models = ModelId::models_for_provider(Provider::OpenAI);
assert!(openai_models.contains(&ModelId::GPT5));
assert!(openai_models.contains(&ModelId::GPT52Codex));
assert!(openai_models.contains(&ModelId::GPT51Codex));
assert!(openai_models.contains(&ModelId::GPT51CodexMax));
assert!(openai_models.contains(&ModelId::GPT5Codex));
assert!(!openai_models.contains(&ModelId::Gemini3FlashPreview));
let anthropic_models = ModelId::models_for_provider(Provider::Anthropic);
assert!(anthropic_models.contains(&ModelId::ClaudeOpus47));
assert!(anthropic_models.contains(&ModelId::ClaudeSonnet46));
assert!(anthropic_models.contains(&ModelId::ClaudeHaiku45));
assert!(!anthropic_models.contains(&ModelId::GPT5));
let deepseek_models = ModelId::models_for_provider(Provider::DeepSeek);
assert!(deepseek_models.contains(&ModelId::DeepSeekChat));
assert!(deepseek_models.contains(&ModelId::DeepSeekReasoner));
let zai_models = ModelId::models_for_provider(Provider::ZAI);
assert!(zai_models.contains(&ModelId::ZaiGlm5));
let ollama_models = ModelId::models_for_provider(Provider::Ollama);
assert!(ollama_models.contains(&ModelId::OllamaGptOss20b));
assert!(ollama_models.contains(&ModelId::OllamaGptOss20bCloud));
assert!(ollama_models.contains(&ModelId::OllamaGptOss120bCloud));
assert!(ollama_models.contains(&ModelId::OllamaQwen317b));
assert!(ollama_models.contains(&ModelId::OllamaDeepseekV32Cloud));
}
#[test]
fn test_fallback_models() {
let fallbacks = ModelId::fallback_models();
assert!(!fallbacks.is_empty());
assert!(fallbacks.contains(&ModelId::Gemini3FlashPreview));
assert!(fallbacks.contains(&ModelId::GPT52));
assert!(fallbacks.contains(&ModelId::GPT5));
assert!(fallbacks.contains(&ModelId::OpenAIGptOss20b));
assert!(fallbacks.contains(&ModelId::ClaudeOpus47));
assert!(fallbacks.contains(&ModelId::ClaudeSonnet46));
assert!(fallbacks.contains(&ModelId::DeepSeekReasoner));
assert!(fallbacks.contains(&ModelId::ZaiGlm5));
}
#[test]
fn test_reexported_model_id_provider_types() {
let model: ModelId = ModelId::GPT53Codex;
let provider: Provider = Provider::Moonshot;
assert_eq!(model, ModelId::GPT53Codex);
assert_eq!(provider, Provider::Moonshot);
}
#[test]
fn test_moonshot_and_openrouter_minimax_variants() {
assert_eq!(
models::moonshot::KIMI_K2_5.parse::<ModelId>().unwrap(),
ModelId::MoonshotKimiK25
);
assert_eq!(
"minimax/minimax-m2.5".parse::<ModelId>().unwrap(),
ModelId::OpenRouterMinimaxM25
);
assert_eq!(ModelId::MoonshotKimiK25.provider(), Provider::Moonshot);
assert_eq!(
ModelId::OpenRouterMinimaxM25.provider(),
Provider::OpenRouter
);
}