provisioning-platform/crates/ontoref-compute/tests/unit_retry.rs

121 lines
3.3 KiB
Rust
Raw Permalink Normal View History

//! 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);
}