diff --git a/Cargo.lock b/Cargo.lock index 622460ba..36bbe62c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -299,6 +299,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "ctor" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad291aa74992b9b7a7e88c38acbbf6ad7e107f1d90ee8775b7bc1fc3394f485c" +dependencies = [ + "quote", + "syn 2.0.37", +] + [[package]] name = "cxx" version = "1.0.68" @@ -1987,6 +1997,7 @@ version = "0.1.0" dependencies = [ "chrono", "clap", + "ctor", "dns-lookup", "env_logger", "idna 0.3.0", diff --git a/vsock_proxy/Cargo.toml b/vsock_proxy/Cargo.toml index e47a4a7a..3daf60f2 100644 --- a/vsock_proxy/Cargo.toml +++ b/vsock_proxy/Cargo.toml @@ -20,5 +20,6 @@ threadpool = "1.7.1" vsock = "0.3" [dev-dependencies] +ctor = "0.2.7" rand = "0.8.5" tempfile = "3.5.0" diff --git a/vsock_proxy/src/dns.rs b/vsock_proxy/src/dns.rs index 01f86213..fb0e2e7a 100644 --- a/vsock_proxy/src/dns.rs +++ b/vsock_proxy/src/dns.rs @@ -59,3 +59,86 @@ pub fn resolve_single(addr: &str, ip_addr_type: IpAddrType) -> VsockProxyResult< // We already know that rresults containt at least one item. Ok(rresults.first().unwrap().clone()) } + +#[cfg(test)] +mod tests { + use super::*; + + use ctor::ctor; + use std::sync::Once; + use std::env; + + static TEST_INIT: Once = Once::new(); + + static mut INVALID_TEST_DOMAIN: &'static str = "invalid-domain"; + static mut IPV4_ONLY_TEST_DOMAIN: &'static str = "v4.ipv6test.app"; + static mut IPV6_ONLY_TEST_DOMAIN: &'static str = "v6.ipv6test.app"; + static mut DUAL_IP_TEST_DOMAIN: &'static str = "ipv6test.app"; + + #[test] + #[ctor] + fn init() { + // *** To use nonlocal domain names, set TEST_NONLOCAL_DOMAINS variable. *** + // *** TEST_NONLOCAL_DOMAINS=1 cargo test *** + TEST_INIT.call_once(|| { + if env::var_os("TEST_NONLOCAL_DOMAINS").is_none() { + eprintln!("[warn] dns: using 'localhost' for testing."); + unsafe { + IPV4_ONLY_TEST_DOMAIN = "localhost"; + IPV6_ONLY_TEST_DOMAIN = "::1"; + DUAL_IP_TEST_DOMAIN = "localhost"; + } + } + }); + } + + #[test] + fn test_resolve_valid_domain() { + let domain = unsafe { IPV4_ONLY_TEST_DOMAIN }; + let rresults = resolve(domain, IpAddrType::IPAddrMixed).unwrap(); + assert!(!rresults.is_empty()); + } + + #[test] + fn test_resolve_valid_dual_ip_domain() { + let domain = unsafe { DUAL_IP_TEST_DOMAIN }; + let rresults = resolve(domain, IpAddrType::IPAddrMixed).unwrap(); + assert!(!rresults.is_empty()); + } + + #[test] + fn test_resolve_invalid_domain() { + let domain = unsafe { INVALID_TEST_DOMAIN }; + let rresults = resolve(domain, IpAddrType::IPAddrMixed); + assert!(rresults.is_err() && rresults.err().unwrap().eq("DNS lookup failed!")); + } + + #[test] + fn test_resolve_ipv4_only() { + let domain = unsafe { IPV4_ONLY_TEST_DOMAIN }; + let rresults = resolve(domain, IpAddrType::IPAddrV4Only).unwrap(); + assert!(rresults.iter().all(|item| item.ip.is_ipv4())); + } + + #[test] + fn test_resolve_ipv6_only() { + let domain = unsafe { IPV6_ONLY_TEST_DOMAIN }; + let rresults = resolve(domain, IpAddrType::IPAddrV6Only).unwrap(); + assert!(rresults.iter().all(|item| item.ip.is_ipv6())); + } + + #[test] + fn test_resolve_no_accepted_ip() { + let domain = unsafe { IPV4_ONLY_TEST_DOMAIN }; + let rresults = resolve(domain, IpAddrType::IPAddrV6Only); + assert!(rresults.is_err() && rresults.err().unwrap().eq("No accepted IP was found.")); + } + + #[test] + fn test_resolve_single_address() { + let domain = unsafe { IPV4_ONLY_TEST_DOMAIN }; + let rresult = resolve_single(domain, IpAddrType::IPAddrMixed).unwrap(); + assert!(rresult.ip.is_ipv4()); + assert!(rresult.ttl != 0); + } +}