pollux/tests/config_validation.rs
Jeena 55fe47b172 Replace custom logging with tracing crate and RUST_LOG env var
- Remove custom logging module and init_logging function
- Update main.rs to use tracing_subscriber with EnvFilter
- Remove log_level from global config structure
- Update documentation and tests to use RUST_LOG
- Format long lines in config.rs and test files for better readability
2026-01-22 05:25:46 +00:00

393 lines
11 KiB
Rust

mod common;
use std::process::Command;
#[test]
fn test_missing_config_file() {
let output = Command::new(env!("CARGO_BIN_EXE_pollux"))
.arg("--config")
.arg("nonexistent.toml")
.env("RUST_LOG", "error")
.output()
.unwrap();
assert!(!output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
let stdout = String::from_utf8(output.stdout).unwrap();
assert!(stderr.contains("Config file 'nonexistent.toml' not found"));
assert!(stdout.contains("Create the config file with"));
}
#[test]
fn test_nonexistent_root_directory() {
let temp_dir = common::setup_test_environment();
let config_path = temp_dir.path().join("config.toml");
let config_content = format!(
r#"
bind_host = "127.0.0.1"
["example.com"]
root = "/definitely/does/not/exist"
cert = "{}"
key = "{}"
"#,
temp_dir.path().join("cert.pem").display(),
temp_dir.path().join("key.pem").display()
);
std::fs::write(&config_path, config_content).unwrap();
let output = Command::new(env!("CARGO_BIN_EXE_pollux"))
.arg("--config")
.arg(&config_path)
.env("RUST_LOG", "error")
.output()
.unwrap();
assert!(!output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stderr.contains("Failed to parse config file"));
assert!(stderr.contains(
"Error for host 'example.com': Root directory '/definitely/does/not/exist' does not exist"
));
}
#[test]
fn test_missing_certificate_file() {
let temp_dir = common::setup_test_environment();
let config_path = temp_dir.path().join("config.toml");
let config_content = format!(
r#"
bind_host = "127.0.0.1"
["example.com"]
root = "{}"
cert = "/nonexistent/cert.pem"
key = "{}"
"#,
temp_dir.path().join("content").display(),
temp_dir.path().join("key.pem").display()
);
std::fs::write(&config_path, config_content).unwrap();
let output = Command::new(env!("CARGO_BIN_EXE_pollux"))
.arg("--config")
.arg(&config_path)
.env("RUST_LOG", "error")
.output()
.unwrap();
assert!(!output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stderr.contains(
"Error for host 'example.com': Certificate file '/nonexistent/cert.pem' does not exist"
));
assert!(stderr.contains("Generate or obtain TLS certificates for your domain"));
}
#[test]
fn test_valid_config_startup() {
let temp_dir = common::setup_test_environment();
let port = 1967 + (std::process::id() % 1000) as u16;
let config_path = temp_dir.path().join("config.toml");
let config_content = format!(
r#"
bind_host = "127.0.0.1"
port = {}
["localhost"]
root = "{}"
cert = "{}"
key = "{}"
"#,
port,
temp_dir.path().join("content").display(),
temp_dir.path().join("cert.pem").display(),
temp_dir.path().join("key.pem").display()
);
std::fs::write(&config_path, config_content).unwrap();
let mut server_process = Command::new(env!("CARGO_BIN_EXE_pollux"))
.arg("--config")
.arg(&config_path)
.spawn()
.unwrap();
// Wait for server to start
std::thread::sleep(std::time::Duration::from_millis(500));
// Check server is still running (didn't exit with error)
assert!(
server_process.try_wait().unwrap().is_none(),
"Server should still be running with valid config"
);
// Kill server
server_process.kill().unwrap();
}
#[test]
fn test_valid_multiple_hosts_startup() {
let temp_dir = common::setup_test_environment();
let port = 1965 + (std::process::id() % 1000) as u16;
// Create host directories
std::fs::create_dir(temp_dir.path().join("host1")).unwrap();
std::fs::create_dir(temp_dir.path().join("host2")).unwrap();
// Generate certificates for both hosts
let cert1_path = temp_dir.path().join("host1_cert.pem");
let key1_path = temp_dir.path().join("host1_key.pem");
let cert2_path = temp_dir.path().join("host2_cert.pem");
let key2_path = temp_dir.path().join("host2_key.pem");
// Generate certificate for host1
let cert_result1 = std::process::Command::new("openssl")
.args(&[
"req",
"-x509",
"-newkey",
"rsa:2048",
"-keyout",
&key1_path.to_string_lossy(),
"-out",
&cert1_path.to_string_lossy(),
"-days",
"1",
"-nodes",
"-subj",
"/CN=host1.com",
])
.output();
// Generate certificate for host2
let cert_result2 = std::process::Command::new("openssl")
.args(&[
"req",
"-x509",
"-newkey",
"rsa:2048",
"-keyout",
&key2_path.to_string_lossy(),
"-out",
&cert2_path.to_string_lossy(),
"-days",
"1",
"-nodes",
"-subj",
"/CN=host2.com",
])
.output();
if cert_result1.is_err() || cert_result2.is_err() {
panic!("Failed to generate test certificates for multiple hosts test");
}
let config_path = temp_dir.path().join("config.toml");
let config_content = format!(
r#"
bind_host = "127.0.0.1"
port = {}
["host1.com"]
root = "{}"
cert = "{}"
key = "{}"
["host2.com"]
root = "{}"
cert = "{}"
key = "{}"
"#,
port,
temp_dir.path().join("host1").display(),
cert1_path.display(),
key1_path.display(),
temp_dir.path().join("host2").display(),
cert2_path.display(),
key2_path.display()
);
std::fs::write(&config_path, config_content).unwrap();
let mut server_process = Command::new(env!("CARGO_BIN_EXE_pollux"))
.arg("--config")
.arg(&config_path)
.spawn()
.unwrap();
// Wait for server to start
std::thread::sleep(std::time::Duration::from_millis(500));
// Check server is still running (didn't exit with error)
assert!(
server_process.try_wait().unwrap().is_none(),
"Server should start with valid multiple host config"
);
// Kill server
server_process.kill().unwrap();
}
#[test]
fn test_multiple_hosts_missing_certificate() {
let temp_dir = common::setup_test_environment();
let config_path = temp_dir.path().join("config.toml");
// Create host directories
std::fs::create_dir(temp_dir.path().join("host1")).unwrap();
std::fs::create_dir(temp_dir.path().join("host2")).unwrap();
// Generate certificate for only one host
let cert1_path = temp_dir.path().join("host1_cert.pem");
let key1_path = temp_dir.path().join("host1_key.pem");
let cert_result = std::process::Command::new("openssl")
.args(&[
"req",
"-x509",
"-newkey",
"rsa:2048",
"-keyout",
&key1_path.to_string_lossy(),
"-out",
&cert1_path.to_string_lossy(),
"-days",
"1",
"-nodes",
"-subj",
"/CN=host1.com",
])
.output();
if cert_result.is_err() {
panic!("Failed to generate test certificate");
}
let config_content = format!(
r#"
bind_host = "127.0.0.1"
["host1.com"]
root = "{}"
cert = "{}"
key = "{}"
["host2.com"]
root = "{}"
cert = "/nonexistent/cert.pem"
key = "/nonexistent/key.pem"
"#,
temp_dir.path().join("host1").display(),
cert1_path.display(),
key1_path.display(),
temp_dir.path().join("host2").display()
);
std::fs::write(&config_path, config_content).unwrap();
let output = Command::new(env!("CARGO_BIN_EXE_pollux"))
.arg("--config")
.arg(&config_path)
.env("RUST_LOG", "error")
.output()
.unwrap();
assert!(!output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stderr.contains(
"Error for host 'host2.com': Certificate file '/nonexistent/cert.pem' does not exist"
));
}
#[test]
fn test_multiple_hosts_invalid_hostname() {
let temp_dir = common::setup_test_environment();
let config_path = temp_dir.path().join("config.toml");
// Create host directories
std::fs::create_dir(temp_dir.path().join("validhost")).unwrap();
std::fs::create_dir(temp_dir.path().join("invalidhost")).unwrap();
// Generate certificates for both hosts
let cert1_path = temp_dir.path().join("valid_cert.pem");
let key1_path = temp_dir.path().join("valid_key.pem");
let cert2_path = temp_dir.path().join("invalid_cert.pem");
let key2_path = temp_dir.path().join("invalid_key.pem");
// Generate certificate for valid host
let cert_result1 = std::process::Command::new("openssl")
.args(&[
"req",
"-x509",
"-newkey",
"rsa:2048",
"-keyout",
&key1_path.to_string_lossy(),
"-out",
&cert1_path.to_string_lossy(),
"-days",
"1",
"-nodes",
"-subj",
"/CN=valid.com",
])
.output();
// Generate certificate for invalid host (hostname validation happens before cert validation)
let cert_result2 = std::process::Command::new("openssl")
.args(&[
"req",
"-x509",
"-newkey",
"rsa:2048",
"-keyout",
&key2_path.to_string_lossy(),
"-out",
&cert2_path.to_string_lossy(),
"-days",
"1",
"-nodes",
"-subj",
"/CN=invalid.com",
])
.output();
if cert_result1.is_err() || cert_result2.is_err() {
panic!("Failed to generate test certificates");
}
let config_content = format!(
r#"
bind_host = "127.0.0.1"
["valid.com"]
root = "{}"
cert = "{}"
key = "{}"
["bad..host.com"]
root = "{}"
cert = "{}"
key = "{}"
"#,
temp_dir.path().join("validhost").display(),
cert1_path.display(),
key1_path.display(),
temp_dir.path().join("invalidhost").display(),
cert2_path.display(),
key2_path.display()
);
std::fs::write(&config_path, config_content).unwrap();
let output = Command::new(env!("CARGO_BIN_EXE_pollux"))
.arg("--config")
.arg(&config_path)
.env("RUST_LOG", "error")
.output()
.unwrap();
assert!(!output.status.success());
let stderr = String::from_utf8(output.stderr).unwrap();
assert!(stderr.contains("Invalid hostname 'bad..host.com'. Hostnames must be valid DNS names."));
}