From b8566fdc030df2cf222dfcb168094d8da06bcf3d Mon Sep 17 00:00:00 2001 From: aggstam Date: Mon, 10 Oct 2022 21:27:43 +0300 Subject: [PATCH] p2pnet/hosts.rs: filtering tests added --- src/net/hosts.rs | 194 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) diff --git a/src/net/hosts.rs b/src/net/hosts.rs index 73612afb3..d23a6820c 100644 --- a/src/net/hosts.rs +++ b/src/net/hosts.rs @@ -278,3 +278,197 @@ fn is_valid_onion(onion: &str) -> bool { base32::decode(&onion.to_uppercase()).is_some() } + +#[cfg(test)] +mod tests { + use std::net::{IpAddr, Ipv4Addr}; + + use fxhash::{FxHashMap, FxHashSet}; + use ipnet::{Ipv4Net, Ipv6Net}; + use iprange::IpRange; + // Uncomment for inner logging + //use simplelog::{ColorChoice, Config, LevelFilter, TermLogger, TerminalMode}; + use url::Url; + + use crate::net::{ + constants::{IP4_PRIV_RANGES, IP6_PRIV_RANGES}, + hosts::{filter_invalid, filter_localnet, filter_non_resolving, is_valid_onion}, + }; + + #[test] + fn test_filter_localnet() { + // Uncomment for inner logging + /* + TermLogger::init( + LevelFilter::Debug, + Config::default(), + TerminalMode::Mixed, + ColorChoice::Auto, + ) + .unwrap(); + */ + + // Create addresses to test + let valid = Url::parse("tls://facebook.com:13333").unwrap(); + let onion = Url::parse( + "tor://facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion:13333", + ) + .unwrap(); + let localhost = Url::parse("tls://localhost:13333").unwrap(); + let localip = Url::parse("tls://127.0.0.1:13333").unwrap(); + + // Create input addresses vector + let input_addrs = vec![valid.clone(), onion.clone(), localhost, localip]; + + // Create expected output addresses vector + let output_addrs = vec![valid, onion]; + let output_addrs = FxHashSet::from_iter(output_addrs.iter()); + + // Execute filtering for v4 addr + let filtered = filter_localnet(input_addrs); + let filtered = FxHashSet::from_iter(filtered.iter()); + // Validate filtered addresses + assert_eq!(output_addrs, filtered); + } + + #[test] + fn test_filter_invalid() { + // Uncomment for inner logging + /* + TermLogger::init( + LevelFilter::Debug, + Config::default(), + TerminalMode::Mixed, + ColorChoice::Auto, + ) + .unwrap(); + */ + + // Initialize ipv4_range and ipv6_range if needed + let mut ipv4_range: IpRange = + IP4_PRIV_RANGES.iter().map(|s| s.parse().unwrap()).collect(); + let mut ipv6_range: IpRange = + IP6_PRIV_RANGES.iter().map(|s| s.parse().unwrap()).collect(); + + // These will make the trie potentially smaller + ipv4_range.simplify(); + ipv6_range.simplify(); + + // Create addresses to test + let valid = Url::parse("tls://facebook.com:13333").unwrap(); + let domainless = Url::parse("unix:/run/foo.socket").unwrap(); + let mut hostless = Url::parse("tls://185.60.216.35:13333").unwrap(); + hostless.set_host(None).unwrap(); + let onion = Url::parse( + "tor://facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion:13333", + ) + .unwrap(); + let invalid_onion = + Url::parse("tor://facebookwemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion:13333") + .unwrap(); + + // Create input addresses vector + let input_addrs = vec![valid.clone(), domainless, hostless, onion.clone(), invalid_onion]; + + // Create expected output addresses vector + let output_addrs = vec![valid, onion]; + let output_addrs = FxHashSet::from_iter(output_addrs.iter()); + + // Execute filtering for v4 addr + let filtered = filter_invalid(&ipv4_range, &ipv6_range, input_addrs); + let filtered: Vec = filtered.into_iter().map(|(k, _)| k).collect(); + let filtered = FxHashSet::from_iter(filtered.iter()); + // Validate filtered addresses + assert_eq!(output_addrs, filtered); + } + + #[test] + fn test_filter_non_resolving() { + // Uncomment for inner logging + /* + TermLogger::init( + LevelFilter::Debug, + Config::default(), + TerminalMode::Mixed, + ColorChoice::Auto, + ) + .unwrap(); + */ + + // Create addresses to test + let connection_url_v4 = Url::parse("tls://185.60.216.35:13333").unwrap(); + let connection_url_v6 = + Url::parse("tls://[2a03:2880:f12d:83:face:b00c:0:25de]:13333").unwrap(); + let fake_connection_url = Url::parse("tls://185.199.109.153:13333").unwrap(); + let resolving_url = Url::parse("tls://facebook.com:13333").unwrap(); + let random_url = Url::parse("tls://facebookkk.com:13333").unwrap(); + let onion = Url::parse( + "tor://facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion:13333", + ) + .unwrap(); + + // Create input addresses hashmap, containing created addresses, excluding connection url + let mut input_addrs = FxHashMap::default(); + input_addrs.insert( + resolving_url.clone(), + vec![ + IpAddr::V4(Ipv4Addr::new(185, 60, 216, 35)), + "2a03:2880:f12d:83:face:b00c:0:25de".parse().unwrap(), + ], + ); + input_addrs.insert(random_url, vec![]); + input_addrs.insert(onion.clone(), vec![]); + + // Create expected output addresses hashset + let mut output_addrs = FxHashMap::default(); + output_addrs.insert( + resolving_url, + vec![ + IpAddr::V4(Ipv4Addr::new(185, 60, 216, 35)), + "2a03:2880:f12d:83:face:b00c:0:25de".parse().unwrap(), + ], + ); + output_addrs.insert(onion.clone(), vec![]); + // Convert hashmap to Vec = output_addrs.into_iter().map(|(k, _)| k).collect(); + let output_addrs = FxHashSet::from_iter(output_addrs.iter()); + + let mut fake_output_addrs: FxHashMap> = FxHashMap::default(); + // Onion addresses don't get filtered, as we can't resolve them + fake_output_addrs.insert(onion, vec![]); + let fake_output_addrs: Vec = fake_output_addrs.into_iter().map(|(k, _)| k).collect(); + let fake_output_addrs = FxHashSet::from_iter(fake_output_addrs.iter()); + + // Execute filtering for v4 addr + let filtered = filter_non_resolving(connection_url_v4, input_addrs.clone()); + let filtered = FxHashSet::from_iter(filtered.iter()); + // Validate filtered addresses + assert_eq!(output_addrs, filtered); + + // Execute filtering for v6 addr + let filtered = filter_non_resolving(connection_url_v6, input_addrs.clone()); + let filtered = FxHashSet::from_iter(filtered.iter()); + assert_eq!(output_addrs, filtered); + + // Execute filtering for fake addr + let filtered = filter_non_resolving(fake_connection_url, input_addrs); + let filtered = FxHashSet::from_iter(filtered.iter()); + assert_eq!(fake_output_addrs, filtered); + } + + #[test] + fn test_is_valid_onion() { + // Valid onion + assert_eq!( + is_valid_onion("facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd.onion"), + true + ); + // Valid onion without .onion suffix + assert_eq!( + is_valid_onion("facebookwkhpilnemxj7asaniu7vnjjbiltxjqhye3mhbshg7kx5tfyd"), + true + ); + // Invalid onion + assert_eq!(is_valid_onion("facebook.com"), false); + } +}