use std::io::ErrorKind;
use aws_sdk_s3::config::http::HttpResponse;
use aws_sdk_s3::error::{ErrorMetadata, SdkError};
use aws_sdk_s3::operation::get_object::GetObjectError;
use aws_smithy_types::body::SdkBody;
fn service_error(status: u16, code: &str) -> SdkError<GetObjectError, HttpResponse> {
let err = GetObjectError::generic(ErrorMetadata::builder().code(code).message("made by the test").build());
let raw = HttpResponse::new(status.try_into().unwrap(), SdkBody::empty());
SdkError::service_error(err, raw)
}
#[test]
fn a_code_has_the_kind_of_its_status() {
let pairs = [
(403, "AccessDenied"), (403, "InvalidAccessKeyId"), (403, "SignatureDoesNotMatch"),
(404, "NoSuchKey"), (404, "NoSuchBucket"),
(409, "OperationAborted"), (412, "PreconditionFailed"), (409, "ConditionalRequestConflict"),
(503, "SlowDown"), (500, "InternalError"), (503, "ServiceUnavailable"),
(400, "RequestTimeout"), (400, "InvalidArgument"), (400, "MalformedXML"), (501, "NotImplemented"),
];
for (status, code) in pairs {
let by_status = hyperfile::s3_error_kind(&service_error(status, code));
let by_code = hyperfile::s3_code_kind(Some(code));
if code == "RequestTimeout" {
assert_eq!(by_code, ErrorKind::TimedOut);
continue;
}
assert_eq!(by_code, by_status, "{} {}: by code {:?}, by status {:?}", status, code, by_code, by_status);
}
assert_eq!(hyperfile::s3_code_kind(Some("SomethingNew")), ErrorKind::Other);
assert_eq!(hyperfile::s3_code_kind(None), ErrorKind::Other);
}
#[test]
fn a_refused_condition_is_told_by_its_code() {
assert!(hyperfile::is_condition_failure(&service_error(412, "PreconditionFailed")));
assert!(hyperfile::is_condition_failure(&service_error(200, "PreconditionFailed")));
assert_eq!(hyperfile::s3_error_kind(&service_error(200, "PreconditionFailed")), ErrorKind::AlreadyExists);
assert!(!hyperfile::is_condition_failure(&service_error(503, "SlowDown")));
}
#[test]
fn errors_without_a_response() {
let timeout: SdkError<GetObjectError, HttpResponse> = SdkError::timeout_error("made by the test");
assert_eq!(hyperfile::s3_error_kind(&timeout), ErrorKind::TimedOut);
let unbuilt: SdkError<GetObjectError, HttpResponse> = SdkError::construction_failure("made by the test");
assert_eq!(hyperfile::s3_error_kind(&unbuilt), ErrorKind::InvalidInput);
}
#[test]
fn which_kinds_are_retryable() {
for k in [ErrorKind::ConnectionReset, ErrorKind::TimedOut, ErrorKind::ResourceBusy] {
assert!(hyperfile::is_retryable(k), "{:?}", k);
}
for k in [ErrorKind::AlreadyExists, ErrorKind::NotFound, ErrorKind::PermissionDenied,
ErrorKind::InvalidInput, ErrorKind::InvalidData, ErrorKind::Unsupported,
ErrorKind::StaleNetworkFileHandle, ErrorKind::Other, ErrorKind::Interrupted] {
assert!(!hyperfile::is_retryable(k), "{:?}", k);
}
for status in [429, 500, 502, 503, 504] {
assert!(hyperfile::is_retryable(hyperfile::s3_error_kind(&service_error(status, "Busy"))), "{}", status);
}
}