fn calculate_jump_host_timeout(hop_count: usize) -> u64 {
const BASE_TIMEOUT: u64 = 30;
const PER_HOP_TIMEOUT: u64 = 15;
const MAX_TIMEOUT_SECS: u64 = 600;
BASE_TIMEOUT
.saturating_add(PER_HOP_TIMEOUT.saturating_mul(hop_count as u64))
.min(MAX_TIMEOUT_SECS)
}
#[test]
fn test_timeout_calculation_no_hops() {
let timeout = calculate_jump_host_timeout(0);
assert_eq!(
timeout, 30,
"Direct connection should use 30 second timeout"
);
}
#[test]
fn test_timeout_calculation_single_hop() {
let timeout = calculate_jump_host_timeout(1);
assert_eq!(timeout, 45, "Single hop should be 45 seconds");
}
#[test]
fn test_timeout_calculation_multiple_hops() {
assert_eq!(calculate_jump_host_timeout(2), 60); assert_eq!(calculate_jump_host_timeout(3), 75); assert_eq!(calculate_jump_host_timeout(5), 105); assert_eq!(calculate_jump_host_timeout(10), 180); }
#[test]
fn test_timeout_calculation_max_allowed_hops() {
let timeout = calculate_jump_host_timeout(10);
assert_eq!(timeout, 180); assert!(
timeout <= 600,
"Timeout should never exceed 600 seconds, got {timeout}"
);
}
#[test]
fn test_timeout_calculation_cap_at_600() {
let timeout_38_hops = calculate_jump_host_timeout(38);
assert_eq!(timeout_38_hops, 600, "38 hops should hit max timeout");
let timeout_39_hops = calculate_jump_host_timeout(39);
assert_eq!(
timeout_39_hops, 600,
"39 hops should be capped at max timeout"
);
let timeout_100_hops = calculate_jump_host_timeout(100);
assert_eq!(
timeout_100_hops, 600,
"100 hops should be capped at max timeout"
);
}
#[test]
fn test_timeout_calculation_prevents_integer_overflow() {
let timeout = calculate_jump_host_timeout(usize::MAX);
assert_eq!(
timeout, 600,
"Extreme hop count should be capped at max timeout, not overflow"
);
let timeout = calculate_jump_host_timeout(1_000_000);
assert_eq!(timeout, 600, "Very large hop count should be capped");
let timeout = calculate_jump_host_timeout(u64::MAX as usize);
assert_eq!(timeout, 600, "u64::MAX hop count should be capped");
}
#[test]
fn test_timeout_calculation_boundary_conditions() {
assert_eq!(calculate_jump_host_timeout(37), 585); assert_eq!(calculate_jump_host_timeout(38), 600);
assert_eq!(calculate_jump_host_timeout(39), 600); assert_eq!(calculate_jump_host_timeout(40), 600); }
#[test]
fn test_timeout_calculation_consistency() {
let mut prev_timeout = 0;
for hop_count in 0..=50 {
let timeout = calculate_jump_host_timeout(hop_count);
assert!(
timeout >= prev_timeout,
"Timeout should be monotonic: hop_count={hop_count}, timeout={timeout}, prev={prev_timeout}"
);
assert!(
timeout <= 600,
"Timeout should never exceed 600: hop_count={hop_count}, timeout={timeout}"
);
prev_timeout = timeout;
}
assert_eq!(prev_timeout, 600, "Should reach and maintain max timeout");
}
#[test]
fn test_timeout_calculation_realistic_scenarios() {
assert_eq!(calculate_jump_host_timeout(1), 45);
assert_eq!(calculate_jump_host_timeout(2), 60);
assert_eq!(calculate_jump_host_timeout(3), 75);
let max_allowed_timeout = calculate_jump_host_timeout(10);
assert!(
max_allowed_timeout <= 600,
"Even max allowed hops should be reasonable"
);
assert_eq!(max_allowed_timeout, 180); }
#[test]
fn test_timeout_formula_correctness() {
for hop_count in 0..=100 {
let timeout = calculate_jump_host_timeout(hop_count);
let expected_uncapped = 30 + (15 * hop_count as u64);
let expected = expected_uncapped.min(600);
assert_eq!(
timeout, expected,
"Formula mismatch at hop_count={hop_count}: got {timeout}, expected {expected}"
);
}
}