//! Integration tests for the `[client] bridges` field + [`aura_cli::dial_targets::build_dial_targets`]. //! //! Parses a synthetic `client.toml` with bridges, walks through `build_dial_targets`, and asserts //! the resulting candidate list shape. Real dial attempts are out of scope (no server running); //! this test focuses on the parse-build-shape contract that `client::run` relies on. use aura_cli::config::ClientConfigFile; use aura_cli::dial_targets::build_dial_targets; const CLIENT_TOML: &str = r#" [client] name = "laptop" server_addr = "203.0.113.10:443" sni = "vpn.example.com" bridges = ["203.0.113.11", "203.0.113.12:9999"] [pki] ca_cert = "ca.crt" cert = "client.crt" key = "client.key" [tunnel] local_ip = "10.7.0.2" "#; #[test] fn bridges_parse_into_client_config() { let cfg = ClientConfigFile::parse(CLIENT_TOML).expect("parse"); assert_eq!(cfg.client.bridges.len(), 2); assert!(cfg.client.bridges.contains(&"203.0.113.11".to_string())); assert!(cfg .client .bridges .contains(&"203.0.113.12:9999".to_string())); } #[test] fn build_dial_targets_from_parsed_client_config() { let cfg = ClientConfigFile::parse(CLIENT_TOML).expect("parse"); let dial = cfg.dial_config().expect("dial config"); let targets = build_dial_targets(&dial.endpoints, &cfg.client.bridges); assert_eq!(targets.len(), 3, "primary + two bridges"); // The primary is always first. assert_eq!(targets[0].udp.unwrap().to_string(), "203.0.113.10:443"); // Each bridge entry must keep the per-transport ports (the bridge `:9999` in the second // string is ignored — transports always use [transport] ports). for t in &targets[1..] { assert_eq!(t.udp.unwrap().port(), 443); assert_eq!(t.quic.unwrap().port(), 444); } // Both bridge IPs are represented. let bridge_ips: std::collections::HashSet = targets[1..] .iter() .map(|e| e.udp.unwrap().ip().to_string()) .collect(); assert!(bridge_ips.contains("203.0.113.11")); assert!(bridge_ips.contains("203.0.113.12")); } #[test] fn empty_bridges_field_yields_only_primary() { let toml = r#" [client] name = "laptop" server_addr = "203.0.113.10:443" sni = "vpn.example.com" [pki] ca_cert = "ca.crt" cert = "client.crt" key = "client.key" [tunnel] local_ip = "10.7.0.2" "#; let cfg = ClientConfigFile::parse(toml).expect("parse minimal"); assert!(cfg.client.bridges.is_empty(), "no bridges field"); let dial = cfg.dial_config().expect("dial config"); let targets = build_dial_targets(&dial.endpoints, &cfg.client.bridges); assert_eq!(targets.len(), 1, "only primary when bridges omitted"); } /// `detect_default_egress_iface` is best-effort and tolerated to be `None`. When it does return a /// value, the iface name must be non-empty. #[test] fn detect_default_egress_iface_is_tolerant() { match aura_cli::os_routes::detect_default_egress_iface() { Some(iface) => assert!(!iface.is_empty(), "detected iface name must be non-empty"), None => { // CI / sandboxed environments often have no default route. Tolerated. } } }