#![allow(clippy::assertions_on_constants)]
use std::sync::Mutex;
use cellos_export_http::{
resolve_timeout_ms, HttpExportSink, DEFAULT_CONNECT_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS,
ENV_CONNECT_TIMEOUT_MS, ENV_REQUEST_TIMEOUT_MS,
};
static ENV_LOCK: Mutex<()> = Mutex::new(());
fn lock() -> std::sync::MutexGuard<'static, ()> {
ENV_LOCK.lock().unwrap_or_else(|e| e.into_inner())
}
#[test]
fn defaults_are_bounded_and_sane() {
assert!(
DEFAULT_REQUEST_TIMEOUT_MS > 0,
"default request timeout must be > 0, got {DEFAULT_REQUEST_TIMEOUT_MS}"
);
assert!(
DEFAULT_REQUEST_TIMEOUT_MS <= 5 * 60 * 1000,
"default request timeout must be <= 5min, got {DEFAULT_REQUEST_TIMEOUT_MS}ms"
);
assert!(
DEFAULT_CONNECT_TIMEOUT_MS > 0,
"default connect timeout must be > 0, got {DEFAULT_CONNECT_TIMEOUT_MS}"
);
assert!(
DEFAULT_CONNECT_TIMEOUT_MS <= 60 * 1000,
"default connect timeout must be <= 60s, got {DEFAULT_CONNECT_TIMEOUT_MS}ms"
);
assert!(
DEFAULT_CONNECT_TIMEOUT_MS <= DEFAULT_REQUEST_TIMEOUT_MS,
"connect timeout ({DEFAULT_CONNECT_TIMEOUT_MS}) must not exceed request timeout ({DEFAULT_REQUEST_TIMEOUT_MS})"
);
}
#[test]
fn unset_env_var_falls_back_to_default() {
let _g = lock();
std::env::remove_var(ENV_REQUEST_TIMEOUT_MS);
std::env::remove_var(ENV_CONNECT_TIMEOUT_MS);
assert_eq!(
resolve_timeout_ms(ENV_REQUEST_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS),
DEFAULT_REQUEST_TIMEOUT_MS
);
assert_eq!(
resolve_timeout_ms(ENV_CONNECT_TIMEOUT_MS, DEFAULT_CONNECT_TIMEOUT_MS),
DEFAULT_CONNECT_TIMEOUT_MS
);
}
#[test]
fn valid_override_is_honored() {
let _g = lock();
std::env::set_var(ENV_REQUEST_TIMEOUT_MS, "12345");
let resolved = resolve_timeout_ms(ENV_REQUEST_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS);
std::env::remove_var(ENV_REQUEST_TIMEOUT_MS);
assert_eq!(resolved, 12_345);
}
#[test]
fn zero_override_falls_back_to_default() {
let _g = lock();
std::env::set_var(ENV_REQUEST_TIMEOUT_MS, "0");
let resolved = resolve_timeout_ms(ENV_REQUEST_TIMEOUT_MS, DEFAULT_REQUEST_TIMEOUT_MS);
std::env::remove_var(ENV_REQUEST_TIMEOUT_MS);
assert_eq!(
resolved, DEFAULT_REQUEST_TIMEOUT_MS,
"zero must not disable the timeout; expected fallback to default"
);
}
#[test]
fn garbage_override_falls_back_to_default() {
let _g = lock();
for garbage in [
"",
" ",
"not-a-number",
"-5",
"12.5",
"9999999999999999999999",
] {
std::env::set_var(ENV_CONNECT_TIMEOUT_MS, garbage);
let resolved = resolve_timeout_ms(ENV_CONNECT_TIMEOUT_MS, DEFAULT_CONNECT_TIMEOUT_MS);
std::env::remove_var(ENV_CONNECT_TIMEOUT_MS);
assert_eq!(
resolved, DEFAULT_CONNECT_TIMEOUT_MS,
"garbage env value {garbage:?} must fall back to default"
);
}
}
#[test]
fn sink_constructs_with_default_and_overridden_timeouts() {
let _g = lock();
std::env::remove_var("CELLOS_CA_BUNDLE");
std::env::remove_var(ENV_REQUEST_TIMEOUT_MS);
std::env::remove_var(ENV_CONNECT_TIMEOUT_MS);
let sink = HttpExportSink::new("https://example.invalid/upload", "c1", None, 1, 0);
assert!(
sink.is_ok(),
"sink must construct under default timeout config: {:?}",
sink.err()
);
std::env::set_var(ENV_REQUEST_TIMEOUT_MS, "5000");
std::env::set_var(ENV_CONNECT_TIMEOUT_MS, "1500");
let sink = HttpExportSink::new("https://example.invalid/upload", "c1", None, 1, 0);
std::env::remove_var(ENV_REQUEST_TIMEOUT_MS);
std::env::remove_var(ENV_CONNECT_TIMEOUT_MS);
assert!(
sink.is_ok(),
"sink must construct under overridden timeout config: {:?}",
sink.err()
);
}