onionwire/tests/hs.rs
Sirius DevOps e902a9041d
All checks were successful
ci / test (push) Successful in 2m59s
fix(hs): probe onion reachability instead of waiting on Bootstrapping
Arti combined status stays Bootstrapping through a 5 min HsDir upload
round. Treat a successful connect as published, floor cbtinitialtimeout
with cbtmintimeout at 20s, and skip preemptive 80/443 circuits so IPT
and HsDir builds are not starved. PUBLISH_WAIT stays 360s fail-closed.
2026-09-10 16:14:10 -04:00

69 lines
2.3 KiB
Rust

//! HS publish wait and CBT floor — 180s fail-closed cuts a working HsDir upload.
use std::time::Duration;
use onionwire::hs;
use tor_hsservice::status::State;
#[test]
fn publish_wait_covers_hsdir_retries() {
assert!(
hs::PUBLISH_WAIT >= Duration::from_secs(360),
"180s cuts a working HsDir publish while status is still Bootstrapping"
);
}
#[test]
fn cbt_min_timeout_floor_is_at_least_10s() {
// Drive the comparison through a runtime value: asserting on the constant
// directly is folded away by the compiler and clippy rejects it under
// -D warnings (clippy::assertions_on_constants).
let floor_ms = hs::CBT_MIN_TIMEOUT_MS;
assert!(floor_ms >= 10_000, "learned CBT ~1s kills HsDir circuits");
}
#[test]
fn cbt_initial_timeout_matches_the_floor() {
// Consensus cbtinitialtimeout can be ~2s; 4-hop vanguard HS circuits
// need the same floor as cbtmintimeout before the estimator has samples.
let initial = hs::CBT_INITIAL_TIMEOUT_MS;
let floor = hs::CBT_MIN_TIMEOUT_MS;
assert!(initial >= floor, "initial CBT below min floor");
assert!(initial >= 10_000, "initial CBT too low for HsDir circuits");
}
#[test]
fn no_preemptive_exit_ports() {
// Default predicted 80/443 circuits compete with IPT + HsDir builds.
// OnionWire never exits; keep the predicted list empty.
assert!(
hs::PREEMPTIVE_PREDICTED_PORTS.is_empty(),
"preemptive exit circuits starve HS publish"
);
}
#[test]
fn arti_status_running_is_ready_without_probe() {
assert!(hs::hs_is_ready(State::Running, false));
assert!(hs::hs_is_ready(State::DegradedReachable, false));
}
#[test]
fn bootstrapping_is_not_ready_until_a_probe_connects() {
// Combined status stays Bootstrapping through Arti's 5 min HsDir upload
// round even after some descriptors are already fetchable.
assert!(!hs::hs_is_ready(State::Bootstrapping, false));
assert!(hs::hs_is_ready(State::Bootstrapping, true));
}
#[test]
fn degraded_unreachable_is_ready_only_if_probe_connects() {
assert!(!hs::hs_is_ready(State::DegradedUnreachable, false));
assert!(hs::hs_is_ready(State::DegradedUnreachable, true));
}
#[test]
fn broken_or_shutdown_never_ready() {
assert!(!hs::hs_is_ready(State::Broken, true));
assert!(!hs::hs_is_ready(State::Shutdown, true));
}