diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/stream/AwsChunkedStream.h b/src/aws-cpp-sdk-core/include/aws/core/utils/stream/AwsChunkedStream.h index fbbf85248a9..af12d2572fa 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/stream/AwsChunkedStream.h +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/stream/AwsChunkedStream.h @@ -77,7 +77,7 @@ class AwsChunkedStream { m_request->GetRequestHash().second->Update(reinterpret_cast(m_data.GetUnderlyingData()), bytesRead); } - if (m_chunkingStream != nullptr && !m_chunkingStream->bad()) { + if (bytesRead > 0 && m_chunkingStream != nullptr && !m_chunkingStream->bad()) { if (m_chunkingStream->eof()) { m_chunkingStream->clear(); } diff --git a/tests/aws-cpp-sdk-core-tests/utils/stream/AwsChunkedStreamTest.cpp b/tests/aws-cpp-sdk-core-tests/utils/stream/AwsChunkedStreamTest.cpp index ee43ab90734..6af1db4e5ee 100644 --- a/tests/aws-cpp-sdk-core-tests/utils/stream/AwsChunkedStreamTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/utils/stream/AwsChunkedStreamTest.cpp @@ -81,4 +81,20 @@ TEST_F(AwsChunkedStreamTest, ShouldWorkOnSmallBuffer) { // Any subsequent reads will return 0 because all streams are exhausted amountRead = chunkedStream.BufferedRead(outputBuffer.GetUnderlyingData(), 100); EXPECT_EQ(0ul, amountRead); +} + +TEST_F(AwsChunkedStreamTest, ShouldWorkOnEmptyStream) { + StandardHttpRequest request{"www.nidia.com/juna", Http::HttpMethod::HTTP_GET}; + auto requestHash = Aws::MakeShared(TEST_LOG_TAG); + request.SetRequestHash("crc32", requestHash); + std::shared_ptr inputStream = Aws::MakeShared(TEST_LOG_TAG, ""); + AwsChunkedStream<5> chunkedStream{&request, inputStream}; + Aws::Utils::Array outputBuffer{100}; + // Read first 5 bytes, we get back ten bytes chunk encoded since it is "5\r\n12345\r\n" + Aws::StringStream firstRead; + auto amountRead = chunkedStream.BufferedRead(outputBuffer.GetUnderlyingData(), 100); + std::copy(outputBuffer.GetUnderlyingData(), outputBuffer.GetUnderlyingData() + amountRead, std::ostream_iterator(firstRead)); + EXPECT_EQ(36ul, amountRead); + auto encodedStr = firstRead.str(); + EXPECT_EQ("0\r\nx-amz-checksum-crc32:AAAAAA==\r\n\r\n", encodedStr); } \ No newline at end of file diff --git a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp index aca61e316c5..9f1c56490ec 100644 --- a/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-crt-integration-tests/BucketAndObjectOperationTest.cpp @@ -1311,6 +1311,28 @@ namespace ASSERT_TRUE(isErrorEventReceived); } + TEST_F(BucketAndObjectOperationTest, TestNullBody) + { + const Aws::String fullBucketName = CalculateBucketName(BASE_PUT_OBJECTS_BUCKET_NAME.c_str()); + SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); + CreateBucketRequest createBucketRequest; + createBucketRequest.SetBucket(fullBucketName); + createBucketRequest.SetACL(BucketCannedACL::private_); + + CreateBucketOutcome createBucketOutcome = Client->CreateBucket(createBucketRequest); + AWS_ASSERT_SUCCESS(createBucketOutcome); + const CreateBucketResult& createBucketResult = createBucketOutcome.GetResult(); + ASSERT_TRUE(!createBucketResult.GetLocation().empty()); + ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName)); + TagTestBucket(fullBucketName, Client); + + PutObjectRequest putObjectRequest; + putObjectRequest.SetBucket(fullBucketName); + putObjectRequest.SetKey("sbiscigl_was_here_null"); + PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); + AWS_ASSERT_SUCCESS(putObjectOutcome); + } + TEST_F(BucketAndObjectOperationTest, TestEmptyBody) { const Aws::String fullBucketName = CalculateBucketName(BASE_PUT_OBJECTS_BUCKET_NAME.c_str()); @@ -1328,7 +1350,8 @@ namespace PutObjectRequest putObjectRequest; putObjectRequest.SetBucket(fullBucketName); - putObjectRequest.SetKey("sbiscigl_was_here"); + putObjectRequest.SetKey("sbiscigl_was_here_empty"); + putObjectRequest.SetBody(Aws::MakeShared(ALLOCATION_TAG, "")); PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); AWS_ASSERT_SUCCESS(putObjectOutcome); } diff --git a/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp b/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp index 23800ccd204..c4675b441f3 100644 --- a/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp +++ b/tests/aws-cpp-sdk-s3-integration-tests/BucketAndObjectOperationTest.cpp @@ -2387,6 +2387,28 @@ namespace } } + TEST_F(BucketAndObjectOperationTest, TestNullBody) { + const Aws::String fullBucketName = CalculateBucketName(BASE_PUT_OBJECTS_BUCKET_NAME.c_str()); + SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); + + CreateBucketRequest createBucketRequest; + createBucketRequest.SetBucket(fullBucketName); + createBucketRequest.SetACL(BucketCannedACL::private_); + + CreateBucketOutcome createBucketOutcome = CreateBucket(createBucketRequest); + AWS_ASSERT_SUCCESS(createBucketOutcome); + const CreateBucketResult& createBucketResult = createBucketOutcome.GetResult(); + ASSERT_TRUE(!createBucketResult.GetLocation().empty()); + ASSERT_TRUE(WaitForBucketToPropagate(fullBucketName, Client)); + TagTestBucket(fullBucketName, Client); + + PutObjectRequest putObjectRequest; + putObjectRequest.SetBucket(fullBucketName); + putObjectRequest.SetKey("sbiscigl_was_here_null"); + PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); + AWS_ASSERT_SUCCESS(putObjectOutcome); + } + TEST_F(BucketAndObjectOperationTest, TestEmptyBody) { const Aws::String fullBucketName = CalculateBucketName(BASE_PUT_OBJECTS_BUCKET_NAME.c_str()); SCOPED_TRACE(Aws::String("FullBucketName ") + fullBucketName); @@ -2404,7 +2426,8 @@ namespace PutObjectRequest putObjectRequest; putObjectRequest.SetBucket(fullBucketName); - putObjectRequest.SetKey("sbiscigl_was_here"); + putObjectRequest.SetKey("sbiscigl_was_here_empty"); + putObjectRequest.SetBody(Aws::MakeShared(ALLOCATION_TAG, "")); PutObjectOutcome putObjectOutcome = Client->PutObject(putObjectRequest); AWS_ASSERT_SUCCESS(putObjectOutcome); }