Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions generated/src/aws-cpp-sdk-s3/source/S3Errors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ static const int ANNOTATION_NAME_TOO_LONG_HASH = HashingUtils::HashString("Annot
static const int OBJECT_NOT_IN_ACTIVE_TIER_HASH = HashingUtils::HashString("ObjectNotInActiveTierError");
static const int BUCKET_ALREADY_EXISTS_HASH = HashingUtils::HashString("BucketAlreadyExists");
static const int INVALID_OBJECT_STATE_HASH = HashingUtils::HashString("InvalidObjectState");
// Wasabi returns this code for transient storage-service failures.
static const int TEMPORARILY_UNAVAILABLE_HASH = HashingUtils::HashString("TemporarilyUnavailable");

AWSError<CoreErrors> GetErrorForName(const char* errorName) {
int hashCode = HashingUtils::HashString(errorName);
Expand Down Expand Up @@ -85,6 +87,10 @@ AWSError<CoreErrors> GetErrorForName(const char* errorName) {
} else if (hashCode == INVALID_OBJECT_STATE_HASH) {
return AWSError<CoreErrors>(static_cast<CoreErrors>(S3Errors::INVALID_OBJECT_STATE), RetryableType::NOT_RETRYABLE);
}
else if (hashCode == TEMPORARILY_UNAVAILABLE_HASH)
{
return AWSError<CoreErrors>(CoreErrors::SERVICE_UNAVAILABLE, RetryableType::RETRYABLE);
}
return AWSError<CoreErrors>(CoreErrors::UNKNOWN, false);
}

Expand Down
27 changes: 27 additions & 0 deletions tests/aws-cpp-sdk-s3-unit-tests/S3UnitTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <aws/core/auth/AWSCredentials.h>
#include <aws/core/client/RetryStrategy.h>
#include <aws/core/client/DefaultRetryStrategy.h>
#include <aws/core/client/DefaultRetryStrategy.h>
#include <aws/core/utils/DateTime.h>
#include <aws/s3/S3EndpointProvider.h>
#include <aws/core/utils/HashingUtils.h>
Expand Down Expand Up @@ -363,6 +364,32 @@ class MockRequest : public Aws::AmazonWebServiceRequest
};

//Set http error and error in body in a way to hit generic xml error marshaller, which sets the exception name
TEST_F(S3UnitTest, TemporarilyUnavailableIsRetryable) {
auto mockRequest = Aws::MakeShared<Standard::StandardHttpRequest>(
ALLOCATION_TAG, "https://mock.example/bucket/key", HttpMethod::HTTP_PUT);
mockRequest->SetResponseStreamFactory([]() -> IOStream* {
return Aws::New<StringStream>(ALLOCATION_TAG);
});
auto mockResponse = Aws::MakeShared<Standard::StandardHttpResponse>(ALLOCATION_TAG, mockRequest);
mockResponse->GetResponseBody()
<< "<Error><Code>TemporarilyUnavailable</Code>"
"<Message>Storage service is temporarily not available.</Message></Error>";
mockResponse->SetResponseCode(HttpResponseCode::SERVICE_UNAVAILABLE);

const auto error = S3ErrorMarshaller().BuildAWSError(mockResponse);
EXPECT_EQ(CoreErrors::SERVICE_UNAVAILABLE, error.GetErrorType());
EXPECT_EQ("TemporarilyUnavailable", error.GetExceptionName());
EXPECT_TRUE(error.ShouldRetry());
EXPECT_TRUE(DefaultRetryStrategy().ShouldRetry(error, 0));
}

TEST_F(S3UnitTest, UnknownS3ErrorRemainsNonRetryable) {
const auto error = S3ErrorMapper::GetErrorForName("UnknownStorageError");
EXPECT_EQ(CoreErrors::UNKNOWN, error.GetErrorType());
EXPECT_FALSE(error.ShouldRetry());
EXPECT_FALSE(S3ErrorMapper::GetErrorForName("NoSuchKey").ShouldRetry());
}

TEST_F(S3UnitTest, S3EmbeddedErrorTestNonOKResponse) {

auto mockRequest = Aws::MakeShared<Standard::StandardHttpRequest>(ALLOCATION_TAG, "mockuri", HttpMethod::HTTP_GET);
Expand Down