709 lines
20 KiB
Rust
709 lines
20 KiB
Rust
//! Comprehensive integration tests for ServerConfig precedence order system.
|
|
//!
|
|
//! Tests verify the precedence order: CLI > Env > File > Default
|
|
//! These tests use real config files and environment variables.
|
|
|
|
#![cfg(feature = "api")]
|
|
|
|
use kreuzberg::ServerConfig;
|
|
use std::fs;
|
|
use tempfile::tempdir;
|
|
|
|
// Helper function to cleanup environment variables
|
|
#[allow(unsafe_code)]
|
|
fn cleanup_env_vars() {
|
|
unsafe {
|
|
std::env::remove_var("KREUZBERG_HOST");
|
|
std::env::remove_var("KREUZBERG_PORT");
|
|
std::env::remove_var("KREUZBERG_CORS_ORIGINS");
|
|
std::env::remove_var("KREUZBERG_MAX_REQUEST_BODY_BYTES");
|
|
std::env::remove_var("KREUZBERG_MAX_MULTIPART_FIELD_BYTES");
|
|
}
|
|
}
|
|
|
|
// Helper function to set environment variables
|
|
#[allow(unsafe_code)]
|
|
fn set_env(key: &str, value: &str) {
|
|
unsafe {
|
|
std::env::set_var(key, value);
|
|
}
|
|
}
|
|
|
|
// Helper function to get and store original environment variables
|
|
fn save_env(keys: &[&str]) -> Vec<(String, Option<String>)> {
|
|
keys.iter()
|
|
.map(|key| (key.to_string(), std::env::var(key).ok()))
|
|
.collect()
|
|
}
|
|
|
|
// Helper function to restore environment variables
|
|
#[allow(unsafe_code)]
|
|
fn restore_env(saved: Vec<(String, Option<String>)>) {
|
|
unsafe {
|
|
for (key, value) in saved {
|
|
if let Some(v) = value {
|
|
std::env::set_var(&key, v);
|
|
} else {
|
|
std::env::remove_var(&key);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test 1: Config precedence order - Env wins over File
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_config_precedence_env_over_file() {
|
|
let saved = save_env(&["KREUZBERG_HOST", "KREUZBERG_PORT"]);
|
|
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
// Create config file with file values
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host = "file-host"
|
|
port = 8001
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
// Set env vars (should override file)
|
|
set_env("KREUZBERG_HOST", "env-host");
|
|
set_env("KREUZBERG_PORT", "8002");
|
|
|
|
// Load and apply
|
|
let mut config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
assert_eq!(config.host, "file-host");
|
|
assert_eq!(config.port, 8001);
|
|
|
|
// Apply env overrides
|
|
config.apply_env_overrides().expect("Operation failed");
|
|
|
|
// Verify env vars won (Env > File)
|
|
assert_eq!(config.host, "env-host", "Env HOST should override file HOST");
|
|
assert_eq!(config.port, 8002, "Env PORT should override file PORT");
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|
|
|
|
// Test 2: File-only configuration
|
|
#[test]
|
|
fn test_file_only_configuration() {
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
// Create config with specific values
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host = "192.168.1.100"
|
|
port = 9000
|
|
cors_origins = ["https://app.example.com"]
|
|
max_request_body_bytes = 50000000
|
|
max_multipart_field_bytes = 75000000
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
let config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
|
|
assert_eq!(config.host, "192.168.1.100");
|
|
assert_eq!(config.port, 9000);
|
|
assert_eq!(config.cors_origins.len(), 1);
|
|
assert_eq!(config.cors_origins[0], "https://app.example.com");
|
|
assert_eq!(config.max_request_body_bytes, 50_000_000);
|
|
assert_eq!(config.max_multipart_field_bytes, 75_000_000);
|
|
}
|
|
|
|
// Test 3: Env-only configuration (no config file)
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_env_only_configuration() {
|
|
let saved = save_env(&["KREUZBERG_HOST", "KREUZBERG_PORT", "KREUZBERG_CORS_ORIGINS"]);
|
|
|
|
set_env("KREUZBERG_HOST", "0.0.0.0");
|
|
set_env("KREUZBERG_PORT", "3000");
|
|
set_env(
|
|
"KREUZBERG_CORS_ORIGINS",
|
|
"https://api.example.com, https://app.example.com",
|
|
);
|
|
|
|
// Create default config
|
|
let mut config = ServerConfig::default();
|
|
|
|
// Verify defaults initially
|
|
assert_eq!(config.host, "127.0.0.1");
|
|
assert_eq!(config.port, 8000);
|
|
|
|
// Apply env overrides
|
|
config.apply_env_overrides().expect("Operation failed");
|
|
|
|
// Verify env vars are used
|
|
assert_eq!(config.host, "0.0.0.0");
|
|
assert_eq!(config.port, 3000);
|
|
assert_eq!(config.cors_origins.len(), 2);
|
|
assert!(config.cors_origins.contains(&"https://api.example.com".to_string()));
|
|
assert!(config.cors_origins.contains(&"https://app.example.com".to_string()));
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|
|
|
|
// Test 4: Default configuration
|
|
#[test]
|
|
fn test_default_configuration() {
|
|
let config = ServerConfig::default();
|
|
|
|
// Verify defaults
|
|
assert_eq!(config.host, "127.0.0.1");
|
|
assert_eq!(config.port, 8000);
|
|
assert!(config.cors_origins.is_empty());
|
|
assert_eq!(config.max_request_body_bytes, 104_857_600); // 100 MB
|
|
assert_eq!(config.max_multipart_field_bytes, 104_857_600); // 100 MB
|
|
assert_eq!(config.listen_addr(), "127.0.0.1:8000");
|
|
}
|
|
|
|
// Test 5: Backward compatibility - file without [server] section
|
|
#[test]
|
|
fn test_backward_compatibility_no_server_section() {
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
// Create config with only extraction settings (no [server] section)
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
# No [server] section - extraction-only config
|
|
use_cache = false
|
|
enable_quality_processing = true
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
// ServerConfig::from_file should load with defaults for missing [server] section
|
|
let config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
|
|
// Verify ServerConfig fields have defaults
|
|
assert_eq!(config.host, "127.0.0.1");
|
|
assert_eq!(config.port, 8000);
|
|
assert!(config.cors_origins.is_empty());
|
|
}
|
|
|
|
// Test 6: All three formats - TOML
|
|
#[test]
|
|
fn test_config_format_toml() {
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host = "10.0.0.1"
|
|
port = 7000
|
|
cors_origins = ["https://test.com"]
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
let config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
assert_eq!(config.host, "10.0.0.1");
|
|
assert_eq!(config.port, 7000);
|
|
}
|
|
|
|
// Test 7: All three formats - YAML
|
|
#[test]
|
|
fn test_config_format_yaml() {
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.yaml");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host: 10.0.0.2
|
|
port: 7001
|
|
cors_origins:
|
|
- https://test.com
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
let config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
assert_eq!(config.host, "10.0.0.2");
|
|
assert_eq!(config.port, 7001);
|
|
}
|
|
|
|
// Test 8: All three formats - JSON
|
|
#[test]
|
|
fn test_config_format_json() {
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.json");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"{
|
|
"host": "10.0.0.3",
|
|
"port": 7002,
|
|
"cors_origins": ["https://test.com"]
|
|
}
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
let config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
assert_eq!(config.host, "10.0.0.3");
|
|
assert_eq!(config.port, 7002);
|
|
}
|
|
|
|
// Test 9: CORS configuration - empty (allow all)
|
|
#[test]
|
|
fn test_cors_configuration_allow_all() {
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host = "127.0.0.1"
|
|
port = 8000
|
|
# Empty cors_origins means allow all
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
let config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
|
|
assert!(config.cors_allows_all(), "Empty cors_origins should allow all");
|
|
assert!(config.is_origin_allowed("https://any.com"));
|
|
assert!(config.is_origin_allowed("http://localhost:3000"));
|
|
}
|
|
|
|
// Test 10: CORS configuration - specific origins
|
|
#[test]
|
|
fn test_cors_configuration_specific_origins() {
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host = "127.0.0.1"
|
|
port = 8000
|
|
cors_origins = ["https://app1.com", "https://app2.com"]
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
let config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
|
|
assert!(!config.cors_allows_all(), "Specific origins should not allow all");
|
|
assert!(config.is_origin_allowed("https://app1.com"));
|
|
assert!(config.is_origin_allowed("https://app2.com"));
|
|
assert!(!config.is_origin_allowed("https://app3.com"));
|
|
}
|
|
|
|
// Test 11: CORS precedence - env overrides file
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_cors_precedence_env_over_file() {
|
|
let saved = save_env(&["KREUZBERG_CORS_ORIGINS"]);
|
|
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
cors_origins = ["https://file.com"]
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
set_env("KREUZBERG_CORS_ORIGINS", "https://env1.com, https://env2.com");
|
|
|
|
let mut config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
assert_eq!(config.cors_origins.len(), 1);
|
|
assert_eq!(config.cors_origins[0], "https://file.com");
|
|
|
|
config.apply_env_overrides().expect("Operation failed");
|
|
|
|
assert_eq!(config.cors_origins.len(), 2);
|
|
assert!(config.cors_origins.contains(&"https://env1.com".to_string()));
|
|
assert!(config.cors_origins.contains(&"https://env2.com".to_string()));
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|
|
|
|
// Test 14: Invalid env var values - invalid port
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_invalid_env_port() {
|
|
let saved = save_env(&["KREUZBERG_PORT"]);
|
|
|
|
set_env("KREUZBERG_PORT", "not_a_number");
|
|
|
|
let mut config = ServerConfig::default();
|
|
let result = config.apply_env_overrides();
|
|
|
|
assert!(result.is_err());
|
|
let err_msg = result.unwrap_err().to_string();
|
|
assert!(err_msg.contains("KREUZBERG_PORT"));
|
|
assert!(err_msg.contains("valid u16"));
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|
|
|
|
// Test 15: Invalid env var values - invalid max_request_body_bytes
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_invalid_env_max_request_body_bytes() {
|
|
let saved = save_env(&["KREUZBERG_MAX_REQUEST_BODY_BYTES"]);
|
|
|
|
set_env("KREUZBERG_MAX_REQUEST_BODY_BYTES", "invalid_number");
|
|
|
|
let mut config = ServerConfig::default();
|
|
let result = config.apply_env_overrides();
|
|
|
|
assert!(result.is_err());
|
|
let err_msg = result.unwrap_err().to_string();
|
|
assert!(err_msg.contains("KREUZBERG_MAX_REQUEST_BODY_BYTES"));
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|
|
|
|
// Test 16: Partial overrides - only host, not port
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_partial_overrides_host_only() {
|
|
let saved = save_env(&["KREUZBERG_HOST", "KREUZBERG_PORT"]);
|
|
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host = "file-host"
|
|
port = 8001
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
set_env("KREUZBERG_HOST", "env-host");
|
|
// Explicitly don't set KREUZBERG_PORT
|
|
|
|
let mut config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
config.apply_env_overrides().expect("Operation failed");
|
|
|
|
assert_eq!(config.host, "env-host", "Host should be overridden by env");
|
|
assert_eq!(config.port, 8001, "Port should keep file value");
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|
|
|
|
// Test 17: Partial overrides - only port, not host
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_partial_overrides_port_only() {
|
|
let saved = save_env(&["KREUZBERG_HOST", "KREUZBERG_PORT"]);
|
|
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host = "file-host"
|
|
port = 8001
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
set_env("KREUZBERG_PORT", "9000");
|
|
// Explicitly don't set KREUZBERG_HOST
|
|
|
|
let mut config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
config.apply_env_overrides().expect("Operation failed");
|
|
|
|
assert_eq!(config.host, "file-host", "Host should keep file value");
|
|
assert_eq!(config.port, 9000, "Port should be overridden by env");
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|
|
|
|
// Test 18: Complex scenario with multiple settings
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_complex_scenario_multiple_settings() {
|
|
let saved = save_env(&[
|
|
"KREUZBERG_HOST",
|
|
"KREUZBERG_PORT",
|
|
"KREUZBERG_CORS_ORIGINS",
|
|
"KREUZBERG_MAX_REQUEST_BODY_BYTES",
|
|
]);
|
|
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host = "127.0.0.1"
|
|
port = 8000
|
|
cors_origins = ["https://file.com"]
|
|
max_request_body_bytes = 50000000
|
|
max_multipart_field_bytes = 75000000
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
// Override some settings
|
|
set_env("KREUZBERG_HOST", "0.0.0.0");
|
|
set_env("KREUZBERG_PORT", "3000");
|
|
set_env("KREUZBERG_CORS_ORIGINS", "https://env.com");
|
|
// Don't set max_request_body_bytes - should keep file value
|
|
|
|
let mut config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
config.apply_env_overrides().expect("Operation failed");
|
|
|
|
assert_eq!(config.host, "0.0.0.0");
|
|
assert_eq!(config.port, 3000);
|
|
assert_eq!(config.cors_origins.len(), 1);
|
|
assert_eq!(config.cors_origins[0], "https://env.com");
|
|
assert_eq!(config.max_request_body_bytes, 50_000_000, "File value should persist");
|
|
assert_eq!(config.max_multipart_field_bytes, 75_000_000);
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|
|
|
|
// Test 19: listen_addr helper method
|
|
#[test]
|
|
fn test_listen_addr_helper() {
|
|
let mut config = ServerConfig::default();
|
|
assert_eq!(config.listen_addr(), "127.0.0.1:8000");
|
|
|
|
config.host = "0.0.0.0".to_string();
|
|
config.port = 3000;
|
|
assert_eq!(config.listen_addr(), "0.0.0.0:3000");
|
|
}
|
|
|
|
// Test 20: Upload limits conversion to MB
|
|
#[test]
|
|
fn test_upload_limits_to_mb_conversion() {
|
|
let mut config = ServerConfig::default();
|
|
|
|
// Test request body MB
|
|
assert_eq!(config.max_request_body_mb(), 100);
|
|
|
|
config.max_request_body_bytes = 1_048_576; // 1 MB
|
|
assert_eq!(config.max_request_body_mb(), 1);
|
|
|
|
config.max_request_body_bytes = 1_048_577; // 1 MB + 1 byte - should round up
|
|
assert_eq!(config.max_request_body_mb(), 2);
|
|
|
|
// Test multipart field MB
|
|
config.max_multipart_field_bytes = 1_048_576;
|
|
assert_eq!(config.max_multipart_field_mb(), 1);
|
|
|
|
config.max_multipart_field_bytes = 52_428_800; // 50 MB
|
|
assert_eq!(config.max_multipart_field_mb(), 50);
|
|
}
|
|
|
|
// Test 21: Serialization consistency
|
|
#[test]
|
|
fn test_serialization_consistency() {
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
let original = r#"
|
|
host = "192.168.1.100"
|
|
port = 9000
|
|
cors_origins = ["https://app.com"]
|
|
max_request_body_bytes = 50000000
|
|
max_multipart_field_bytes = 75000000
|
|
"#;
|
|
|
|
fs::write(&config_path, original).expect("Operation failed");
|
|
|
|
let config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
|
|
// Serialize back
|
|
let serialized = toml::to_string(&config).expect("Operation failed");
|
|
|
|
// Deserialize again
|
|
let config2: ServerConfig = toml::from_str(&serialized).expect("Failed to parse string");
|
|
|
|
// Verify consistency
|
|
assert_eq!(config.host, config2.host);
|
|
assert_eq!(config.port, config2.port);
|
|
assert_eq!(config.cors_origins, config2.cors_origins);
|
|
assert_eq!(config.max_request_body_bytes, config2.max_request_body_bytes);
|
|
assert_eq!(config.max_multipart_field_bytes, config2.max_multipart_field_bytes);
|
|
}
|
|
|
|
// Test 22: Empty CORS origins with env override
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_empty_cors_to_specific_via_env() {
|
|
let saved = save_env(&["KREUZBERG_CORS_ORIGINS"]);
|
|
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host = "127.0.0.1"
|
|
port = 8000
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
let mut config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
assert!(config.cors_allows_all(), "File config allows all origins");
|
|
|
|
// Override with specific origins
|
|
set_env("KREUZBERG_CORS_ORIGINS", "https://restricted.com");
|
|
config.apply_env_overrides().expect("Operation failed");
|
|
|
|
assert!(!config.cors_allows_all(), "Should now restrict to specific origin");
|
|
assert!(config.is_origin_allowed("https://restricted.com"));
|
|
assert!(!config.is_origin_allowed("https://other.com"));
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|
|
|
|
// Test 23: Max upload limits in different formats
|
|
#[test]
|
|
fn test_max_limits_across_formats() {
|
|
let dir = tempdir().expect("Operation failed");
|
|
|
|
// Test TOML
|
|
let toml_path = dir.path().join("config.toml");
|
|
fs::write(
|
|
&toml_path,
|
|
r#"
|
|
max_request_body_bytes = 100000000
|
|
max_multipart_field_bytes = 200000000
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
let toml_config = ServerConfig::from_file(&toml_path).expect("Operation failed");
|
|
assert_eq!(toml_config.max_request_body_bytes, 100_000_000);
|
|
assert_eq!(toml_config.max_multipart_field_bytes, 200_000_000);
|
|
|
|
// Test YAML
|
|
let yaml_path = dir.path().join("config.yaml");
|
|
fs::write(
|
|
&yaml_path,
|
|
r#"
|
|
max_request_body_bytes: 100000000
|
|
max_multipart_field_bytes: 200000000
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
let yaml_config = ServerConfig::from_file(&yaml_path).expect("Operation failed");
|
|
assert_eq!(yaml_config.max_request_body_bytes, 100_000_000);
|
|
assert_eq!(yaml_config.max_multipart_field_bytes, 200_000_000);
|
|
|
|
// Test JSON
|
|
let json_path = dir.path().join("config.json");
|
|
fs::write(
|
|
&json_path,
|
|
r#"{
|
|
"max_request_body_bytes": 100000000,
|
|
"max_multipart_field_bytes": 200000000
|
|
}
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
let json_config = ServerConfig::from_file(&json_path).expect("Operation failed");
|
|
assert_eq!(json_config.max_request_body_bytes, 100_000_000);
|
|
assert_eq!(json_config.max_multipart_field_bytes, 200_000_000);
|
|
}
|
|
|
|
// Test 24: Port validation at bounds
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_port_validation_bounds() {
|
|
let saved = save_env(&["KREUZBERG_PORT"]);
|
|
|
|
// Valid port: 0
|
|
set_env("KREUZBERG_PORT", "0");
|
|
let mut config = ServerConfig::default();
|
|
config.apply_env_overrides().expect("Operation failed");
|
|
assert_eq!(config.port, 0);
|
|
|
|
// Valid port: 65535 (max u16)
|
|
set_env("KREUZBERG_PORT", "65535");
|
|
let mut config = ServerConfig::default();
|
|
config.apply_env_overrides().expect("Operation failed");
|
|
assert_eq!(config.port, 65535);
|
|
|
|
// Invalid port: too large
|
|
set_env("KREUZBERG_PORT", "65536");
|
|
let mut config = ServerConfig::default();
|
|
let result = config.apply_env_overrides();
|
|
assert!(result.is_err());
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|
|
|
|
// Test 25: Multiple env var overrides at once
|
|
#[test]
|
|
#[serial_test::serial]
|
|
fn test_multiple_env_overrides_simultaneous() {
|
|
let saved = save_env(&[
|
|
"KREUZBERG_HOST",
|
|
"KREUZBERG_PORT",
|
|
"KREUZBERG_CORS_ORIGINS",
|
|
"KREUZBERG_MAX_REQUEST_BODY_BYTES",
|
|
"KREUZBERG_MAX_MULTIPART_FIELD_BYTES",
|
|
]);
|
|
|
|
let dir = tempdir().expect("Operation failed");
|
|
let config_path = dir.path().join("config.toml");
|
|
|
|
fs::write(
|
|
&config_path,
|
|
r#"
|
|
host = "127.0.0.1"
|
|
port = 8000
|
|
"#,
|
|
)
|
|
.expect("Operation failed");
|
|
|
|
// Set all env vars
|
|
set_env("KREUZBERG_HOST", "192.168.1.1");
|
|
set_env("KREUZBERG_PORT", "5000");
|
|
set_env("KREUZBERG_CORS_ORIGINS", "https://api.com, https://app.com");
|
|
set_env("KREUZBERG_MAX_REQUEST_BODY_BYTES", "150000000");
|
|
set_env("KREUZBERG_MAX_MULTIPART_FIELD_BYTES", "250000000");
|
|
|
|
let mut config = ServerConfig::from_file(&config_path).expect("Operation failed");
|
|
config.apply_env_overrides().expect("Operation failed");
|
|
|
|
// All should be overridden
|
|
assert_eq!(config.host, "192.168.1.1");
|
|
assert_eq!(config.port, 5000);
|
|
assert_eq!(config.cors_origins.len(), 2);
|
|
assert_eq!(config.max_request_body_bytes, 150_000_000);
|
|
assert_eq!(config.max_multipart_field_bytes, 250_000_000);
|
|
|
|
cleanup_env_vars();
|
|
restore_env(saved);
|
|
}
|