2121import static com .github .tomakehurst .wiremock .client .WireMock .urlEqualTo ;
2222import static com .github .tomakehurst .wiremock .core .WireMockConfiguration .wireMockConfig ;
2323import static org .assertj .core .api .Assertions .assertThat ;
24+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
2425
2526import com .github .tomakehurst .wiremock .WireMockServer ;
2627import java .io .IOException ;
3435import java .util .List ;
3536import java .util .Locale ;
3637import java .util .Map ;
38+ import java .util .concurrent .CompletionException ;
3739import java .util .stream .Stream ;
3840import org .junit .jupiter .api .AfterAll ;
3941import org .junit .jupiter .api .AfterEach ;
4042import org .junit .jupiter .api .BeforeAll ;
4143import org .junit .jupiter .api .BeforeEach ;
44+ import org .junit .jupiter .api .Test ;
4245import org .junit .jupiter .params .ParameterizedTest ;
4346import org .junit .jupiter .params .provider .MethodSource ;
4447import software .amazon .awssdk .auth .credentials .AwsBasicCredentials ;
4548import software .amazon .awssdk .auth .credentials .StaticCredentialsProvider ;
49+ import software .amazon .awssdk .core .exception .SdkClientException ;
4650import software .amazon .awssdk .core .interceptor .Context ;
4751import software .amazon .awssdk .core .interceptor .ExecutionAttributes ;
4852import software .amazon .awssdk .core .interceptor .ExecutionInterceptor ;
@@ -71,6 +75,8 @@ public static void setup() throws IOException {
7175
7276 public static Stream <ChecksumAlgorithm > checksumAlgorithmParams () {
7377 List <ChecksumAlgorithm > checksumAlgorithms = new ArrayList <>(ChecksumAlgorithm .knownValues ());
78+ // MD5 calculation is not supported in the SDK
79+ checksumAlgorithms .remove (ChecksumAlgorithm .MD5 );
7480 checksumAlgorithms .add (null );
7581 return checksumAlgorithms .stream ();
7682 }
@@ -100,8 +106,7 @@ public static void teardown() throws IOException {
100106 wireMock .stop ();
101107 }
102108
103- // TODO - re-enable after S3 feature release
104- /*@ParameterizedTest
109+ @ ParameterizedTest
105110 @ MethodSource ("checksumAlgorithmParams" )
106111 public void multipartUpload_withChecksumAlgorithmAndNoChecksumValueProvided_shouldNotAddChecksumType (ChecksumAlgorithm checksumAlgorithm ) {
107112 stubSuccessfulResponses ();
@@ -114,35 +119,22 @@ public void multipartUpload_withChecksumAlgorithmAndNoChecksumValueProvided_shou
114119 assertThat (checksumCapturingInterceptor .createMpuChecksumType ).isNull ();
115120 assertThat (checksumCapturingInterceptor .completeMpuChecksumType ).isNull ();
116121 assertThat (checksumCapturingInterceptor .completeMpuMpObjectSize ).isEqualTo (FILE_SIZE );
117- }*/
122+ }
118123
119- // TODO - re-enable after S3 feature release
120- /*@ParameterizedTest
124+ @ ParameterizedTest
121125 @ MethodSource ("checksumAlgorithmParams" )
122126 public void multipartUpload_withChecksumValueProvided_shouldUseSameAlgorithmForUploadAndAddChecksumTypeFullObject (ChecksumAlgorithm checksumAlgorithm ) {
123127 stubSuccessfulResponses ();
124128
125129 PutObjectRequest .Builder requestBuilder = putObjectRequestBuilder ();
126130 if (checksumAlgorithm != null ) {
127- switch (checksumAlgorithm) {
128- case CRC32:
129- requestBuilder.checksumCRC32("checksumVal");
130- break;
131- case SHA256:
132- requestBuilder.checksumSHA256("checksumVal");
133- break;
134- case CRC32_C:
135- requestBuilder.checksumCRC32C("checksumVal");
136- break;
137- case SHA1:
138- requestBuilder.checksumSHA1("checksumVal");
139- break;
140- case CRC64_NVME:
141- requestBuilder.checksumCRC64NVME("checksumVal");
142- break;
143- default:
144- throw new UnsupportedOperationException("Unsupported checksum algorithm: " + checksumAlgorithm);
145- }
131+ String checksumFieldName = "Checksum" + checksumAlgorithm ;
132+ requestBuilder .sdkFields ().stream ()
133+ .filter (f -> f .memberName ().equals (checksumFieldName ))
134+ .findFirst ()
135+ .orElseThrow (() -> new UnsupportedOperationException (
136+ "No SdkField found for checksum algorithm: " + checksumAlgorithm ))
137+ .set (requestBuilder , "checksumVal" );
146138 }
147139
148140 String expectedChecksumAlgo = checksumAlgorithm == null ? "CRC32" : checksumAlgorithm .toString ();
@@ -158,7 +150,34 @@ public void multipartUpload_withChecksumValueProvided_shouldUseSameAlgorithmForU
158150 assertThat (checksumCapturingInterceptor .completeMpuChecksumType ).isEqualTo (ChecksumType .FULL_OBJECT .toString ());
159151 }
160152 assertThat (checksumCapturingInterceptor .completeMpuMpObjectSize ).isEqualTo (FILE_SIZE );
161- }*/
153+ }
154+
155+ @ Test
156+ public void multipartUpload_withMd5ChecksumValueProvided_shouldPassThrough () {
157+ stubSuccessfulResponses ();
158+
159+ PutObjectRequest putObjectRequest = putObjectRequestBuilder ().checksumMD5 ("checksumVal" ).build ();
160+
161+ multipartS3 .putObject (putObjectRequest , testFile ).join ();
162+ assertThat (checksumCapturingInterceptor .createMpuChecksumAlgorithm ).isEqualTo ("MD5" );
163+ assertThat (checksumCapturingInterceptor .uploadPartChecksumAlgorithm ).isEqualTo ("MD5" );
164+ assertThat (checksumCapturingInterceptor .completeMpuHeaders .get ("x-amz-checksum-md5" )).contains ("checksumVal" );
165+ assertThat (checksumCapturingInterceptor .createMpuChecksumType ).isEqualTo (ChecksumType .FULL_OBJECT .toString ());
166+ assertThat (checksumCapturingInterceptor .completeMpuChecksumType ).isEqualTo (ChecksumType .FULL_OBJECT .toString ());
167+ assertThat (checksumCapturingInterceptor .completeMpuMpObjectSize ).isEqualTo (FILE_SIZE );
168+ }
169+
170+ @ Test
171+ public void multipartUpload_withMd5ChecksumAlgorithmProvided_shouldThrowException () {
172+ stubSuccessfulResponses ();
173+
174+ PutObjectRequest putObjectRequest = putObjectRequestBuilder ().checksumAlgorithm (ChecksumAlgorithm .MD5 ).build ();
175+
176+ assertThatThrownBy (() -> multipartS3 .putObject (putObjectRequest , testFile ).join ())
177+ .isInstanceOf (CompletionException .class )
178+ .hasCauseInstanceOf (SdkClientException .class )
179+ .hasMessageContaining ("MD5 is not supported" );
180+ }
162181
163182 private PutObjectRequest .Builder putObjectRequestBuilder () {
164183 return PutObjectRequest .builder ().bucket ("bucket" ).key ("key" );
0 commit comments