#[macro_use]
extern crate lazy_static;
use nmap_xml_parser::{host, port, NmapResults};
use std::fs;
use std::path::PathBuf;
lazy_static! {
static ref NMAP_TEST_XML: NmapResults = {
let mut path = PathBuf::new();
path.push(&std::env::var("CARGO_MANIFEST_DIR").unwrap());
path.push("tests/test.xml");
let content = fs::read_to_string(path).unwrap();
NmapResults::parse(&content).unwrap()
};
static ref NMAP_ISSUE_ONE: NmapResults = {
let mut path = PathBuf::new();
path.push(&std::env::var("CARGO_MANIFEST_DIR").unwrap());
path.push("tests/issue_1.xml");
let content = fs::read_to_string(path).unwrap();
NmapResults::parse(&content).unwrap()
};
static ref NMAP_HOST_DOWN: NmapResults = {
let mut path = PathBuf::new();
path.push(&std::env::var("CARGO_MANIFEST_DIR").unwrap());
path.push("tests/host-down.xml");
let content = fs::read_to_string(path).unwrap();
NmapResults::parse(&content).unwrap()
};
static ref NMAP_INCOMPLETE_SCAN: NmapResults = {
let mut path = PathBuf::new();
path.push(&std::env::var("CARGO_MANIFEST_DIR").unwrap());
path.push("tests/incomplete_scan.xml");
let content = fs::read_to_string(path).unwrap();
NmapResults::parse(&content).unwrap()
};
}
fn vectors_eq<T: PartialEq>(a: &Vec<T>, b: &Vec<T>) -> bool {
let matching = a.iter().zip(b.iter()).filter(|&(a, b)| a == b).count();
matching == a.len() || matching == b.len()
}
#[test]
fn start_time() {
assert_eq!(NMAP_TEST_XML.scan_start_time, 1588318812);
}
#[test]
fn end_time() {
assert_eq!(NMAP_TEST_XML.scan_end_time, Some(1588318814));
}
#[test]
fn no_end_time() {
assert_eq!(NMAP_INCOMPLETE_SCAN.scan_end_time, None);
}
#[test]
fn host_start_time() {
let host = NMAP_TEST_XML.hosts().next().unwrap();
assert_eq!(host.scan_start_time, Some(1588318812));
}
#[test]
fn host_end_time() {
let host = NMAP_TEST_XML.hosts().next().unwrap();
assert_eq!(host.scan_end_time, Some(1588318814));
}
#[test]
fn host_ip_address() {
let ip: std::net::IpAddr = "45.33.32.156".parse().unwrap();
let host = NMAP_TEST_XML.hosts().next().unwrap();
assert!(host.addresses().len() == 1);
let ip_addr = host.addresses().next().unwrap();
match ip_addr {
host::Address::IpAddr(s) => assert_eq!(s, &ip),
host::Address::MacAddr(_) => assert!(false),
}
}
#[test]
fn host_status() {
let host = NMAP_TEST_XML.hosts().next().unwrap();
assert_eq!(host.status.reason, "echo-reply");
assert_eq!(host.status.reason_ttl, 53);
assert_eq!(host.status.state, host::HostState::Up);
}
#[test]
fn host_hostnames() {
let host = NMAP_TEST_XML.hosts().next().unwrap();
let mut expected = Vec::new();
let h1 = host::Hostname {
name: "scanme.nmap.org".to_string(),
source: host::HostnameType::User,
};
let h2 = host::Hostname {
name: "scanme.nmap.org".to_string(),
source: host::HostnameType::Dns,
};
expected.push(&h1);
expected.push(&h2);
assert!(!(host.host_names().count() == 0));
assert!(vectors_eq(&host.host_names().collect(), &expected));
}
#[test]
fn host_portinfo_ports() {
let host = NMAP_TEST_XML.hosts().next().unwrap();
let mut expected = Vec::new();
let p1 = port::Port {
protocol: port::PortProtocol::Tcp,
port_number: 22,
status: port::PortStatus {
state: port::PortState::Open,
reason: "syn-ack".to_string(),
reason_ttl: 53,
},
service_info: Some(port::ServiceInfo {
name: "ssh".to_string(),
method: port::ServiceMethod::Table,
confidence_level: 3,
}),
};
let p2 = port::Port {
protocol: port::PortProtocol::Tcp,
port_number: 80,
status: port::PortStatus {
state: port::PortState::Open,
reason: "syn-ack".to_string(),
reason_ttl: 52,
},
service_info: Some(port::ServiceInfo {
name: "http".to_string(),
method: port::ServiceMethod::Table,
confidence_level: 3,
}),
};
let p3 = port::Port {
protocol: port::PortProtocol::Tcp,
port_number: 9929,
status: port::PortStatus {
state: port::PortState::Open,
reason: "syn-ack".to_string(),
reason_ttl: 53,
},
service_info: Some(port::ServiceInfo {
name: "nping-echo".to_string(),
method: port::ServiceMethod::Table,
confidence_level: 3,
}),
};
let p4 = port::Port {
protocol: port::PortProtocol::Tcp,
port_number: 31337,
status: port::PortStatus {
state: port::PortState::Open,
reason: "syn-ack".to_string(),
reason_ttl: 52,
},
service_info: Some(port::ServiceInfo {
name: "Elite".to_string(),
method: port::ServiceMethod::Table,
confidence_level: 3,
}),
};
expected.push(&p1);
expected.push(&p2);
expected.push(&p3);
expected.push(&p4);
assert!(!(host.port_info.ports().count() == 0));
assert!(vectors_eq(&host.port_info.ports().collect(), &expected));
}
#[test]
fn test_issue_one() {
let ip: std::net::IpAddr = "192.168.59.138".parse().unwrap();
let mac = "00:0C:29:71:23:2B".to_string();
let host = NMAP_ISSUE_ONE.hosts().next().unwrap();
assert!(host.addresses().count() == 2);
let mut addresses = host.addresses();
let ip_addr = addresses.next().unwrap();
println!("{:?}", ip_addr);
match ip_addr {
host::Address::IpAddr(s) => assert_eq!(s, &ip),
host::Address::MacAddr(_) => assert!(false),
}
let mac_addr = addresses.next().unwrap();
println!("{:?}", mac_addr);
match mac_addr {
host::Address::IpAddr(_) => assert!(false),
host::Address::MacAddr(s) => assert_eq!(s, &mac),
}
}
#[test]
fn test_iter_ports() {
let mut v = Vec::new();
for (_, port) in NMAP_TEST_XML.iter_ports() {
v.push(port.port_number);
}
let expected = vec![22, 80, 9929, 31337];
assert!(vectors_eq(&v, &expected));
}
#[test]
fn test_host_down() {
use host::HostState;
eprintln!("{:?}", *NMAP_HOST_DOWN);
for host in NMAP_HOST_DOWN.hosts() {
assert_eq!(host.status.state, HostState::Down);
}
}