120 lines
3.3 KiB
Rust
120 lines
3.3 KiB
Rust
//! Unit tests for the `retry` module.
|
|
|
|
use std::time::Duration;
|
|
|
|
use ontoref_compute::retry::{
|
|
oom_retry_allowed, BackoffPolicy, RetryDecision, RetryPolicy, MAX_OOM_RETRIES,
|
|
};
|
|
use ontoref_compute::sizing::SizeTier;
|
|
use ontoref_compute::{ComputeError, InstanceHandle, ProviderKind};
|
|
|
|
#[test]
|
|
fn max_oom_retries_is_three() {
|
|
assert_eq!(MAX_OOM_RETRIES, 3);
|
|
}
|
|
|
|
#[test]
|
|
fn oom_retry_allowed_boundary() {
|
|
assert!(oom_retry_allowed(0));
|
|
assert!(oom_retry_allowed(1));
|
|
assert!(oom_retry_allowed(2));
|
|
assert!(!oom_retry_allowed(3));
|
|
assert!(!oom_retry_allowed(100));
|
|
}
|
|
|
|
#[test]
|
|
fn backoff_fixed_zero_on_first_attempt() {
|
|
let b = BackoffPolicy::Fixed { ms: 2_000 };
|
|
assert_eq!(b.delay_for(0), Duration::ZERO);
|
|
assert_eq!(b.delay_for(1), Duration::from_millis(2_000));
|
|
assert_eq!(b.delay_for(5), Duration::from_millis(2_000));
|
|
}
|
|
|
|
#[test]
|
|
fn backoff_exponential_caps_at_max() {
|
|
let b = BackoffPolicy::Exponential { base_ms: 100, max_ms: 3_000 };
|
|
assert_eq!(b.delay_for(0), Duration::ZERO);
|
|
for i in 1..=20u32 {
|
|
let d = b.delay_for(i);
|
|
assert!(d <= Duration::from_millis(3_000), "attempt {i}: {d:?} exceeds cap");
|
|
assert!(d >= Duration::from_millis(100), "attempt {i}: {d:?} below base");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn classify_oom_upsize_on_cloud_provider() {
|
|
let policy = RetryPolicy::default();
|
|
let handle = InstanceHandle::new("test-handle");
|
|
let err = ComputeError::OutOfMemory { handle, size_mb: 8_192 };
|
|
|
|
let decision = ontoref_compute::retry::classify(
|
|
&err,
|
|
ProviderKind::Cloud,
|
|
Some(SizeTier::S),
|
|
&policy,
|
|
0, // no retries used yet
|
|
);
|
|
assert_eq!(decision, RetryDecision::RetryUpsize(SizeTier::M));
|
|
}
|
|
|
|
#[test]
|
|
fn classify_oom_gives_up_at_top_tier() {
|
|
let policy = RetryPolicy::default();
|
|
let handle = InstanceHandle::new("top-tier-handle");
|
|
let err = ComputeError::OutOfMemory { handle, size_mb: 32_768 };
|
|
|
|
let decision = ontoref_compute::retry::classify(
|
|
&err,
|
|
ProviderKind::Cloud,
|
|
Some(SizeTier::L), // already at largest
|
|
&policy,
|
|
0,
|
|
);
|
|
assert_eq!(decision, RetryDecision::GiveUp);
|
|
}
|
|
|
|
#[test]
|
|
fn classify_oom_gives_up_on_local_provider() {
|
|
let policy = RetryPolicy::default();
|
|
let handle = InstanceHandle::new("docker-abc");
|
|
let err = ComputeError::OutOfMemory { handle, size_mb: 4_096 };
|
|
|
|
let decision = ontoref_compute::retry::classify(
|
|
&err,
|
|
ProviderKind::Local, // Docker does not support upsize
|
|
Some(SizeTier::S),
|
|
&policy,
|
|
0,
|
|
);
|
|
assert_eq!(decision, RetryDecision::GiveUp);
|
|
}
|
|
|
|
#[test]
|
|
fn classify_provider_unavailable_retries_same() {
|
|
let policy = RetryPolicy::default();
|
|
let err = ComputeError::ProviderUnavailable("connection refused".into());
|
|
|
|
let decision = ontoref_compute::retry::classify(
|
|
&err,
|
|
ProviderKind::Cloud,
|
|
Some(SizeTier::M),
|
|
&policy,
|
|
0,
|
|
);
|
|
assert_eq!(decision, RetryDecision::RetrySame);
|
|
}
|
|
|
|
#[test]
|
|
fn classify_auth_error_gives_up() {
|
|
let policy = RetryPolicy::default();
|
|
let err = ComputeError::Auth("invalid token".into());
|
|
|
|
let decision = ontoref_compute::retry::classify(
|
|
&err,
|
|
ProviderKind::Cloud,
|
|
Some(SizeTier::M),
|
|
&policy,
|
|
0,
|
|
);
|
|
assert_eq!(decision, RetryDecision::GiveUp);
|
|
}
|