Skip to content

Commit e32cd09

Browse files
authored
fix: set instruction file content length (#501)
* fix: set instruction file content length
1 parent d829a23 commit e32cd09

File tree

2 files changed

+83
-6
lines changed

2 files changed

+83
-6
lines changed

src/main/java/software/amazon/encryption/s3/internal/InstructionFileConfig.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
package software.amazon.encryption.s3.internal;
22

3-
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.DEFAULT_INSTRUCTION_FILE_SUFFIX;
4-
import static software.amazon.encryption.s3.internal.MetadataKeyConstants.INSTRUCTION_FILE;
5-
6-
import java.util.HashMap;
7-
import java.util.Map;
8-
93
import software.amazon.awssdk.core.ResponseInputStream;
104
import software.amazon.awssdk.core.async.AsyncRequestBody;
115
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
@@ -18,6 +12,12 @@
1812
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
1913
import software.amazon.encryption.s3.S3EncryptionClientException;
2014

15+
import java.util.HashMap;
16+
import java.util.Map;
17+
18+
import static software.amazon.encryption.s3.S3EncryptionClientUtilities.DEFAULT_INSTRUCTION_FILE_SUFFIX;
19+
import static software.amazon.encryption.s3.internal.MetadataKeyConstants.INSTRUCTION_FILE;
20+
2121
/**
2222
* Provides configuration options for instruction file behaviors.
2323
*/
@@ -65,8 +65,10 @@ PutObjectResponse putInstructionFile(PutObjectRequest request, String instructio
6565
instFileMetadata.put(INSTRUCTION_FILE, "");
6666

6767
// Use toBuilder to keep all other fields the same as the actual request
68+
// but set the content length, key, and metadata appropriately for the instruction file
6869
final PutObjectRequest instPutRequest = request.toBuilder()
6970
.key(request.key() + instructionFileSuffix)
71+
.contentLength((long) instructionFileContent.getBytes().length)
7072
.metadata(instFileMetadata)
7173
.build();
7274
switch (_clientType) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package software.amazon.encryption.s3.internal;
4+
5+
import org.junit.jupiter.api.Test;
6+
import org.mockito.ArgumentCaptor;
7+
import software.amazon.awssdk.core.async.AsyncRequestBody;
8+
import software.amazon.awssdk.core.sync.RequestBody;
9+
import software.amazon.awssdk.services.s3.S3AsyncClient;
10+
import software.amazon.awssdk.services.s3.S3Client;
11+
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
12+
13+
import java.util.concurrent.CompletableFuture;
14+
15+
import static org.junit.jupiter.api.Assertions.assertEquals;
16+
import static org.mockito.ArgumentMatchers.any;
17+
import static org.mockito.Mockito.*;
18+
19+
class InstructionFileConfigUploadTest {
20+
21+
@Test
22+
void uploadInstructionFileWithSetContentLengthSyncClient() {
23+
// Create a mock for the S3 client
24+
S3Client mockedS3Client = mock(S3Client.class);
25+
// The argument captor is used to capture the PutObjectRequest passed to the putObject method
26+
ArgumentCaptor<PutObjectRequest> instructionFilePutCaptor = ArgumentCaptor.forClass(PutObjectRequest.class);
27+
28+
// Create the InstructionFileConfig with the mocked S3 client
29+
InstructionFileConfig instructionFileConfig = InstructionFileConfig.builder()
30+
.instructionFileClient(mockedS3Client)
31+
.enableInstructionFilePutObject(true)
32+
.build();
33+
34+
// Build some data for the test
35+
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
36+
.key("someKey").build();
37+
String instructionFileContent = "some content that fakes an instruction file";
38+
39+
// call the actual method under test
40+
instructionFileConfig.putInstructionFile(putObjectRequest, instructionFileContent);
41+
42+
// Verify that the putObject method was called and the captured request has the correct content length
43+
verify(mockedS3Client).putObject(instructionFilePutCaptor.capture(), any(RequestBody.class));
44+
assertEquals(instructionFileContent.getBytes().length, instructionFilePutCaptor.getValue().contentLength());
45+
}
46+
47+
@Test
48+
void uploadInstructionFileWithSetContentLengthAsyncClient() {
49+
// Create a mock for the S3 client
50+
S3AsyncClient mockedS3Client = mock(S3AsyncClient.class);
51+
// The async putObject method returns a CompletableFuture, so we need to mock that behavior
52+
when(mockedS3Client.putObject(any(PutObjectRequest.class), any(AsyncRequestBody.class)))
53+
.thenReturn(CompletableFuture.completedFuture(null));
54+
// The argument captor is used to capture the PutObjectRequest passed to the putObject method
55+
ArgumentCaptor<PutObjectRequest> instructionFilePutCaptor = ArgumentCaptor.forClass(PutObjectRequest.class);
56+
57+
// Create the InstructionFileConfig with the mocked S3 async client
58+
InstructionFileConfig instructionFileConfig = InstructionFileConfig.builder()
59+
.instructionFileAsyncClient(mockedS3Client)
60+
.enableInstructionFilePutObject(true)
61+
.build();
62+
63+
// Build some data for the test
64+
PutObjectRequest putObjectRequest = PutObjectRequest.builder()
65+
.key("someKey").build();
66+
String instructionFileContent = "some content that fakes an instruction file";
67+
68+
// Call the actual method under test
69+
instructionFileConfig.putInstructionFile(putObjectRequest, instructionFileContent);
70+
71+
// Verify that the putObject method was called and the captured request has the correct content length
72+
verify(mockedS3Client).putObject(instructionFilePutCaptor.capture(), any(AsyncRequestBody.class));
73+
assertEquals(instructionFileContent.getBytes().length, instructionFilePutCaptor.getValue().contentLength());
74+
}
75+
}

0 commit comments

Comments
 (0)