mod common; #[test] fn test_single_host_config() { let temp_dir = tempfile::TempDir::new().unwrap(); let config_path = temp_dir.path().join("config.toml"); let port = 1967 + (std::process::id() % 1000) as u16; // Create content directory and certificates let content_dir = temp_dir.path().join("content"); std::fs::create_dir(&content_dir).unwrap(); // Generate test certificates use std::process::Command; let cert_path = temp_dir.path().join("cert.pem"); let key_path = temp_dir.path().join("key.pem"); let cert_result = Command::new("openssl") .args(&[ "req", "-x509", "-newkey", "rsa:2048", "-keyout", &key_path.to_string_lossy(), "-out", &cert_path.to_string_lossy(), "-days", "1", "-nodes", "-subj", "/CN=example.com", ]) .output(); if cert_result.is_err() { panic!("Failed to generate test certificates for config test"); } let config_content = format!( r#" bind_host = "127.0.0.1" port = {} ["example.com"] root = "{}" cert = "{}" key = "{}" "#, port, content_dir.display(), cert_path.display(), key_path.display() ); std::fs::write(&config_path, config_content).unwrap(); let mut server_process = std::process::Command::new(env!("CARGO_BIN_EXE_pollux")) .arg("--config") .arg(&config_path) .spawn() .unwrap(); std::thread::sleep(std::time::Duration::from_millis(500)); assert!( server_process.try_wait().unwrap().is_none(), "Server should start with valid single host config" ); server_process.kill().unwrap(); } #[test] fn test_multiple_hosts_config() { let temp_dir = common::setup_test_environment(); let config_path = temp_dir.path().join("config.toml"); let config_content = format!( r#" [site1.com] root = "{}" cert = "{}" key = "{}" [site2.org] root = "{}" cert = "{}" key = "{}" bind_host = "127.0.0.1" port = 1965 "#, temp_dir.path().join("site1").display(), temp_dir.path().join("site1_cert.pem").display(), temp_dir.path().join("site1_key.pem").display(), temp_dir.path().join("site2").display(), temp_dir.path().join("site2_cert.pem").display(), temp_dir.path().join("site2_key.pem").display() ); std::fs::write(&config_path, config_content).unwrap(); // Create additional directories and generate certificates std::fs::create_dir(temp_dir.path().join("site1")).unwrap(); std::fs::create_dir(temp_dir.path().join("site2")).unwrap(); // Generate certificates for each host use std::process::Command; // Site 1 certificate let cert_result1 = Command::new("openssl") .args(&[ "req", "-x509", "-newkey", "rsa:2048", "-keyout", &temp_dir.path().join("site1_key.pem").to_string_lossy(), "-out", &temp_dir.path().join("site1_cert.pem").to_string_lossy(), "-days", "1", "-nodes", "-subj", "/CN=site1.com", ]) .output(); // Site 2 certificate let cert_result2 = Command::new("openssl") .args(&[ "req", "-x509", "-newkey", "rsa:2048", "-keyout", &temp_dir.path().join("site2_key.pem").to_string_lossy(), "-out", &temp_dir.path().join("site2_cert.pem").to_string_lossy(), "-days", "1", "-nodes", "-subj", "/CN=site2.org", ]) .output(); if cert_result1.is_err() || cert_result2.is_err() { panic!("Failed to generate test certificates for multiple hosts test"); } // Test server starts successfully with multiple host config let port = 1968 + (std::process::id() % 1000) as u16; let config_content = format!( r#" bind_host = "127.0.0.1" port = {} ["site1.com"] root = "{}" cert = "{}" key = "{}" ["site2.org"] root = "{}" cert = "{}" key = "{}" "#, port, temp_dir.path().join("site1").display(), temp_dir.path().join("site1_cert.pem").display(), temp_dir.path().join("site1_key.pem").display(), temp_dir.path().join("site2").display(), temp_dir.path().join("site2_cert.pem").display(), temp_dir.path().join("site2_key.pem").display() ); std::fs::write(&config_path, config_content).unwrap(); let mut server_process = std::process::Command::new(env!("CARGO_BIN_EXE_pollux")) .arg("--config") .arg(&config_path) .spawn() .unwrap(); std::thread::sleep(std::time::Duration::from_millis(500)); assert!( server_process.try_wait().unwrap().is_none(), "Server should start with valid multiple host config" ); server_process.kill().unwrap(); } #[test] fn test_missing_required_fields_in_host_config() { let temp_dir = common::setup_test_environment(); let config_path = temp_dir.path().join("config.toml"); let config_content = r#" bind_host = "127.0.0.1" port = 1965 ["example.com"] root = "/tmp/content" # missing cert and key "#; std::fs::write(&config_path, config_content).unwrap(); let output = std::process::Command::new(env!("CARGO_BIN_EXE_pollux")) .arg("--config") .arg(&config_path) .output() .unwrap(); assert!(!output.status.success()); let stderr = String::from_utf8(output.stderr).unwrap(); assert!(stderr.contains("Missing required field") || stderr.contains("missing field")); } #[test] fn test_invalid_hostname_config() { let temp_dir = common::setup_test_environment(); let config_path = temp_dir.path().join("config.toml"); let config_content = format!( r#" ["invalid"] root = "{}" cert = "{}" key = "{}" "#, 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 output = std::process::Command::new(env!("CARGO_BIN_EXE_pollux")) .arg("--config") .arg(&config_path) .output() .unwrap(); assert!(!output.status.success()); let stderr = String::from_utf8(output.stderr).unwrap(); assert!(stderr.contains("Invalid hostname")); } #[test] fn test_no_hosts_config() { let temp_dir = common::setup_test_environment(); let config_path = temp_dir.path().join("config.toml"); let config_content = r#" bind_host = "127.0.0.1" port = 1965 # No host sections "#; std::fs::write(&config_path, config_content).unwrap(); let output = std::process::Command::new(env!("CARGO_BIN_EXE_pollux")) .arg("--config") .arg(&config_path) .output() .unwrap(); assert!(!output.status.success()); let stderr = String::from_utf8(output.stderr).unwrap(); assert!(stderr.contains("No host configurations found")); } #[test] fn test_duplicate_hostname_config() { let temp_dir = common::setup_test_environment(); let config_path = temp_dir.path().join("config.toml"); let config_content = format!( r#" [example.com] root = "{}" cert = "{}" key = "{}" [example.com] root = "{}" cert = "{}" key = "{}" "#, temp_dir.path().join("path1").display(), temp_dir.path().join("cert1.pem").display(), temp_dir.path().join("key1.pem").display(), temp_dir.path().join("path2").display(), temp_dir.path().join("cert2.pem").display(), temp_dir.path().join("key2.pem").display() ); std::fs::write(&config_path, config_content).unwrap(); // Create the directories and certs std::fs::create_dir(temp_dir.path().join("path1")).unwrap(); std::fs::create_dir(temp_dir.path().join("path2")).unwrap(); std::fs::write(temp_dir.path().join("cert1.pem"), "cert1").unwrap(); std::fs::write(temp_dir.path().join("key1.pem"), "key1").unwrap(); std::fs::write(temp_dir.path().join("cert2.pem"), "cert2").unwrap(); std::fs::write(temp_dir.path().join("key2.pem"), "key2").unwrap(); let output = std::process::Command::new(env!("CARGO_BIN_EXE_pollux")) .arg("--config") .arg(&config_path) .output() .unwrap(); // Duplicate table headers are not allowed in TOML, so this should fail assert!(!output.status.success()); } #[test] fn test_host_with_port_override() { let temp_dir = common::setup_test_environment(); let config_path = temp_dir.path().join("config.toml"); // Test server starts successfully let port = 1969 + (std::process::id() % 1000) as u16; let config_content = format!( r#" bind_host = "127.0.0.1" port = {} ["example.com"] root = "{}" cert = "{}" key = "{}" port = 1970 # Override global port "#, 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 = std::process::Command::new(env!("CARGO_BIN_EXE_pollux")) .arg("--config") .arg(&config_path) .spawn() .unwrap(); std::thread::sleep(std::time::Duration::from_millis(500)); assert!( server_process.try_wait().unwrap().is_none(), "Server should start with host port override" ); server_process.kill().unwrap(); } #[test] fn test_config_file_not_found() { let output = std::process::Command::new(env!("CARGO_BIN_EXE_pollux")) .arg("--config") .arg("nonexistent.toml") .output() .unwrap(); assert!(!output.status.success()); let stderr = String::from_utf8(output.stderr).unwrap(); assert!(stderr.contains("Config file 'nonexistent.toml' not found")); }