use std::net::{
Ipv4Addr,
Ipv6Addr,
SocketAddr,
SocketAddrV4,
SocketAddrV6
};
use ipnetwork::Ipv4Network;
use crate::util::fmt_bytes;
use crate::net::address::InterfaceAddress;
use crate::config::Config;
use crate::control::KeyArg;
use crate::peer::{
Address,
NodeID
};
#[test]
fn node_id() {
println!("testing known good id strings");
let good_ids: [(&str, [u8; 6]); 10] = [
("nbYYd1-k", [0x9D, 0xB6, 0x18, 0x77, 0x5F, 0xA4]),
("V6X_GkqJ", [0x57, 0xA5, 0xFF, 0x1A, 0x4A, 0x89]),
("pfL3udnz", [0xA5, 0xF2, 0xF7, 0xB9, 0xD9, 0xF3]),
("e1n7zlYm", [0x7B, 0x59, 0xFB, 0xCE, 0x56, 0x26]),
("rTsxHkTp", [0xAD, 0x3B, 0x31, 0x1E, 0x44, 0xE9]),
("0xATfaUf", [0xD3, 0x10, 0x13, 0x7D, 0xA5, 0x1F]),
("hcSDERrj", [0x85, 0xC4, 0x83, 0x11, 0x1A, 0xE3]),
("las0IFEY", [0x95, 0xAB, 0x34, 0x20, 0x51, 0x18]),
("q2kBjiUF", [0xAB, 0x69, 0x01, 0x8E, 0x25, 0x05]),
("t94Blkn8", [0xB7, 0xDE, 0x01, 0x96, 0x49, 0xFC])
];
for (id_str, id_bytes) in good_ids {
let id = id_str.parse::<NodeID>().unwrap();
assert_eq!(
id.get(),
id_bytes,
"str: {}, expected: {}, parsed: {}",
id_str,
fmt_bytes(&id_bytes),
fmt_bytes(&id.get())
);
}
let bad_ids = [
("", "empty"),
("nbYYd1", "corrupted"),
("lasFEY", "corrupted"),
("KsYLF8=", "corrupted"),
("t94Blkk=", "too short"),
("81PfIeMFLswhhk7mWS262pU2moc36g3NA5z6CKsYLF8=", "too long"),
("V6X/GkqJ", "wrong character set"),
("nbYYd1+k", "wrong character set"),
("========", "invalid base64"),
(" ", "invalid base64"),
("++++++++", "invalid base64"),
("↑↑↓↓←→", "invalid base64")
];
println!("testing bad id strings (they should fail to parse)");
for (id_str, description) in bad_ids {
print!("bad id str: \"{id_str}\" ({description})\t");
let err_msg = id_str.parse::<NodeID>().unwrap_err();
println!("parse error: {err_msg}");
}
}
#[test]
fn encryption_key() {
println!("testing known good key strings");
let good_keys: [(&str, u128, u128); 5] = [
( "9gU5dcNPXL2oWl/JiTMW4F9w+VUZduPKeWXxEUg5MW4=",
0xF6053975C34F5CBDA85A5FC9893316E0,
0x5F70F9551976E3CA7965F1114839316E
),
( "XZkl6H5tBXuVcYCiUm5wFfJr8LOf4c+ISd/hg9wU4gU=",
0x5D9925E87E6D057B957180A2526E7015,
0xF26BF0B39FE1CF8849DFE183DC14E205
),
( "bpoQ1NuWaoaZXxfc+jrdnpuYc+slFH13eIPhzBRII5w=",
0x6E9A10D4DB966A86995F17DCFA3ADD9E,
0x9B9873EB25147D777883E1CC1448239C
),
( "NUFHzgEUQg2917u+FhmgtTi6nXL1Hi1vDybnbpOPHl4=",
0x354147CE0114420DBDD7BBBE1619A0B5,
0x38BA9D72F51E2D6F0F26E76E938F1E5E
),
( "K1Tg4+2kHEHMt3XpUyAG63Vz8/da/KqybaRF3mes6Z8=",
0x2B54E0E3EDA41C41CCB775E9532006EB,
0x7573F3F75AFCAAB26DA445DE67ACE99F
)
];
for (key_str, key_half1, key_half2) in good_keys {
let mut key_bytes = [0u8; 32];
key_bytes[..16].copy_from_slice(&key_half1.to_be_bytes());
key_bytes[16..].copy_from_slice(&key_half2.to_be_bytes());
let key = key_str.parse::<KeyArg>().unwrap();
assert_eq!(
key.clone().get(),
key_bytes,
"\n\tstr: {},\n\texpected: {},\n\treceived: {}",
key_str,
fmt_bytes(&key_bytes),
fmt_bytes(&key.get())
);
}
let bad_keys = [
("", "empty"),
("KsYLF8=", "corrupted"),
("pfL3udnz", "too short"),
("1PfIeMFLswhhk7mWS262pU2moc36g3NA5z6CKsYLF8=", "corrupted"),
("81PfIeMFLswhhk7mWS262pU2mo36g3NA5z6CKsYLF8=", "corrupted"),
("e1IJF24IqcxGoZ5TIDME10vqHKYg13w7AL1U33E6/w==", "too short"),
("e1IJF24IqcxGoZ5TIDME10vqHKYg13w7AL1U33E6/yoq", "too long"),
("NUFHzgEUQg2917u-FhmgtTi6nXL1Hi1vDybnbpOPHl4=", "wrong character set"),
("========", "invalid base64"),
(" ", "invalid base64"),
("________", "invalid base64"),
("↑↑↓↓←→", "invalid base64")
];
println!("testing bad key strings (they should fail to parse)");
for (key_str, description) in bad_keys {
print!("bad key str: \"{key_str}\" ({description})\t");
let err_msg = key_str.parse::<KeyArg>().unwrap_err();
println!("parse error: {err_msg}");
}
}
#[test]
fn config_file() {
println!("generating default config, serializing and then deserializing");
let cfg = Config::default();
let cfg_string = cfg.to_pretty_string();
let parsed_cfg = toml::from_str::<Config>(&cfg_string).unwrap();
assert_eq!(parsed_cfg, cfg);
}
fn known_good_addresses() -> [(&'static str, SocketAddr); 6] {
[
(
"127.0.0.1:0",
SocketAddrV4::new(Ipv4Addr::LOCALHOST, 0).into()
),
(
"[::1]:0",
SocketAddrV6::new(Ipv6Addr::LOCALHOST, 0, 0, 0).into()
),
(
"127.0.0.1:9999",
SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9999).into()
),
(
"127.0.0.1:9999",
SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9999).into()
),
(
"[::1]:10000",
SocketAddrV6::new(Ipv6Addr::LOCALHOST, 10000, 0, 0).into()
),
(
"[::]:1",
SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, 1, 0, 0).into()
)
]
}
fn known_bad_addresses() -> [(&'static str, &'static str); 8] {
[
("127.0.0.1", "missing port"),
("[::1]", "missing port"),
("::1", "missing port"),
("::1:9999", "missing port"),
("::", "missing port"),
("127.0.0.1:99999", "bogus port"),
("127.0.0.0.1:9", "bogus ip"),
("256.0.0.1:9", "bogus ip")
]
}
#[test]
fn address() {
println!("testing known good addr strings");
let test_cases = known_good_addresses()
.map(|(addr_str, socket_addr)| (addr_str, match socket_addr {
SocketAddr::V4(addr) => Address::V4UdpChaCha20(addr),
SocketAddr::V6(addr) => Address::V6UdpChaCha20(addr)
}));
for (addr_str, if_addr) in test_cases {
println!("str: {addr_str:?}");
println!("expected: {if_addr}");
let parsed = addr_str.parse::<Address>().unwrap();
println!("received: {parsed}");
assert_eq!(parsed, if_addr);
}
println!("testing bad addr strings (they should fail to parse)");
for (bad_str, description) in known_bad_addresses() {
print!("bad addr str: \"{bad_str}\" ({description})\t");
let err_msg = bad_str.parse::<Address>().unwrap_err();
println!("parse error: {err_msg:?}");
}
}
#[test]
fn interface_address() {
use InterfaceAddress::V4UdpChaCha20 as V4UC;
use InterfaceAddress::V6UdpChaCha20 as V6UC;
let loopback_network = Ipv4Network::new(
Ipv4Addr::new(127, 0, 0, 0),
8
).unwrap();
let another_network = Ipv4Network::new(
Ipv4Addr::new(10, 0, 0, 0),
24
).unwrap();
let both_networks = || vec![loopback_network, another_network];
println!("testing known good iface addr strings");
let without_routes = known_good_addresses()
.map(|(addr_str, socket_addr)| (addr_str, match socket_addr {
SocketAddr::V4(addr) => V4UC{addr, if_name: None, routes: vec![]},
SocketAddr::V6(addr) => V6UC{addr, if_name: None, routes: vec![]}
}));
let with_routes = [
("127.0.0.1:9999 /8", V4UC {
addr: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9999),
if_name: None,
routes: vec![loopback_network]
}),
("127.0.0.1:9999 127.0.0.0/8", V4UC {
addr: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9999),
if_name: None,
routes: vec![loopback_network]
}),
("127.0.0.1:9999 127.0.0.1/8", V4UC {
addr: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9999),
if_name: None,
routes: vec![loopback_network]
}),
("127.0.0.1:9999 127.0.255.255/8", V4UC {
addr: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9999),
if_name: None,
routes: vec![loopback_network]
}),
("127.0.0.1:9999 10.0.0.0/24", V4UC {
addr: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9999),
if_name: None,
routes: vec![another_network]
}),
("10.0.0.33:9999 /24", V4UC {
addr: SocketAddrV4::new(Ipv4Addr::new(10, 0, 0, 33), 9999),
if_name: None,
routes: vec![another_network]
}),
("127.0.0.1:9999 /8 10.0.0.0/24", V4UC {
addr: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9999),
if_name: None,
routes: both_networks()
}),
("127.0.0.1:9999 127.0.0.0/8 10.0.0.0/24", V4UC {
addr: SocketAddrV4::new(Ipv4Addr::LOCALHOST, 9999),
if_name: None,
routes: both_networks()
})
];
let test_cases = without_routes.into_iter().chain(with_routes);
for (addr_str, if_addr) in test_cases {
println!("str: {addr_str:?}");
println!("expected: {if_addr}");
let parsed = addr_str.parse::<InterfaceAddress>().unwrap();
println!("received: {parsed}");
assert_eq!(parsed, if_addr);
}
let with_routes = [
("127.0.0.1:9 /33", "bogus prefix"),
("127.0.0.1:9 /0 /0", "double prefix"),
("127.0.0.1:9 ::1/0", "ip version mismatch"),
("127.0.0.1:9 /0 ::1/0", "ip version mismatch")
];
let test_cases = known_bad_addresses().into_iter().chain(with_routes);
println!("testing bad iface addr strings (they should fail to parse)");
for (bad_str, description) in test_cases {
print!("bad iface_addr str: \"{bad_str}\" ({description})\t");
let err_msg = bad_str.parse::<InterfaceAddress>().unwrap_err();
println!("parse error: {err_msg:?}");
}
}