#[cfg(test)]
mod tests {
use crate::traceroute::{AsnInfo, SegmentType};
use std::net::Ipv4Addr;
#[test]
fn test_transit_classification_no_asn_public_ip() {
let ipv4 = Ipv4Addr::new(206, 223, 116, 16);
let is_internal = crate::traceroute::is_internal_ip(&ipv4);
let is_cgnat = crate::traceroute::is_cgnat(&ipv4);
assert!(!is_internal, "206.223.116.16 should not be internal");
assert!(!is_cgnat, "206.223.116.16 should not be CGNAT");
let in_isp_segment = true; let asn_info: Option<AsnInfo> = None;
let segment = if !is_internal && !is_cgnat && asn_info.is_none() && in_isp_segment {
SegmentType::Transit
} else {
SegmentType::Unknown
};
assert_eq!(
segment,
SegmentType::Transit,
"Public IP without ASN after ISP should be TRANSIT"
);
}
#[test]
fn test_destination_segment_with_matching_asn() {
let dest_asn = Some(15169u32);
let hop_asn_info = Some(AsnInfo {
asn: 15169,
prefix: "142.250.0.0/15".to_string(),
country_code: "US".to_string(),
registry: "arin".to_string(),
name: "GOOGLE, US".to_string(),
});
let segment = if let Some(asn_info) = &hop_asn_info {
if let Some(dest) = dest_asn {
if asn_info.asn == dest {
SegmentType::Destination
} else {
SegmentType::Transit
}
} else {
SegmentType::Unknown
}
} else {
SegmentType::Unknown
};
assert_eq!(
segment,
SegmentType::Destination,
"Hop with ASN matching destination should be DESTINATION"
);
}
#[test]
fn test_transit_segment_different_asn() {
let isp_asn = Some(46375u32); let dest_asn = Some(15169u32); let _in_isp_segment = false;
let hop_asn_info = Some(AsnInfo {
asn: 10310, prefix: "209.191.64.0/20".to_string(),
country_code: "US".to_string(),
registry: "arin".to_string(),
name: "YAHOO-1, US".to_string(),
});
let segment = if let Some(asn_info) = &hop_asn_info {
if let Some(isp) = isp_asn {
if asn_info.asn == isp {
SegmentType::Isp
} else if let Some(dest) = dest_asn {
if asn_info.asn == dest {
SegmentType::Destination
} else {
SegmentType::Transit
}
} else {
SegmentType::Transit
}
} else {
SegmentType::Unknown
}
} else {
SegmentType::Unknown
};
assert_eq!(
segment,
SegmentType::Transit,
"Hop with ASN different from ISP and destination should be TRANSIT"
);
}
#[test]
fn test_isp_segment_classification() {
let cgnat_ip = Ipv4Addr::new(100, 65, 0, 1);
assert!(
crate::traceroute::is_cgnat(&cgnat_ip),
"100.65.0.1 should be in CGNAT range"
);
let isp_asn = Some(46375u32);
let hop_asn = AsnInfo {
asn: 46375,
prefix: "75.101.32.0/19".to_string(),
country_code: "US".to_string(),
registry: "arin".to_string(),
name: "AS-SONICTELECOM, US".to_string(),
};
let segment = if Some(hop_asn.asn) == isp_asn {
SegmentType::Isp
} else {
SegmentType::Unknown
};
assert_eq!(
segment,
SegmentType::Isp,
"Hop with ASN matching ISP should be ISP segment"
);
}
#[test]
fn test_lan_segment_classification() {
let private_ips = vec![
Ipv4Addr::new(192, 168, 1, 1), Ipv4Addr::new(10, 0, 0, 1), Ipv4Addr::new(172, 16, 0, 1), Ipv4Addr::new(127, 0, 0, 1), Ipv4Addr::new(169, 254, 0, 1), ];
for ip in private_ips {
assert!(
crate::traceroute::is_internal_ip(&ip),
"{} should be classified as internal/LAN",
ip
);
}
let public_ips = vec![
Ipv4Addr::new(8, 8, 8, 8),
Ipv4Addr::new(1, 1, 1, 1),
Ipv4Addr::new(206, 223, 116, 16),
];
for ip in public_ips {
assert!(
!crate::traceroute::is_internal_ip(&ip),
"{} should NOT be classified as internal/LAN",
ip
);
}
}
#[test]
fn test_segment_priority_in_classification() {
let isp_asn = Some(46375u32);
let dest_asn = Some(46375u32); let in_isp_segment = true;
let hop_asn = AsnInfo {
asn: 46375,
prefix: "75.101.32.0/19".to_string(),
country_code: "US".to_string(),
registry: "arin".to_string(),
name: "AS-SONICTELECOM, US".to_string(),
};
let segment = if in_isp_segment && Some(hop_asn.asn) == isp_asn {
SegmentType::Isp
} else if Some(hop_asn.asn) == dest_asn {
SegmentType::Destination
} else {
SegmentType::Transit
};
assert_eq!(
segment,
SegmentType::Isp,
"When in ISP segment, ISP classification should take priority"
);
}
}