#[cfg(test)]
use super::ssrf::validate_url_against_ssrf;
use super::trait_def::Validate;
use crate::config::models::auth::AuthConfig;
use crate::config::models::cache::CacheConfig;
use crate::config::models::enterprise::{EnterpriseConfig, SsoConfig};
use crate::config::models::provider::ProviderConfig;
use crate::config::models::rate_limit::RateLimitConfig;
use crate::config::models::server::ServerConfig;
use crate::config::models::storage::{DatabaseConfig, RedisConfig};
#[test]
fn test_server_config_validation() {
let mut config = ServerConfig::default();
assert!(Validate::validate(&config).is_ok());
config.port = 0;
assert!(Validate::validate(&config).is_err());
config.port = 8080;
config.host = "".to_string();
assert!(Validate::validate(&config).is_err());
}
#[test]
fn test_server_config_default_values() {
let config = ServerConfig::default();
assert_eq!(config.port, 8000);
assert_eq!(config.host, "0.0.0.0");
}
#[test]
fn test_server_config_custom_port() {
let config = ServerConfig {
port: 3000,
host: "127.0.0.1".to_string(),
..Default::default()
};
assert!(Validate::validate(&config).is_ok());
assert_eq!(config.port, 3000);
}
#[test]
fn test_server_config_port_range() {
for port in [80, 443, 8080, 8000, 3000, 65535] {
let config = ServerConfig {
port,
..Default::default()
};
assert!(Validate::validate(&config).is_ok());
}
}
#[test]
fn test_provider_config_validation() {
let mut config = ProviderConfig {
name: "test".to_string(),
provider_type: "openai".to_string(),
api_key: "test-key".to_string(),
..Default::default()
};
assert!(config.validate().is_ok());
config.provider_type = "custom_provider".to_string();
assert!(config.validate().is_err());
config.provider_type = "openai".to_string();
config.weight = 0.0;
assert!(config.validate().is_err());
}
#[test]
fn test_provider_config_all_types() {
let provider_types = ["openai", "anthropic", "mistral", "cloudflare", "groq"];
for provider_type in provider_types {
let config = ProviderConfig {
name: "test".to_string(),
provider_type: provider_type.to_string(),
api_key: "test-key".to_string(),
..Default::default()
};
assert!(
config.validate().is_ok(),
"Provider type '{}' should be valid",
provider_type
);
}
}
#[test]
fn test_provider_config_local_catalog_type_allows_empty_api_key() {
let config = ProviderConfig {
name: "local-vllm".to_string(),
provider_type: "vllm".to_string(),
api_key: "".to_string(),
..Default::default()
};
assert!(config.validate().is_ok());
}
#[test]
fn test_provider_config_weight_validation() {
let mut config = ProviderConfig {
name: "test".to_string(),
provider_type: "openai".to_string(),
api_key: "test-key".to_string(),
weight: 1.0,
..Default::default()
};
assert!(config.validate().is_ok());
config.weight = 0.0;
assert!(config.validate().is_err());
config.weight = -1.0;
assert!(config.validate().is_err());
config.weight = 100.0;
assert!(config.validate().is_ok());
}
#[test]
fn test_provider_config_empty_name() {
let config = ProviderConfig {
name: "".to_string(),
provider_type: "openai".to_string(),
api_key: "test-key".to_string(),
..Default::default()
};
assert!(config.validate().is_err());
}
#[test]
fn test_auth_config_validation() {
let mut config = AuthConfig {
jwt_secret: "a-very-long-secret-key-for-testing-purposes".to_string(),
..Default::default()
};
assert!(config.validate().is_ok());
config.jwt_secret = "short".to_string();
assert!(config.validate().is_err());
config.jwt_secret = "".to_string();
assert!(config.validate().is_err());
}
#[test]
fn test_auth_config_jwt_secret_min_length() {
let config = AuthConfig {
jwt_secret: "aA1!".repeat(8), ..Default::default()
};
assert!(config.validate().is_ok());
let config = AuthConfig {
jwt_secret: "aA1!".repeat(7) + "aA1", ..Default::default()
};
assert!(config.validate().is_err());
}
#[test]
fn test_cache_validation_skips_when_disabled() {
let config = CacheConfig {
enabled: false,
ttl: 0,
max_size: 0,
semantic_cache: true,
similarity_threshold: 2.0,
};
assert!(Validate::validate(&config).is_ok());
}
#[test]
fn test_rate_limit_validation_skips_when_disabled() {
let config = RateLimitConfig {
enabled: false,
default_rpm: 0,
default_tpm: 0,
..Default::default()
};
assert!(Validate::validate(&config).is_ok());
}
#[test]
fn test_database_validation_skips_when_disabled() {
let config = DatabaseConfig {
enabled: false,
url: "".to_string(),
max_connections: 0,
connection_timeout: 0,
ssl: false,
};
assert!(Validate::validate(&config).is_ok());
}
#[test]
fn test_redis_validation_skips_when_disabled() {
let config = RedisConfig {
enabled: false,
url: "".to_string(),
max_connections: 0,
connection_timeout: 0,
cluster: false,
};
assert!(Validate::validate(&config).is_ok());
}
#[test]
fn test_enterprise_validation_skips_when_disabled() {
let config = EnterpriseConfig {
enabled: false,
sso: Some(SsoConfig {
provider: "invalid-provider".to_string(),
client_id: "".to_string(),
client_secret: "".to_string(),
redirect_url: "".to_string(),
settings: Default::default(),
}),
audit_logging: false,
advanced_analytics: false,
};
assert!(Validate::validate(&config).is_ok());
}
#[test]
fn test_ssrf_validation_valid_urls() {
assert!(validate_url_against_ssrf("https://api.openai.com/v1", "test").is_ok());
assert!(validate_url_against_ssrf("https://api.anthropic.com", "test").is_ok());
assert!(validate_url_against_ssrf("http://example.com:8080/api", "test").is_ok());
}
#[test]
fn test_ssrf_validation_https_urls() {
assert!(validate_url_against_ssrf("https://8.8.8.8", "test").is_ok());
assert!(validate_url_against_ssrf("https://api.github.com", "test").is_ok());
assert!(validate_url_against_ssrf("https://google.com", "test").is_ok());
}
#[test]
fn test_ssrf_validation_http_urls() {
assert!(validate_url_against_ssrf("http://8.8.8.8", "test").is_ok());
assert!(validate_url_against_ssrf("http://example.com:9000", "test").is_ok());
}
#[test]
fn test_ssrf_validation_url_with_path() {
assert!(validate_url_against_ssrf("https://8.8.8.8/v1/chat", "test").is_ok());
assert!(validate_url_against_ssrf("https://example.com/api/v2/messages", "test").is_ok());
}
#[test]
fn test_ssrf_validation_url_with_query() {
assert!(validate_url_against_ssrf("https://8.8.8.8/v1?key=value", "test").is_ok());
}
#[test]
fn test_ssrf_validation_localhost() {
assert!(validate_url_against_ssrf("http://localhost/api", "test").is_err());
assert!(validate_url_against_ssrf("http://localhost:8080/api", "test").is_err());
assert!(validate_url_against_ssrf("http://LOCALHOST/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_localhost_variations() {
assert!(validate_url_against_ssrf("https://localhost", "test").is_err());
assert!(validate_url_against_ssrf("http://localhost:3000", "test").is_err());
assert!(validate_url_against_ssrf("http://LocalHost/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_loopback() {
assert!(validate_url_against_ssrf("http://127.0.0.1/api", "test").is_err());
assert!(validate_url_against_ssrf("http://127.0.0.1:8080/api", "test").is_err());
assert!(validate_url_against_ssrf("http://[::1]/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_loopback_range() {
assert!(validate_url_against_ssrf("http://127.0.0.2/api", "test").is_err());
assert!(validate_url_against_ssrf("http://127.255.255.255/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_private_ip() {
assert!(validate_url_against_ssrf("http://10.0.0.1/api", "test").is_err());
assert!(validate_url_against_ssrf("http://172.16.0.1/api", "test").is_err());
assert!(validate_url_against_ssrf("http://192.168.1.1/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_private_ip_10_range() {
assert!(validate_url_against_ssrf("http://10.0.0.0/api", "test").is_err());
assert!(validate_url_against_ssrf("http://10.255.255.255/api", "test").is_err());
assert!(validate_url_against_ssrf("http://10.100.50.25/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_private_ip_172_range() {
assert!(validate_url_against_ssrf("http://172.16.0.0/api", "test").is_err());
assert!(validate_url_against_ssrf("http://172.31.255.255/api", "test").is_err());
assert!(validate_url_against_ssrf("http://172.20.100.50/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_private_ip_192_range() {
assert!(validate_url_against_ssrf("http://192.168.0.0/api", "test").is_err());
assert!(validate_url_against_ssrf("http://192.168.255.255/api", "test").is_err());
assert!(validate_url_against_ssrf("http://192.168.100.50/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_metadata_endpoints() {
assert!(validate_url_against_ssrf("http://169.254.169.254/latest/meta-data", "test").is_err());
assert!(
validate_url_against_ssrf("http://metadata.google.internal/computeMetadata", "test")
.is_err()
);
}
#[test]
fn test_ssrf_validation_aws_metadata() {
assert!(validate_url_against_ssrf("http://169.254.169.254/latest", "test").is_err());
assert!(
validate_url_against_ssrf("http://169.254.169.254/latest/meta-data/iam", "test").is_err()
);
}
#[test]
fn test_ssrf_validation_link_local() {
assert!(validate_url_against_ssrf("http://169.254.0.1/api", "test").is_err());
assert!(validate_url_against_ssrf("http://169.254.100.50/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_encoded_ip() {
assert!(validate_url_against_ssrf("http://2130706433/api", "test").is_err());
assert!(validate_url_against_ssrf("http://167772161/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_hex_encoded_ip() {
assert!(validate_url_against_ssrf("http://0x7f000001/api", "test").is_err());
assert!(validate_url_against_ssrf("http://0x0a000001/api", "test").is_err());
}
#[test]
fn test_ssrf_validation_invalid_scheme() {
assert!(validate_url_against_ssrf("file:///etc/passwd", "test").is_err());
assert!(validate_url_against_ssrf("ftp://example.com", "test").is_err());
assert!(validate_url_against_ssrf("gopher://example.com", "test").is_err());
}
#[test]
fn test_ssrf_validation_other_schemes() {
assert!(validate_url_against_ssrf("ssh://example.com", "test").is_err());
assert!(validate_url_against_ssrf("telnet://example.com", "test").is_err());
assert!(validate_url_against_ssrf("data:text/html,<script>", "test").is_err());
}
#[test]
fn test_ssrf_validation_invalid_url() {
assert!(validate_url_against_ssrf("not a url", "test").is_err());
assert!(validate_url_against_ssrf("", "test").is_err());
assert!(validate_url_against_ssrf("://missing-scheme", "test").is_err());
}
#[test]
fn test_provider_config_ssrf_validation() {
let mut config = ProviderConfig {
name: "test".to_string(),
provider_type: "openai".to_string(),
api_key: "test-key".to_string(),
base_url: Some("http://localhost:8080".to_string()),
..Default::default()
};
assert!(config.validate().is_err());
config.base_url = Some("https://api.openai.com/v1".to_string());
assert!(config.validate().is_ok());
config.base_url = Some("http://192.168.1.1/api".to_string());
assert!(config.validate().is_err());
config.base_url = Some("http://169.254.169.254/latest".to_string());
assert!(config.validate().is_err());
}
#[test]
fn test_provider_config_no_base_url() {
let config = ProviderConfig {
name: "test".to_string(),
provider_type: "openai".to_string(),
api_key: "test-key".to_string(),
base_url: None,
..Default::default()
};
assert!(config.validate().is_ok());
}
#[test]
fn test_ssrf_unspecified_address() {
assert!(validate_url_against_ssrf("http://0.0.0.0/api", "test").is_err());
assert!(validate_url_against_ssrf("http://0/api", "test").is_err());
}
#[test]
fn test_ssrf_context_message() {
let result = validate_url_against_ssrf("http://localhost/api", "provider_url");
assert!(result.is_err());
let error_message = result.unwrap_err();
assert!(error_message.contains("provider_url"));
assert!(error_message.contains("SSRF"));
}