155 lines
4.7 KiB
Rust
155 lines
4.7 KiB
Rust
//! Kernel-independent unit and conversion tests for Phase 2 Native Linux Network Engine.
|
|
|
|
use chrono::Utc;
|
|
use ipnet::IpNet;
|
|
use nx9_wg_core::types::network::Route;
|
|
use nx9_wg_network::error::NetworkError;
|
|
use nx9_wg_network::forwarding::IpForwardingStatus;
|
|
use std::net::{IpAddr, Ipv4Addr};
|
|
use std::str::FromStr;
|
|
use uuid::Uuid;
|
|
|
|
#[test]
|
|
fn test_ipv4_route_destination_conversion() {
|
|
let dest = IpNet::from_str("192.168.10.0/24").expect("valid cidr");
|
|
assert_eq!(dest.addr(), IpAddr::V4(Ipv4Addr::new(192, 168, 10, 0)));
|
|
assert_eq!(dest.prefix_len(), 24);
|
|
}
|
|
|
|
#[test]
|
|
fn test_ipv6_route_destination_conversion() {
|
|
let dest = IpNet::from_str("fd00:abcd::/64").expect("valid ipv6 cidr");
|
|
assert_eq!(dest.prefix_len(), 64);
|
|
assert!(dest.addr().is_ipv6());
|
|
}
|
|
|
|
#[test]
|
|
fn test_optional_gateway_resolution() {
|
|
let now = Utc::now().naive_utc();
|
|
let r_with_gw = Route {
|
|
id: Uuid::new_v4(),
|
|
network_id: None,
|
|
interface_id: None,
|
|
destination: IpNet::from_str("10.100.0.0/16").unwrap(),
|
|
gateway: Some(IpAddr::from_str("10.0.0.1").unwrap()),
|
|
interface_name: Some("wg0".to_string()),
|
|
metric: Some(50),
|
|
enabled: true,
|
|
description: None,
|
|
created_at: now,
|
|
updated_at: now,
|
|
};
|
|
|
|
assert!(r_with_gw.gateway.is_some());
|
|
assert_eq!(
|
|
r_with_gw.gateway.unwrap(),
|
|
IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1))
|
|
);
|
|
|
|
let r_no_gw = Route {
|
|
id: Uuid::new_v4(),
|
|
network_id: None,
|
|
interface_id: None,
|
|
destination: IpNet::from_str("10.200.0.0/16").unwrap(),
|
|
gateway: None,
|
|
interface_name: Some("wg0".to_string()),
|
|
metric: None,
|
|
enabled: true,
|
|
description: None,
|
|
created_at: now,
|
|
updated_at: now,
|
|
};
|
|
|
|
assert!(r_no_gw.gateway.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn test_default_route_safety_invariants() {
|
|
let v4_default = IpNet::from_str("0.0.0.0/0").unwrap();
|
|
assert!(v4_default.addr().is_unspecified());
|
|
assert_eq!(v4_default.prefix_len(), 0);
|
|
|
|
let v6_default = IpNet::from_str("::/0").unwrap();
|
|
assert!(v6_default.addr().is_unspecified());
|
|
assert_eq!(v6_default.prefix_len(), 0);
|
|
|
|
let non_default = IpNet::from_str("10.0.0.0/8").unwrap();
|
|
assert!(!non_default.addr().is_unspecified() || non_default.prefix_len() != 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_forwarding_status_serde() {
|
|
let status = IpForwardingStatus {
|
|
ipv4_enabled: true,
|
|
ipv6_enabled: false,
|
|
};
|
|
|
|
let json = serde_json::to_string(&status).expect("serialize");
|
|
assert!(json.contains("\"ipv4_enabled\":true"));
|
|
assert!(json.contains("\"ipv6_enabled\":false"));
|
|
|
|
let deserialized: IpForwardingStatus = serde_json::from_str(&json).expect("deserialize");
|
|
assert_eq!(status, deserialized);
|
|
}
|
|
|
|
#[test]
|
|
fn test_error_variants_formatting() {
|
|
let err_iface = NetworkError::InterfaceNotFound("wg-test".to_string());
|
|
assert_eq!(err_iface.to_string(), "interface 'wg-test' not found");
|
|
|
|
let err_addr = NetworkError::AddressNotFound("10.0.0.1/24".to_string());
|
|
assert_eq!(err_addr.to_string(), "address '10.0.0.1/24' not found");
|
|
|
|
let err_route = NetworkError::RouteNotFound("192.168.1.0/24".to_string());
|
|
assert_eq!(err_route.to_string(), "route '192.168.1.0/24' not found");
|
|
|
|
let err_netlink = NetworkError::Netlink("Netlink connection refused".to_string());
|
|
assert_eq!(
|
|
err_netlink.to_string(),
|
|
"netlink error: Netlink connection refused"
|
|
);
|
|
|
|
let err_perm = NetworkError::PermissionDenied("Operation requires CAP_NET_ADMIN".to_string());
|
|
assert_eq!(
|
|
err_perm.to_string(),
|
|
"permission denied: Operation requires CAP_NET_ADMIN"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_route_equality_and_filtering() {
|
|
let now = Utc::now().naive_utc();
|
|
let r1 = Route {
|
|
id: Uuid::new_v4(),
|
|
network_id: None,
|
|
interface_id: None,
|
|
destination: IpNet::from_str("172.16.0.0/12").unwrap(),
|
|
gateway: Some(IpAddr::from_str("10.0.0.254").unwrap()),
|
|
interface_name: Some("wg0".to_string()),
|
|
metric: Some(20),
|
|
enabled: true,
|
|
description: None,
|
|
created_at: now,
|
|
updated_at: now,
|
|
};
|
|
|
|
let r2 = Route {
|
|
id: Uuid::new_v4(),
|
|
network_id: None,
|
|
interface_id: None,
|
|
destination: IpNet::from_str("172.16.0.0/12").unwrap(),
|
|
gateway: Some(IpAddr::from_str("10.0.0.254").unwrap()),
|
|
interface_name: Some("wg0".to_string()),
|
|
metric: Some(20),
|
|
enabled: false,
|
|
description: None,
|
|
created_at: now,
|
|
updated_at: now,
|
|
};
|
|
|
|
assert_eq!(r1.destination, r2.destination);
|
|
assert_eq!(r1.gateway, r2.gateway);
|
|
assert!(r1.enabled);
|
|
assert!(!r2.enabled);
|
|
}
|