use super::trait_def::Validate;
use crate::config::models::router::{
CircuitBreakerConfig, GatewayRouterConfig, LoadBalancerConfig,
};
use tracing::debug;
impl Validate for GatewayRouterConfig {
fn validate(&self) -> Result<(), String> {
debug!("Validating router configuration");
self.circuit_breaker.validate()?;
self.load_balancer.validate()?;
if self.circuit_breaker.min_requests != crate::config::models::default_min_requests() {
return Err(
"router.circuit_breaker.min_requests is not supported by runtime router yet"
.to_string(),
);
}
if self.circuit_breaker.success_threshold != 3 {
return Err(
"router.circuit_breaker.success_threshold is not supported by runtime router yet"
.to_string(),
);
}
if self.load_balancer.sticky_sessions {
return Err(
"router.load_balancer.sticky_sessions is not supported by runtime router yet"
.to_string(),
);
}
if self.load_balancer.session_timeout != 3600 {
return Err(
"router.load_balancer.session_timeout is not supported by runtime router yet"
.to_string(),
);
}
Ok(())
}
}
impl Validate for CircuitBreakerConfig {
fn validate(&self) -> Result<(), String> {
if self.failure_threshold == 0 {
return Err("Circuit breaker failure threshold must be greater than 0".to_string());
}
if self.recovery_timeout == 0 {
return Err("Circuit breaker recovery timeout must be greater than 0".to_string());
}
if self.min_requests == 0 {
return Err("Circuit breaker min requests must be greater than 0".to_string());
}
Ok(())
}
}
impl Validate for LoadBalancerConfig {
fn validate(&self) -> Result<(), String> {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::super::trait_def::Validate;
use super::*; use crate::config::models::provider::RetryConfig;
fn validate_config<T: Validate>(config: &T) -> Result<(), String> {
Validate::validate(config)
}
fn create_valid_circuit_breaker_config() -> CircuitBreakerConfig {
CircuitBreakerConfig {
failure_threshold: 5,
recovery_timeout: 60,
min_requests: 10,
..Default::default()
}
}
fn create_valid_retry_config() -> RetryConfig {
RetryConfig {
base_delay: 100,
max_delay: 1000,
backoff_multiplier: 2.0,
..Default::default()
}
}
#[test]
fn test_circuit_breaker_config_valid() {
let config = create_valid_circuit_breaker_config();
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_circuit_breaker_zero_failure_threshold() {
let mut config = create_valid_circuit_breaker_config();
config.failure_threshold = 0;
let result = validate_config(&config);
assert!(result.is_err());
assert!(result.unwrap_err().contains("failure threshold"));
}
#[test]
fn test_circuit_breaker_high_failure_threshold() {
let mut config = create_valid_circuit_breaker_config();
config.failure_threshold = 100;
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_circuit_breaker_zero_recovery_timeout() {
let mut config = create_valid_circuit_breaker_config();
config.recovery_timeout = 0;
let result = validate_config(&config);
assert!(result.is_err());
assert!(result.unwrap_err().contains("recovery timeout"));
}
#[test]
fn test_circuit_breaker_long_recovery_timeout() {
let mut config = create_valid_circuit_breaker_config();
config.recovery_timeout = 3600;
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_circuit_breaker_zero_min_requests() {
let mut config = create_valid_circuit_breaker_config();
config.min_requests = 0;
let result = validate_config(&config);
assert!(result.is_err());
assert!(result.unwrap_err().contains("min requests"));
}
#[test]
fn test_circuit_breaker_high_min_requests() {
let mut config = create_valid_circuit_breaker_config();
config.min_requests = 1000;
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_retry_config_valid() {
let config = create_valid_retry_config();
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_retry_zero_base_delay() {
let mut config = create_valid_retry_config();
config.base_delay = 0;
let result = validate_config(&config);
assert!(result.is_err());
assert!(result.unwrap_err().contains("base delay"));
}
#[test]
fn test_retry_max_delay_equals_base_delay() {
let mut config = create_valid_retry_config();
config.base_delay = 100;
config.max_delay = 100;
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_retry_max_delay_less_than_base_delay() {
let mut config = create_valid_retry_config();
config.base_delay = 200;
config.max_delay = 100;
let result = validate_config(&config);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.contains("base delay cannot be greater than max delay")
);
}
#[test]
fn test_retry_valid_delay_range() {
let mut config = create_valid_retry_config();
config.base_delay = 100;
config.max_delay = 10000;
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_retry_backoff_multiplier_exactly_one() {
let mut config = create_valid_retry_config();
config.backoff_multiplier = 1.0;
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_retry_backoff_multiplier_zero() {
let mut config = create_valid_retry_config();
config.backoff_multiplier = 0.0;
let result = validate_config(&config);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.contains("backoff multiplier must be greater than 0")
);
}
#[test]
fn test_retry_backoff_multiplier_negative() {
let mut config = create_valid_retry_config();
config.backoff_multiplier = -0.5;
let result = validate_config(&config);
assert!(result.is_err());
assert!(
result
.unwrap_err()
.contains("backoff multiplier must be greater than 0")
);
}
#[test]
fn test_retry_backoff_multiplier_valid() {
let mut config = create_valid_retry_config();
config.backoff_multiplier = 1.5;
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_retry_backoff_multiplier_high() {
let mut config = create_valid_retry_config();
config.backoff_multiplier = 10.0;
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_router_config_valid() {
let config = GatewayRouterConfig::default();
assert!(validate_config(&config).is_ok());
}
#[test]
fn test_router_config_with_invalid_circuit_breaker() {
let mut config = GatewayRouterConfig::default();
config.circuit_breaker.failure_threshold = 0;
let result = validate_config(&config);
assert!(result.is_err());
}
#[test]
fn test_load_balancer_config_valid() {
let config = LoadBalancerConfig::default();
assert!(validate_config(&config).is_ok());
}
}