72 lines
3.9 KiB
Rust
72 lines
3.9 KiB
Rust
// file: crates/ksp-offchain-transport-lib/unit_tests/http_admission.rs
|
|
// version: 2
|
|
|
|
#[test]
|
|
fn fixed_admission_smooths_undocumented_burst_and_refills_deterministically() -> ksp_core_lib::Result<()> {
|
|
let policy = match crate::HttpAdmissionPolicy::fixed(2, std::time::Duration::from_secs(1), std::option::Option::None) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let controller = match crate::HttpAdmissionController::new(policy, std::option::Option::None) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let start = std::time::Instant::now();
|
|
assert!(matches!(controller.try_admit_at(start), crate::HttpAdmissionDecision::Ready));
|
|
let deferred = controller.try_admit_at(start);
|
|
let delay = match deferred {
|
|
crate::HttpAdmissionDecision::Deferred(value) => value,
|
|
crate::HttpAdmissionDecision::Ready => {
|
|
return std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_HTTP_RATE_LIMIT_INVALID, "test expected local deferral"));
|
|
},
|
|
};
|
|
assert!(delay > std::time::Duration::ZERO);
|
|
let half_second = match start.checked_add(std::time::Duration::from_millis(500)) {
|
|
std::option::Option::Some(value) => value,
|
|
std::option::Option::None => {
|
|
return std::result::Result::Err(ksp_core_lib::Error::new(crate::ERROR_CODE_HTTP_RATE_LIMIT_INVALID, "test instant overflow"));
|
|
},
|
|
};
|
|
assert!(matches!(controller.try_admit_at(half_second), crate::HttpAdmissionDecision::Ready));
|
|
return std::result::Result::Ok(());
|
|
}
|
|
|
|
#[test]
|
|
fn documented_burst_may_exceed_average_window_budget_and_is_consumed_atomically() -> ksp_core_lib::Result<()> {
|
|
let policy = match crate::HttpAdmissionPolicy::fixed(1, std::time::Duration::from_secs(1), std::option::Option::Some(2)) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let controller = match crate::HttpAdmissionController::new(policy, std::option::Option::None) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let start = std::time::Instant::now();
|
|
assert!(matches!(controller.try_admit_at(start), crate::HttpAdmissionDecision::Ready));
|
|
assert!(matches!(controller.try_admit_at(start), crate::HttpAdmissionDecision::Ready));
|
|
assert!(matches!(controller.try_admit_at(start), crate::HttpAdmissionDecision::Deferred(_)));
|
|
return std::result::Result::Ok(());
|
|
}
|
|
|
|
#[test]
|
|
fn provider_retry_after_extends_but_cannot_pathologically_lock_cooldown() -> ksp_core_lib::Result<()> {
|
|
let controller =
|
|
match crate::HttpAdmissionController::new(crate::HttpAdmissionPolicy::Dynamic, std::option::Option::Some(std::time::Duration::from_secs(2))) {
|
|
std::result::Result::Ok(value) => value,
|
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
|
};
|
|
let applied = controller.record_rate_limited(std::option::Option::Some(std::time::Duration::from_secs(99_999)));
|
|
assert_eq!(applied, crate::HTTP_MAX_RETRY_AFTER);
|
|
let remaining = controller.cooldown_remaining();
|
|
assert!(remaining.is_some());
|
|
assert!(matches!(controller.try_admit(), crate::HttpAdmissionDecision::Deferred(_)));
|
|
return std::result::Result::Ok(());
|
|
}
|
|
|
|
#[test]
|
|
fn admission_policy_rejects_zero_values_and_invalid_fallback() {
|
|
assert!(crate::HttpAdmissionPolicy::fixed(0, std::time::Duration::from_secs(1), std::option::Option::None).is_err());
|
|
assert!(crate::HttpAdmissionPolicy::fixed(1, std::time::Duration::ZERO, std::option::Option::None).is_err());
|
|
assert!(crate::HttpAdmissionPolicy::fixed(1, std::time::Duration::from_secs(1), std::option::Option::Some(0)).is_err());
|
|
}
|