#![allow(clippy::unwrap_used)]
use assert_cmd::Command;
use predicates::prelude::*;
use std::time::{Duration, Instant};
#[test]
fn test_very_low_timeout() {
let mut cmd = Command::cargo_bin("ftr").unwrap();
cmd.args([
"--probe-timeout-ms",
"1",
"--start-ttl",
"1",
"--max-hops",
"5",
"127.0.0.1",
]);
let start = Instant::now();
let output = cmd.output().unwrap();
let duration = start.elapsed();
assert!(
duration < Duration::from_secs(10),
"Command took too long: {:?}",
duration
);
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("*") || stdout.contains("127.0.0.1"));
}
}
#[test]
fn test_high_ttl_value() {
let mut cmd = Command::cargo_bin("ftr").unwrap();
cmd.args([
"--start-ttl",
"64",
"--probe-timeout-ms",
"100",
"--no-enrich",
"127.0.0.1",
]);
let output = cmd.output().unwrap();
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("127.0.0.1"));
}
}
#[test]
fn test_multiple_concurrent_instances() {
let mut handles = vec![];
for i in 0..3 {
let handle = std::thread::spawn(move || {
let mut cmd = Command::cargo_bin("ftr").unwrap();
cmd.args([
"--start-ttl",
"1",
"--probe-timeout-ms",
"100",
"--no-enrich",
"127.0.0.1",
]);
cmd.env("FTR_INSTANCE", i.to_string());
cmd.output()
});
handles.push(handle);
}
for handle in handles {
let result = handle.join().expect("Thread panicked");
assert!(result.is_ok());
}
}
#[test]
fn test_ipv4_address_input() {
let mut cmd = Command::cargo_bin("ftr").unwrap();
cmd.args([
"--start-ttl",
"1",
"--probe-timeout-ms",
"100",
"--no-enrich",
"192.168.1.1",
]);
let output = cmd.output().unwrap();
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(stdout.contains("192.168.1.1"));
}
}
#[test]
fn test_queries_edge_cases() {
let test_cases = vec![
("1", true), ("3", true), ("10", true), ];
for (queries, should_succeed) in test_cases {
let mut cmd = Command::cargo_bin("ftr").unwrap();
cmd.args([
"--queries",
queries,
"--start-ttl",
"1",
"--probe-timeout-ms",
"100",
"127.0.0.1",
]);
let output = cmd.output().unwrap();
if should_succeed {
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(
!stderr.contains("queries"),
"Should not fail due to queries parameter"
);
}
}
}
}
#[test]
fn test_port_boundaries() {
let test_cases = vec![
(1, true), (443, true), (8080, true), (65535, true), ];
for (port, _should_succeed) in test_cases {
let mut cmd = Command::cargo_bin("ftr").unwrap();
cmd.args([
"--protocol",
"udp",
"--port",
&port.to_string(),
"--start-ttl",
"1",
"--probe-timeout-ms",
"100",
"127.0.0.1",
]);
cmd.assert().code(predicate::eq(0).or(predicate::eq(1)));
}
}
#[test]
fn test_silent_hops_minimalist_output() {
let mut cmd = Command::cargo_bin("ftr").unwrap();
cmd.args([
"--start-ttl",
"10",
"--probe-timeout-ms",
"50",
"--no-enrich",
"8.8.8.8",
]);
let output = cmd.output().unwrap();
if output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
let lines: Vec<&str> = stdout.lines().collect();
for line in lines {
if line.trim_start().starts_with(char::is_numeric) {
assert!(!line.contains("[UNKNOWN]"), "Should not contain [UNKNOWN]");
}
}
}
}