v0.2.5-pre.009
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-onchain-transport-lib/unit_tests/resilience.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
fn non_zero(value: u32) -> std::num::NonZeroU32 {
|
||||
return std::num::NonZeroU32::new(value).expect("test limit must be non-zero");
|
||||
@@ -46,46 +46,46 @@ fn retry_backoff_is_exponential_and_bounded() {
|
||||
#[test]
|
||||
fn retry_safe_timeout_is_retried_until_budget_is_exhausted() {
|
||||
let settings = retry_settings();
|
||||
let first = super::evaluate_transport_retry(
|
||||
let first = crate::evaluate_transport_retry(
|
||||
method("getBalance"),
|
||||
&settings,
|
||||
super::HttpRetryCause::Timeout,
|
||||
super::HttpDispatchState::DispatchedAmbiguous,
|
||||
crate::HttpRetryCause::Timeout,
|
||||
crate::HttpDispatchState::DispatchedAmbiguous,
|
||||
0,
|
||||
std::option::Option::None,
|
||||
);
|
||||
assert_eq!(first, super::HttpRetryDecision::RetryAfter(std::time::Duration::from_millis(100)));
|
||||
let exhausted = super::evaluate_transport_retry(
|
||||
assert_eq!(first, crate::HttpRetryDecision::RetryAfter(std::time::Duration::from_millis(100)));
|
||||
let exhausted = crate::evaluate_transport_retry(
|
||||
method("getBalance"),
|
||||
&settings,
|
||||
super::HttpRetryCause::Timeout,
|
||||
super::HttpDispatchState::DispatchedAmbiguous,
|
||||
crate::HttpRetryCause::Timeout,
|
||||
crate::HttpDispatchState::DispatchedAmbiguous,
|
||||
settings.max_retries(),
|
||||
std::option::Option::None,
|
||||
);
|
||||
assert_eq!(exhausted, super::HttpRetryDecision::Stop);
|
||||
assert_eq!(exhausted, crate::HttpRetryDecision::Stop);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_submission_never_retries_after_ambiguous_dispatch() {
|
||||
let decision = super::evaluate_transport_retry(
|
||||
let decision = crate::evaluate_transport_retry(
|
||||
method("sendTransaction"),
|
||||
&retry_settings(),
|
||||
super::HttpRetryCause::Connection,
|
||||
super::HttpDispatchState::DispatchedAmbiguous,
|
||||
crate::HttpRetryCause::Connection,
|
||||
crate::HttpDispatchState::DispatchedAmbiguous,
|
||||
0,
|
||||
std::option::Option::None,
|
||||
);
|
||||
assert_eq!(decision, super::HttpRetryDecision::Stop);
|
||||
assert_eq!(decision, crate::HttpRetryDecision::Stop);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_submission_can_retry_when_transport_proves_no_dispatch() {
|
||||
let decision = super::evaluate_transport_retry(
|
||||
let decision = crate::evaluate_transport_retry(
|
||||
method("sendTransaction"),
|
||||
&retry_settings(),
|
||||
super::HttpRetryCause::Connection,
|
||||
super::HttpDispatchState::NotDispatched,
|
||||
crate::HttpRetryCause::Connection,
|
||||
crate::HttpDispatchState::NotDispatched,
|
||||
0,
|
||||
std::option::Option::None,
|
||||
);
|
||||
@@ -94,36 +94,36 @@ fn write_submission_can_retry_when_transport_proves_no_dispatch() {
|
||||
|
||||
#[test]
|
||||
fn rpc_application_and_invalid_response_are_not_transport_retries() {
|
||||
for cause in [super::HttpRetryCause::RpcApplication, super::HttpRetryCause::InvalidResponse, super::HttpRetryCause::Request] {
|
||||
let decision = super::evaluate_transport_retry(
|
||||
for cause in [crate::HttpRetryCause::RpcApplication, crate::HttpRetryCause::InvalidResponse, crate::HttpRetryCause::Request] {
|
||||
let decision = crate::evaluate_transport_retry(
|
||||
method("getBalance"),
|
||||
&retry_settings(),
|
||||
cause,
|
||||
super::HttpDispatchState::NotDispatched,
|
||||
crate::HttpDispatchState::NotDispatched,
|
||||
0,
|
||||
std::option::Option::None,
|
||||
);
|
||||
assert_eq!(decision, super::HttpRetryDecision::Stop);
|
||||
assert_eq!(decision, crate::HttpRetryDecision::Stop);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_retry_after_can_extend_backoff_but_is_defensively_bounded() {
|
||||
let settings = retry_settings();
|
||||
let extended = super::evaluate_transport_retry(
|
||||
let extended = crate::evaluate_transport_retry(
|
||||
method("getBalance"),
|
||||
&settings,
|
||||
super::HttpRetryCause::RateLimited,
|
||||
super::HttpDispatchState::DispatchedAmbiguous,
|
||||
crate::HttpRetryCause::RateLimited,
|
||||
crate::HttpDispatchState::DispatchedAmbiguous,
|
||||
0,
|
||||
std::option::Option::Some(std::time::Duration::from_secs(3)),
|
||||
);
|
||||
assert_eq!(extended.delay(), std::option::Option::Some(std::time::Duration::from_secs(3)));
|
||||
let bounded = super::evaluate_transport_retry(
|
||||
let bounded = crate::evaluate_transport_retry(
|
||||
method("getBalance"),
|
||||
&settings,
|
||||
super::HttpRetryCause::RateLimited,
|
||||
super::HttpDispatchState::DispatchedAmbiguous,
|
||||
crate::HttpRetryCause::RateLimited,
|
||||
crate::HttpDispatchState::DispatchedAmbiguous,
|
||||
0,
|
||||
std::option::Option::Some(std::time::Duration::from_secs(600)),
|
||||
);
|
||||
@@ -144,29 +144,29 @@ fn token_bucket_consumes_burst_then_refills_from_elapsed_time() {
|
||||
#[test]
|
||||
fn absent_burst_capacity_defaults_to_one_second_of_rps_capacity() {
|
||||
let role = role_limits(std::option::Option::Some(2), std::option::Option::None, std::option::Option::None, std::option::Option::None);
|
||||
let runtime = std::sync::Arc::new(super::HttpRoleRuntime::new(&role, std::sync::Arc::new(tokio::sync::Notify::new())));
|
||||
let runtime = std::sync::Arc::new(crate::HttpRoleRuntime::new(&role, std::sync::Arc::new(tokio::sync::Notify::new())));
|
||||
let now = std::time::Instant::now();
|
||||
let first = runtime.try_acquire(now);
|
||||
let second = runtime.try_acquire(now);
|
||||
let third = runtime.try_acquire(now);
|
||||
assert!(matches!(first, super::RoleAdmissionAttempt::Ready(_)));
|
||||
assert!(matches!(second, super::RoleAdmissionAttempt::Ready(_)));
|
||||
assert!(matches!(third, super::RoleAdmissionAttempt::BlockedUntil(_)));
|
||||
assert!(matches!(first, crate::RoleAdmissionAttempt::Ready(_)));
|
||||
assert!(matches!(second, crate::RoleAdmissionAttempt::Ready(_)));
|
||||
assert!(matches!(third, crate::RoleAdmissionAttempt::BlockedUntil(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn concurrency_semaphore_releases_capacity_when_permit_is_dropped() {
|
||||
let role = role_limits(std::option::Option::None, std::option::Option::None, std::option::Option::Some(1), std::option::Option::None);
|
||||
let runtime = std::sync::Arc::new(super::HttpRoleRuntime::new(&role, std::sync::Arc::new(tokio::sync::Notify::new())));
|
||||
let runtime = std::sync::Arc::new(crate::HttpRoleRuntime::new(&role, std::sync::Arc::new(tokio::sync::Notify::new())));
|
||||
let now = std::time::Instant::now();
|
||||
let first = runtime.try_acquire(now);
|
||||
let held = match first {
|
||||
super::RoleAdmissionAttempt::Ready(permit) => permit,
|
||||
crate::RoleAdmissionAttempt::Ready(permit) => permit,
|
||||
_ => panic!("first concurrency permit must be available"),
|
||||
};
|
||||
assert!(matches!(runtime.try_acquire(now), super::RoleAdmissionAttempt::ConcurrencySaturated));
|
||||
assert!(matches!(runtime.try_acquire(now), crate::RoleAdmissionAttempt::ConcurrencySaturated));
|
||||
drop(held);
|
||||
assert!(matches!(runtime.try_acquire(now), super::RoleAdmissionAttempt::Ready(_)));
|
||||
assert!(matches!(runtime.try_acquire(now), crate::RoleAdmissionAttempt::Ready(_)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -177,7 +177,7 @@ fn rate_limit_cooldown_marks_role_and_caps_provider_delay() {
|
||||
std::option::Option::None,
|
||||
std::option::Option::Some(std::time::Duration::from_millis(10)),
|
||||
);
|
||||
let runtime = super::HttpRoleRuntime::new(&role, std::sync::Arc::new(tokio::sync::Notify::new()));
|
||||
let runtime = crate::HttpRoleRuntime::new(&role, std::sync::Arc::new(tokio::sync::Notify::new()));
|
||||
let pause = runtime.record_rate_limited(std::option::Option::Some(std::time::Duration::from_secs(600)));
|
||||
assert_eq!(pause, std::time::Duration::from_secs(60));
|
||||
assert_eq!(runtime.rate_limit_count(), 1);
|
||||
|
||||
Reference in New Issue
Block a user