mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-08 04:58:12 +00:00
test(odm): pin gcs error classes and require the backend contracts in ci (#7250)
* test(odm): pin gcs source status-to-error-class mapping The native GCS backend classifies every failure from the HTTP status alone, because GCS states its error code in a body this backend never reads. Only NotFound is negative-cached and only a retryable class may be re-sent, so cover 401/403 -> AccessDenied, 429/503 -> Throttled, 500/502 -> ServerError and 404 -> NotFound over both HEAD and GET. * ci(odm): require the source-backend contract tests in test-and-lint The shared contract tests already run in ci/test-and-lint, but only because gcs is a rustfs default feature; nothing failed if that selection went away. Pin the S3, Azure and native GCS contracts in the core required-test manifest so a lost selection fails the lane.
This commit is contained in:
@@ -561,4 +561,41 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// GCS states its error code in the response body, which this backend never
|
||||
/// reads, so every class must follow from the status alone. The classes are
|
||||
/// what the runtime acts on: only `NotFound` is negative-cached, and only a
|
||||
/// retryable class may be re-sent rather than counted against the breaker.
|
||||
/// The 404 row scripts the readable-bucket probe as well, because a GCS
|
||||
/// object 404 is only a key miss once the bucket has answered
|
||||
/// (`object_404_requires_a_readable_source_bucket` pins that rule).
|
||||
#[tokio::test]
|
||||
async fn gcs_statuses_map_onto_the_shared_error_classes() {
|
||||
for method in [Method::HEAD, Method::GET] {
|
||||
for (status, expected, retryable) in [
|
||||
(404_u16, "not_found", false),
|
||||
(403, "access_denied", false),
|
||||
(401, "access_denied", false),
|
||||
(429, "throttled", true),
|
||||
(503, "throttled", true),
|
||||
(500, "server_error", true),
|
||||
(502, "server_error", true),
|
||||
] {
|
||||
let mut script = vec![ScriptedResponse::new(status, Vec::new(), String::new())];
|
||||
if status == 404 {
|
||||
script.push(ScriptedResponse::new(200, Vec::new(), "{}".to_string()));
|
||||
}
|
||||
let (endpoint, _) = scripted_server(script).await;
|
||||
let backend = backend(&endpoint);
|
||||
let result = if method == Method::HEAD {
|
||||
backend.head("a.txt").await.map(|_| ())
|
||||
} else {
|
||||
backend.get("a.txt", None).await.map(|_| ())
|
||||
};
|
||||
let err = result.expect_err("a non-2xx status must fail");
|
||||
assert_eq!(err.class_label(), expected, "{method} HTTP {status}: {err:?}");
|
||||
assert_eq!(err.is_retryable(), retryable, "{method} HTTP {status}: {err:?}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user