|
34 | 34 | import static org.junit.jupiter.params.provider.Arguments.arguments; |
35 | 35 | import static software.amazon.awssdk.services.s3.internal.multipart.utils.MultipartDownloadTestUtils.internalErrorBody; |
36 | 36 | import static software.amazon.awssdk.services.s3.internal.multipart.utils.MultipartDownloadTestUtils.transformersSuppliers; |
| 37 | +import static software.amazon.awssdk.services.s3.multipart.S3MultipartExecutionAttribute.MULTIPART_DOWNLOAD_RESUME_CONTEXT; |
37 | 38 |
|
38 | 39 | import com.github.tomakehurst.wiremock.http.Fault; |
39 | 40 | import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; |
|
58 | 59 | import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; |
59 | 60 | import software.amazon.awssdk.core.SplittingTransformerConfiguration; |
60 | 61 | import software.amazon.awssdk.core.async.AsyncResponseTransformer; |
| 62 | +import software.amazon.awssdk.core.exception.SdkClientException; |
61 | 63 | import software.amazon.awssdk.core.internal.async.ByteArrayAsyncResponseTransformer; |
62 | 64 | import software.amazon.awssdk.core.internal.async.FileAsyncResponseTransformer; |
63 | 65 | import software.amazon.awssdk.core.internal.async.InputStreamResponseTransformer; |
|
67 | 69 | import software.amazon.awssdk.regions.Region; |
68 | 70 | import software.amazon.awssdk.services.s3.S3AsyncClient; |
69 | 71 | import software.amazon.awssdk.services.s3.internal.multipart.utils.MultipartDownloadTestUtils; |
| 72 | +import software.amazon.awssdk.services.s3.model.GetObjectRequest; |
70 | 73 | import software.amazon.awssdk.services.s3.model.GetObjectResponse; |
71 | 74 | import software.amazon.awssdk.services.s3.model.S3Exception; |
72 | 75 | import software.amazon.awssdk.services.s3.utils.AsyncResponseTransformerTestSupplier; |
@@ -144,6 +147,47 @@ public <T> void errorOnThirdPart_shouldCompleteExceptionallyOnlyPartsGreaterThan |
144 | 147 | } |
145 | 148 | } |
146 | 149 |
|
| 150 | + @ParameterizedTest |
| 151 | + @MethodSource("partSizeAndTransformerParams") |
| 152 | + public <T> void partCountValidationFailure_shouldThrowException( |
| 153 | + AsyncResponseTransformerTestSupplier<T> supplier, |
| 154 | + int partSize) { |
| 155 | + |
| 156 | + // To trigger the partCount failure, the resumeContext is used to initialize the actualGetCount larger than the |
| 157 | + // totalPart number set in the response. This won't happen in real scenario, just to test if the error can be surfaced |
| 158 | + // to the user if the validation fails. |
| 159 | + MultipartDownloadResumeContext resumeContext = new MultipartDownloadResumeContext(); |
| 160 | + resumeContext.addCompletedPart(1); |
| 161 | + resumeContext.addCompletedPart(2); |
| 162 | + resumeContext.addCompletedPart(3); |
| 163 | + resumeContext.addToBytesToLastCompletedParts(3 * partSize); |
| 164 | + |
| 165 | + GetObjectRequest request = GetObjectRequest.builder() |
| 166 | + .bucket(BUCKET) |
| 167 | + .key(KEY) |
| 168 | + .overrideConfiguration(config -> config |
| 169 | + .putExecutionAttribute( |
| 170 | + MULTIPART_DOWNLOAD_RESUME_CONTEXT, |
| 171 | + resumeContext)) |
| 172 | + .build(); |
| 173 | + |
| 174 | + util.stubForPart(BUCKET, KEY, 4, 2, partSize); |
| 175 | + |
| 176 | + // Skip the lazy transformer since the error won't surface unless the content is consumed |
| 177 | + AsyncResponseTransformer<GetObjectResponse, T> transformer = supplier.transformer(); |
| 178 | + if (transformer instanceof InputStreamResponseTransformer || transformer instanceof PublisherAsyncResponseTransformer) { |
| 179 | + return; |
| 180 | + } |
| 181 | + |
| 182 | + assertThatThrownBy(() -> { |
| 183 | + T res = multipartClient.getObject(request, transformer).join(); |
| 184 | + supplier.body(res); |
| 185 | + }).isInstanceOf(CompletionException.class) |
| 186 | + .hasCauseInstanceOf(SdkClientException.class) |
| 187 | + .hasMessageContaining("PartsCount validation failed. Expected 2, downloaded 4 parts"); |
| 188 | + |
| 189 | + } |
| 190 | + |
147 | 191 | @ParameterizedTest |
148 | 192 | @MethodSource("nonRetryableResponseTransformers") |
149 | 193 | public <T> void errorOnFirstPart_shouldFail(AsyncResponseTransformerTestSupplier<T> supplier) { |
|
0 commit comments