Files
nx9-wg/crates/nx9-wireguard/tests/test_native_conversions.rs
T

158 lines
4.5 KiB
Rust

//! Unit tests for native Linux WireGuard conversion utilities and error invariants.
//!
//! These tests verify CIDR parsing, endpoint parsing, key decoding, and peer
//! filtering without requiring CAP_NET_ADMIN or kernel mutation.
use base64::Engine as _;
use nx9_wg_core::types::wireguard::PeerState;
use nx9_wireguard::WireGuardError;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
#[test]
fn test_ipv4_cidr_parsing() {
let net: ipnet::IpNet = "10.0.0.2/32".parse().unwrap();
assert_eq!(net.addr(), IpAddr::V4(Ipv4Addr::new(10, 0, 0, 2)));
assert_eq!(net.prefix_len(), 32);
}
#[test]
fn test_ipv6_cidr_parsing() {
let net: ipnet::IpNet = "fd00::2/128".parse().unwrap();
assert!(net.addr().is_ipv6());
assert_eq!(net.prefix_len(), 128);
}
#[test]
fn test_multiple_allowed_ips_parsing() {
let csv = "10.0.0.2/32, fd00::2/128";
let nets: Vec<ipnet::IpNet> = csv
.split(',')
.map(|s| s.trim())
.filter(|s| !s.is_empty())
.map(|s| s.parse::<ipnet::IpNet>().unwrap())
.collect();
assert_eq!(nets.len(), 2);
assert!(nets[0].addr().is_ipv4());
assert!(nets[1].addr().is_ipv6());
}
#[test]
fn test_empty_allowed_ips() {
let csv = "";
let nets: Vec<ipnet::IpNet> = csv
.split(',')
.map(|s| s.trim())
.filter(|s| !s.is_empty())
.filter_map(|s| s.parse::<ipnet::IpNet>().ok())
.collect();
assert!(nets.is_empty());
}
#[test]
fn test_invalid_cidr_rejected() {
let result = "invalid/cidr".parse::<ipnet::IpNet>();
assert!(result.is_err());
}
#[test]
fn test_ipv4_endpoint_parsing() {
let addr: SocketAddr = "198.51.100.2:45000".parse().unwrap();
assert_eq!(addr.ip(), IpAddr::V4(Ipv4Addr::new(198, 51, 100, 2)));
assert_eq!(addr.port(), 45000);
}
#[test]
fn test_ipv6_endpoint_parsing() {
let addr: SocketAddr = "[2001:db8::1]:51820".parse().unwrap();
assert!(addr.ip().is_ipv6());
assert_eq!(addr.port(), 51820);
}
#[test]
fn test_invalid_endpoint_rejected() {
let result = "not-an-endpoint".parse::<SocketAddr>();
assert!(result.is_err());
}
#[test]
fn test_base64_key_decode_valid() {
let key_bytes = [0xAAu8; 32];
let b64 = base64::engine::general_purpose::STANDARD.encode(key_bytes);
let decoded = base64::engine::general_purpose::STANDARD
.decode(&b64)
.unwrap();
assert_eq!(decoded.len(), 32);
let mut arr = [0u8; 32];
arr.copy_from_slice(&decoded);
assert_eq!(arr, key_bytes);
}
#[test]
fn test_base64_key_decode_wrong_length() {
let short_key = [0xBBu8; 16];
let b64 = base64::engine::general_purpose::STANDARD.encode(short_key);
let decoded = base64::engine::general_purpose::STANDARD
.decode(&b64)
.unwrap();
assert_ne!(decoded.len(), 32);
}
#[test]
fn test_base64_key_decode_invalid_base64() {
let result = base64::engine::general_purpose::STANDARD.decode("not!valid!base64!!!");
assert!(result.is_err());
}
#[test]
fn test_peer_state_filtering() {
let states = [
PeerState::Active,
PeerState::Disabled,
PeerState::Revoked,
PeerState::Expired,
];
let active_count = states.iter().filter(|s| **s == PeerState::Active).count();
assert_eq!(active_count, 1, "only Active peers should be synchronized");
}
#[test]
fn test_error_display_no_key_leakage() {
let err = WireGuardError::Key("invalid base64".to_string());
let display = format!("{err}");
assert!(!display.contains("secret"));
assert!(!display.contains("private"));
assert!(display.contains("invalid base64"));
}
#[test]
fn test_error_variants_exist() {
let _ = format!("{}", WireGuardError::InterfaceNotFound("wg0".into()));
let _ = format!("{}", WireGuardError::WrongInterfaceType("eth0".into()));
let _ = format!("{}", WireGuardError::Unsupported("no kernel module".into()));
let _ = format!("{}", WireGuardError::InvalidEndpoint("bad:ep".into()));
let _ = format!("{}", WireGuardError::InvalidAllowedIp("bad/cidr".into()));
}
#[test]
fn test_prefix_length_preservation() {
let cases = [
("10.0.0.0/8", 8),
("10.0.0.0/16", 16),
("10.0.0.0/24", 24),
("10.0.0.1/32", 32),
("fd00::/64", 64),
("fd00::1/128", 128),
("0.0.0.0/0", 0),
("::/0", 0),
];
for (cidr, expected_prefix) in cases {
let net: ipnet::IpNet = cidr.parse().unwrap();
assert_eq!(
net.prefix_len(),
expected_prefix,
"prefix mismatch for {cidr}"
);
}
}