use std::error::Error as _;
use flowscope::{Error, ErrorCode, Module};
#[test]
fn send_sync_static() {
fn assert_traits<T: Send + Sync + 'static>() {}
assert_traits::<Error>();
}
#[test]
fn match_on_module_and_code() {
let r = flowscope::pcap::PcapFlowSource::open("/no/such/path.pcap");
let err = r.err().expect("open of nonexistent file should fail");
match (err.module(), err.code()) {
(Module::Pcap, ErrorCode::Io) => { }
other => panic!("expected (Pcap, Io); got {other:?}"),
}
}
#[test]
fn io_error_carries_source() {
let r = flowscope::pcap::PcapFlowSource::open("/no/such/path.pcap");
let err = r.err().unwrap();
let src = err
.source()
.expect("io error should chain to std::io::Error");
let s = src.to_string();
assert!(!s.is_empty(), "source must display non-empty");
let io = src
.downcast_ref::<std::io::Error>()
.expect("source should downcast to io::Error");
assert_eq!(io.kind(), std::io::ErrorKind::NotFound);
}
#[cfg(feature = "dns")]
#[test]
fn dns_parse_error_routes_correctly() {
let r = flowscope::dns::parse_message(&[0u8; 4]);
let err = r.err().unwrap();
assert_eq!(err.module(), Module::Dns);
assert_eq!(err.code(), ErrorCode::Parse);
assert!(err.is_recoverable());
}
#[cfg(feature = "dns")]
#[test]
fn dns_parse_error_with_source_chain() {
let payload = [0xffu8; 16];
let r = flowscope::dns::parse_message(&payload);
let err = r.err().unwrap();
assert_eq!(err.module(), Module::Dns);
assert_eq!(err.code(), ErrorCode::Parse);
assert!(err.to_string().contains("simple-dns"));
}
#[cfg(feature = "icmp")]
#[test]
fn icmp_parse_error_carries_source() {
let r = flowscope::icmp::parse_v4(&[]);
let err = r.err().unwrap();
assert_eq!(err.module(), Module::Icmp);
assert_eq!(err.code(), ErrorCode::Parse);
assert!(err.source().is_some(), "etherparse error should chain");
}
#[test]
fn display_format_stable_shape() {
let r = flowscope::pcap::PcapFlowSource::open("/no/such/path.pcap");
let err = r.err().unwrap();
let s = err.to_string();
assert!(s.starts_with("pcap: io: "), "got {s:?}");
}