#![allow(missing_docs)]
use hashbrown::HashSet;
use serde_json::Value;
use std::fs;
use vtcode_core::config::constants::{model_helpers, models};
#[test]
#[ignore = "requires models.json to match constants"]
fn constants_cover_models_json() {
let json = fs::read_to_string("docs/models.json")
.expect("Failed to read docs/models.json. Make sure you're running tests from the project root.");
let models_data: Value = serde_json::from_str(&json).expect("Failed to parse docs/models.json as valid JSON");
let providers = models_data.as_object().expect("docs/models.json should be a JSON object");
let mut validated_providers = HashSet::new();
for (provider_name, provider_spec) in providers {
let provider_models = provider_spec.get("models").and_then(|m| m.as_object());
if provider_models.is_none() {
continue; }
let provider_models = provider_models.unwrap();
let model_ids_from_json: HashSet<&str> = provider_models.keys().map(|s| s.as_str()).collect();
let constants_models = match provider_name.as_str() {
"openai" => {
validated_providers.insert("openai");
Some(models::openai::SUPPORTED_MODELS)
}
"anthropic" => {
validated_providers.insert("anthropic");
Some(models::anthropic::SUPPORTED_MODELS)
}
"google" => {
validated_providers.insert("google");
Some(models::google::SUPPORTED_MODELS)
}
"openrouter" => {
validated_providers.insert("openrouter");
Some(models::openrouter::SUPPORTED_MODELS)
}
"deepseek" => {
validated_providers.insert("deepseek");
Some(models::deepseek::SUPPORTED_MODELS)
}
"zai" => {
validated_providers.insert("zai");
Some(models::zai::SUPPORTED_MODELS)
}
_ => None, };
if let Some(constants_models) = constants_models {
let model_ids_from_constants: HashSet<&str> = constants_models.iter().copied().collect();
let missing_in_constants: Vec<_> = model_ids_from_json.difference(&model_ids_from_constants).collect();
let extra_in_constants: Vec<_> = model_ids_from_constants.difference(&model_ids_from_json).collect();
assert!(
missing_in_constants.is_empty(),
"Missing models in constants.rs for provider '{provider_name}': {missing_in_constants:?}\n\
Add these models to models::{provider_name}::SUPPORTED_MODELS in crates/codegen/vtcode-core/src/config/constants.rs"
);
assert!(
extra_in_constants.is_empty(),
"Extra models in constants.rs for provider '{provider_name}' not found in docs/models.json: {extra_in_constants:?}\n\
Remove these models from models::{provider_name}::SUPPORTED_MODELS or add them to docs/models.json"
);
for &model_id in constants_models {
assert!(
model_helpers::is_valid(provider_name, model_id),
"Model validation failed for {provider_name}:{model_id} - model_helpers::is_valid should return true"
);
}
let default_model = model_helpers::default_for(provider_name)
.unwrap_or_else(|| panic!("No default model found for provider '{provider_name}'"));
assert!(
model_helpers::is_valid(provider_name, default_model),
"Default model '{default_model}' for provider '{provider_name}' is not in the supported models list"
);
assert!(
constants_models.contains(&default_model),
"Default model '{default_model}' for provider '{provider_name}' is not in SUPPORTED_MODELS"
);
println!("[SUCCESS] Provider '{}': {} models validated", provider_name, constants_models.len());
}
}
let expected_providers = ["openai", "anthropic", "google", "openrouter", "deepseek", "zai"];
for expected in &expected_providers {
assert!(
validated_providers.contains(expected),
"Expected to validate provider '{expected}' but it was not found in docs/models.json or was skipped"
);
}
println!("[SUCCESS] All {} providers validated against docs/models.json", validated_providers.len());
}
#[test]
fn model_helpers_validation_edge_cases() {
assert_eq!(model_helpers::supported_for("nonexistent"), None);
assert_eq!(model_helpers::default_for("nonexistent"), None);
assert!(!model_helpers::is_valid("nonexistent", "any-model"));
assert!(!model_helpers::is_valid("openai", "invalid-model-id"));
assert!(!model_helpers::is_valid("anthropic", "invalid-model-id"));
assert!(!model_helpers::is_valid("google", "invalid-model-id"));
assert!(!model_helpers::is_valid("openrouter", "invalid-model-id"));
assert!(model_helpers::is_valid("openai", models::openai::DEFAULT_MODEL));
assert!(model_helpers::is_valid("anthropic", models::anthropic::DEFAULT_MODEL));
assert!(model_helpers::is_valid("google", models::google::DEFAULT_MODEL));
assert!(model_helpers::is_valid("openrouter", models::openrouter::DEFAULT_MODEL));
assert!(model_helpers::is_valid("zai", models::zai::DEFAULT_MODEL));
}
#[test]
fn backwards_compatibility_constants() {
assert!(!models::GEMINI_3_FLASH_PREVIEW.is_empty());
assert!(!models::GPT_5.is_empty());
assert!(!models::CLAUDE_SONNET_4_6.is_empty());
assert!(!models::CLAUDE_HAIKU_4_5.is_empty());
assert_eq!(models::GEMINI_3_FLASH_PREVIEW, models::google::GEMINI_3_FLASH_PREVIEW);
assert_eq!(models::GPT_5, models::openai::GPT_5);
assert_eq!(models::CLAUDE_SONNET_4_6, models::anthropic::CLAUDE_SONNET_4_6);
assert_eq!(models::CLAUDE_HAIKU_4_5, models::anthropic::CLAUDE_HAIKU_4_5);
}