Skip to content

Commit be3fe4c

Browse files
authored
Integration test cases for Cross region Async and Sync Clients (#4128)
* Integration test cases for Cross region Sync and Sync Clients * Renamed files as Integration test * Handled CR comments to take care of retries thus captureInterceptor is removed * rebased and added CRT in Integ test
1 parent 4039f39 commit be3fe4c

File tree

6 files changed

+428
-1
lines changed

6 files changed

+428
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.services.s3.crossregion;
17+
18+
import static software.amazon.awssdk.testutils.service.S3BucketUtils.temporaryBucketName;
19+
20+
import org.junit.jupiter.api.AfterAll;
21+
import org.junit.jupiter.api.BeforeAll;
22+
import org.junit.jupiter.api.BeforeEach;
23+
import software.amazon.awssdk.services.s3.S3AsyncClient;
24+
25+
public class S3CrossRegionAsyncIntegrationTest extends S3CrossRegionAsyncIntegrationTestBase {
26+
private static final String BUCKET = temporaryBucketName(S3CrossRegionAsyncIntegrationTest.class);
27+
28+
@BeforeAll
29+
static void setUpClass() {
30+
s3 = s3ClientBuilder().build();
31+
createBucket(BUCKET);
32+
}
33+
34+
@AfterAll
35+
static void clearClass() {
36+
deleteBucketAndAllContents(BUCKET);
37+
}
38+
39+
@BeforeEach
40+
public void initialize() {
41+
crossRegionS3Client = S3AsyncClient.builder()
42+
.region(CROSS_REGION)
43+
.serviceConfiguration(s -> s.crossRegionAccessEnabled(true))
44+
.build();
45+
}
46+
47+
@Override
48+
protected String bucketName() {
49+
return BUCKET;
50+
}
51+
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.services.s3.crossregion;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
import java.util.concurrent.CompletableFuture;
21+
import software.amazon.awssdk.core.ResponseBytes;
22+
import software.amazon.awssdk.core.async.AsyncRequestBody;
23+
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
24+
import software.amazon.awssdk.services.s3.S3AsyncClient;
25+
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
26+
import software.amazon.awssdk.services.s3.model.DeleteObjectResponse;
27+
import software.amazon.awssdk.services.s3.model.DeleteObjectsRequest;
28+
import software.amazon.awssdk.services.s3.model.DeleteObjectsResponse;
29+
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
30+
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
31+
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
32+
import software.amazon.awssdk.services.s3.model.HeadBucketResponse;
33+
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
34+
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
35+
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
36+
import software.amazon.awssdk.services.s3.model.S3Object;
37+
import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Publisher;
38+
39+
public abstract class S3CrossRegionAsyncIntegrationTestBase extends S3CrossRegionIntegrationTestBase{
40+
protected S3AsyncClient crossRegionS3Client;
41+
42+
@Override
43+
protected List<S3Object> paginatedAPICall(ListObjectsV2Request listObjectsV2Request) {
44+
List<S3Object> resultObjects = new ArrayList<>();
45+
ListObjectsV2Publisher publisher = crossRegionS3Client.listObjectsV2Paginator(listObjectsV2Request);
46+
CompletableFuture<Void> subscribe = publisher.subscribe(response -> {
47+
response.contents().forEach(a -> resultObjects.add(a));
48+
});
49+
subscribe.join();
50+
return resultObjects;
51+
}
52+
53+
@Override
54+
protected DeleteObjectsResponse postObjectAPICall(DeleteObjectsRequest deleteObjectsRequest) {
55+
return crossRegionS3Client.deleteObjects(deleteObjectsRequest).join();
56+
}
57+
58+
@Override
59+
protected HeadBucketResponse headAPICall(HeadBucketRequest headBucketRequest) {
60+
return crossRegionS3Client.headBucket(headBucketRequest).join();
61+
}
62+
63+
@Override
64+
protected DeleteObjectResponse deleteObjectAPICall(DeleteObjectRequest deleteObjectRequest) {
65+
return crossRegionS3Client.deleteObject(deleteObjectRequest).join();
66+
}
67+
68+
@Override
69+
protected PutObjectResponse putAPICall(PutObjectRequest putObjectRequest, String testString) {
70+
return crossRegionS3Client.putObject(putObjectRequest, AsyncRequestBody.fromString(testString)).join();
71+
}
72+
73+
@Override
74+
protected ResponseBytes<GetObjectResponse> getAPICall(GetObjectRequest getObjectRequest) {
75+
return crossRegionS3Client.getObject(getObjectRequest, AsyncResponseTransformer.toBytes()).join();
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.services.s3.crossregion;
17+
18+
import static software.amazon.awssdk.testutils.service.S3BucketUtils.temporaryBucketName;
19+
20+
import org.junit.jupiter.api.AfterAll;
21+
import org.junit.jupiter.api.BeforeAll;
22+
import org.junit.jupiter.api.BeforeEach;
23+
import software.amazon.awssdk.services.s3.S3AsyncClient;
24+
25+
public class S3CrossRegionCrtIntegrationTest extends S3CrossRegionAsyncIntegrationTestBase {
26+
private static final String BUCKET = temporaryBucketName(S3CrossRegionCrtIntegrationTest.class);
27+
28+
@BeforeAll
29+
static void setUpClass() {
30+
s3 = s3ClientBuilder().build();
31+
createBucket(BUCKET);
32+
}
33+
34+
@AfterAll
35+
static void clearClass() {
36+
deleteBucketAndAllContents(BUCKET);
37+
}
38+
39+
@BeforeEach
40+
public void initialize() {
41+
crossRegionS3Client = S3AsyncClient.crtBuilder()
42+
.region(CROSS_REGION)
43+
.crossRegionAccessEnabled(true)
44+
.build();
45+
}
46+
@Override
47+
protected String bucketName() {
48+
return BUCKET;
49+
}
50+
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package software.amazon.awssdk.services.s3.crossregion;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
import java.util.List;
21+
import java.util.stream.IntStream;
22+
import org.junit.jupiter.api.Test;
23+
import software.amazon.awssdk.core.ResponseBytes;
24+
import software.amazon.awssdk.core.sync.RequestBody;
25+
import software.amazon.awssdk.regions.Region;
26+
import software.amazon.awssdk.services.s3.S3IntegrationTestBase;
27+
import software.amazon.awssdk.services.s3.model.ChecksumAlgorithm;
28+
import software.amazon.awssdk.services.s3.model.ChecksumMode;
29+
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
30+
import software.amazon.awssdk.services.s3.model.DeleteObjectResponse;
31+
import software.amazon.awssdk.services.s3.model.DeleteObjectsRequest;
32+
import software.amazon.awssdk.services.s3.model.DeleteObjectsResponse;
33+
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
34+
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
35+
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
36+
import software.amazon.awssdk.services.s3.model.HeadBucketResponse;
37+
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
38+
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
39+
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
40+
import software.amazon.awssdk.services.s3.model.S3Object;
41+
42+
public abstract class S3CrossRegionIntegrationTestBase extends S3IntegrationTestBase {
43+
44+
public static final String X_AMZ_BUCKET_REGION = "x-amz-bucket-region";
45+
46+
protected static final Region CROSS_REGION = Region.of("eu-central-1");
47+
48+
private static final String KEY = "key";
49+
50+
@Test
51+
void getApi_CrossRegionCall() {
52+
s3.putObject(p -> p.bucket(bucketName()).checksumAlgorithm(ChecksumAlgorithm.CRC32).key(KEY), RequestBody.fromString(
53+
"TEST_STRING"));
54+
GetObjectRequest getObjectRequest =
55+
GetObjectRequest.builder().bucket(bucketName()).checksumMode(ChecksumMode.ENABLED).key(KEY).build();
56+
ResponseBytes<GetObjectResponse> response = getAPICall(getObjectRequest);
57+
assertThat(new String(response.asByteArray())).isEqualTo("TEST_STRING");
58+
}
59+
60+
@Test
61+
void putApi_CrossRegionCall() {
62+
s3.putObject(p -> p.bucket(bucketName()).checksumAlgorithm(ChecksumAlgorithm.CRC32).key(KEY), RequestBody.fromString(
63+
"TEST_STRING"));
64+
PutObjectRequest putObjectRequest =
65+
PutObjectRequest.builder().bucket(bucketName()).checksumAlgorithm(ChecksumAlgorithm.CRC32).key(KEY).build();
66+
PutObjectResponse response = putAPICall(putObjectRequest, "TEST_STRING");
67+
assertThat(response.checksumCRC32()).isEqualTo("S9ke8w==");
68+
}
69+
70+
@Test
71+
void deleteApi_CrossRegionCall() {
72+
s3.putObject(p -> p.bucket(bucketName()).checksumAlgorithm(ChecksumAlgorithm.CRC32).key(KEY), RequestBody.fromString(
73+
"TEST_STRING"));
74+
DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder().bucket(bucketName()).key(KEY).build();
75+
DeleteObjectResponse response = deleteObjectAPICall(deleteObjectRequest);
76+
assertThat(response).isNotNull();
77+
}
78+
79+
@Test
80+
void postApi_CrossRegionCall() {
81+
s3.putObject(p -> p.bucket(bucketName()).checksumAlgorithm(ChecksumAlgorithm.CRC32).key(KEY), RequestBody.fromString(
82+
"TEST_STRING"));
83+
s3.putObject(p -> p.bucket(bucketName()).checksumAlgorithm(ChecksumAlgorithm.CRC32).key(KEY + "_1"),
84+
RequestBody.fromString("TEST_STRING"));
85+
DeleteObjectsRequest deleteObjectsRequest =
86+
DeleteObjectsRequest.builder().bucket(bucketName()).delete(d -> d.objects(o -> o.key(KEY), o -> o.key(KEY + "_1"))).build();
87+
DeleteObjectsResponse response = postObjectAPICall(deleteObjectsRequest);
88+
assertThat(response).isNotNull();
89+
}
90+
91+
@Test
92+
void cachedRegionGetsUsed_when_CrossRegionCall() {
93+
putAPICall(PutObjectRequest.builder().bucket(bucketName()).checksumAlgorithm(ChecksumAlgorithm.CRC32).key(KEY).build(),
94+
"TEST_STRING");
95+
GetObjectRequest getObjectRequest =
96+
GetObjectRequest.builder().bucket(bucketName()).checksumMode(ChecksumMode.ENABLED).key(KEY).build();
97+
ResponseBytes<GetObjectResponse> response = getAPICall(getObjectRequest);
98+
assertThat(new String(response.asByteArray())).isEqualTo("TEST_STRING");
99+
}
100+
101+
@Test
102+
void paginatedApi_CrossRegionCall() {
103+
s3.deleteObject(p -> p.bucket(bucketName()).key(KEY));
104+
int maxKeys = 3;
105+
int totalKeys = maxKeys * 2 ;
106+
IntStream.range(0, totalKeys )
107+
.forEach(
108+
i ->
109+
s3.putObject(p -> p.bucket(bucketName()).checksumAlgorithm(ChecksumAlgorithm.CRC32).key(KEY + "_" + i),
110+
RequestBody.fromString("TEST_STRING"))
111+
);
112+
ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder().bucket(bucketName()).maxKeys(maxKeys).build();
113+
List<S3Object> s3ObjectList = paginatedAPICall(listObjectsV2Request);
114+
assertThat(s3ObjectList).hasSize(totalKeys);
115+
IntStream.range(0, totalKeys ).forEach(i -> s3.deleteObject(p -> p.bucket(bucketName()).key(KEY + "_" + i)));
116+
}
117+
118+
@Test
119+
void headApi_CrossRegionCall() {
120+
s3.putObject(p -> p.bucket(bucketName()).checksumAlgorithm(ChecksumAlgorithm.CRC32).key(KEY), RequestBody.fromString(
121+
"TEST_STRING"));
122+
HeadBucketRequest headBucketRequest = HeadBucketRequest.builder().bucket(bucketName()).build();
123+
HeadBucketResponse response = headAPICall(headBucketRequest);
124+
assertThat(response).isNotNull();
125+
}
126+
127+
protected abstract List<S3Object> paginatedAPICall(ListObjectsV2Request listObjectsV2Request);
128+
129+
protected abstract DeleteObjectsResponse postObjectAPICall(DeleteObjectsRequest deleteObjectsRequest);
130+
131+
protected abstract HeadBucketResponse headAPICall(HeadBucketRequest headBucketRequest);
132+
133+
protected abstract DeleteObjectResponse deleteObjectAPICall(DeleteObjectRequest deleteObjectRequest);
134+
135+
protected abstract PutObjectResponse putAPICall(PutObjectRequest putObjectRequest, String testString);
136+
137+
protected abstract ResponseBytes<GetObjectResponse> getAPICall(GetObjectRequest getObjectRequest);
138+
139+
protected abstract String bucketName();
140+
141+
}

0 commit comments

Comments
 (0)