use super::*;
use std::net::{Ipv4Addr, Ipv6Addr};
#[test]
fn test_resolve_endpoint_success() {
let mut env = HashMap::new();
let host = HostDef {
name: "node_a",
ip: IpAddr::V4(Ipv4Addr::new(192, 168, 1, 10)),
mac: Some([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]),
span: (0, 10),
};
env.insert("node_a", host.clone());
let arg = Argument::Variable("node_a");
let resolved = resolve_endpoint(&arg, &env).expect("Failed to resolve defined host");
assert_eq!(resolved.name, "node_a");
assert_eq!(resolved.ip, IpAddr::V4(Ipv4Addr::new(192, 168, 1, 10)));
assert_eq!(resolved.mac, Some([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]));
}
#[test]
fn test_resolve_endpoint_undefined_error() {
let env = HashMap::new();
let arg = Argument::Variable("unknown_node");
let result = resolve_endpoint(&arg, &env);
assert!(result.is_err());
assert!(result.unwrap_err().contains("Undefined variable"));
}
#[test]
fn test_derive_mac_statement_override() {
let stmt_mac = Some([0xde, 0xad, 0xbe, 0xef, 0x00, 0x01]);
let host_mac = Some([0x00, 0x11, 0x22, 0x33, 0x44, 0x55]);
let ip = IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1));
let derived = derive_mac(host_mac, stmt_mac, ip, true);
assert_eq!(derived, [0xde, 0xad, 0xbe, 0xef, 0x00, 0x01]);
}
#[test]
fn test_derive_mac_host_fallback() {
let stmt_mac = None;
let host_mac = Some([0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]);
let ip = IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1));
let derived = derive_mac(host_mac, stmt_mac, ip, true);
assert_eq!(derived, [0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]);
}
#[test]
fn test_derive_mac_ipv4_multicast_rfc1112() {
let mcast_ip1 = IpAddr::V4(Ipv4Addr::new(224, 0, 0, 1));
let mac1 = derive_mac(None, None, mcast_ip1, false);
assert_eq!(mac1, [0x01, 0x00, 0x5E, 0x00, 0x00, 0x01]);
let mcast_ip2 = IpAddr::V4(Ipv4Addr::new(239, 255, 1, 2));
let mac2 = derive_mac(None, None, mcast_ip2, false);
assert_eq!(mac2, [0x01, 0x00, 0x5E, 0x7F, 0x01, 0x02]);
}
#[test]
fn test_derive_mac_ipv6_multicast_rfc2464() {
let mcast_v6 = IpAddr::V6(Ipv6Addr::new(0xff02, 0, 0, 0, 0, 0, 0, 1));
let mac = derive_mac(None, None, mcast_v6, false);
assert_eq!(mac, [0x33, 0x33, 0x00, 0x00, 0x00, 0x01]);
}
#[test]
fn test_derive_mac_unicast_defaults() {
let caller_ip = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 1));
let callee_ip = IpAddr::V4(Ipv4Addr::new(192, 168, 1, 2));
let caller_mac = derive_mac(None, None, caller_ip, true);
let callee_mac = derive_mac(None, None, callee_ip, false);
assert_eq!(caller_mac, [0x00, 0x00, 0x00, 0x00, 0x00, 0x01]);
assert_eq!(callee_mac, [0x00, 0x00, 0x00, 0x00, 0x00, 0x02]);
}
#[test]
fn test_default_dst_port_mappings() {
assert_eq!(default_dst_port(&Protocol::Dns, None), 53);
assert_eq!(default_dst_port(&Protocol::Dhcp, None), 67);
assert_eq!(default_dst_port(&Protocol::Ntp, None), 123);
assert_eq!(default_dst_port(&Protocol::Http, None), 80);
assert_eq!(default_dst_port(&Protocol::Http2, None), 443);
assert_eq!(default_dst_port(&Protocol::Bgp, None), 179);
assert_eq!(default_dst_port(&Protocol::Vxlan, None), 4789);
assert_eq!(default_dst_port(&Protocol::Wireguard, None), 51820);
assert_eq!(default_dst_port(&Protocol::Modbus, None), 502);
assert_eq!(default_dst_port(&Protocol::Snmp1, Some(&SnmpPduType::Trap)), 162);
assert_eq!(default_dst_port(&Protocol::Snmp2, Some(&SnmpPduType::Get)), 161);
assert_eq!(default_dst_port(&Protocol::Arp, None), 0);
assert_eq!(default_dst_port(&Protocol::Icmp, None), 0);
assert_eq!(default_dst_port(&Protocol::Ospf, None), 0);
}
#[test]
fn test_is_tcp_protocol_logic() {
assert!(is_tcp_protocol(&Protocol::Tcp, None));
assert!(is_tcp_protocol(&Protocol::Bgp, None));
assert!(is_tcp_protocol(&Protocol::Http, None));
assert!(is_tcp_protocol(&Protocol::Ssh, None));
assert!(is_tcp_protocol(&Protocol::Modbus, None));
assert!(!is_tcp_protocol(&Protocol::Modbus, Some(TransportProto::Udp)));
assert!(!is_tcp_protocol(&Protocol::Dns, None));
assert!(is_tcp_protocol(&Protocol::Dns, Some(TransportProto::Tcp)));
}
#[test]
fn test_generate_pcap_end_to_end() {
let dsl = r#"
HOST client { IP 10.0.0.1 MAC 00:11:22:33:44:55 }
HOST server { IP 10.0.0.2 MAC 00:aa:bb:cc:dd:ee }
FLOW test_flow(c, s) {
c -> s UDP DSTPORT 8080 SRCPORT 5000 PAYLOAD "FrameAssembly Test"
}
COMPILE {
test_flow(client, server)
}
"#;
let program = crate::parser::parse_program(dsl).expect("Failed to parse valid DSL");
let temp_dir = std::env::temp_dir();
let temp_pcap = temp_dir.join("test_frameassembly_backend.pcap");
let pcap_path = temp_pcap.to_str().expect("Valid path");
let result = generate_pcap(&program, pcap_path);
assert!(result.is_ok(), "generate_pcap failed: {:?}", result.err());
let metadata = std::fs::metadata(&temp_pcap).expect("PCAP file must exist");
assert!(metadata.len() > 24, "PCAP must contain global header and packets");
let _ = std::fs::remove_file(&temp_pcap);
}