Skip to content

Commit 940735d

Browse files
authored
Add http client test suite for long-running request patterns (#6924)
* http test suite added * checkstyle fix * fix test name * fix check style
1 parent d3e9148 commit 940735d

9 files changed

Lines changed: 558 additions & 0 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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.http.apache;
17+
18+
import software.amazon.awssdk.http.SdkHttpClient;
19+
import software.amazon.awssdk.http.SdkHttpClientLongRunningRequestTestSuite;
20+
import software.amazon.awssdk.utils.AttributeMap;
21+
22+
public class ApacheHttpClientLongRunningRequestTest extends SdkHttpClientLongRunningRequestTestSuite {
23+
24+
@Override
25+
protected SdkHttpClient createSdkHttpClient(AttributeMap config) {
26+
return ApacheHttpClient.builder().buildWithDefaults(config);
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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.http.apache5;
17+
18+
import software.amazon.awssdk.http.SdkHttpClient;
19+
import software.amazon.awssdk.http.SdkHttpClientLongRunningRequestTestSuite;
20+
import software.amazon.awssdk.utils.AttributeMap;
21+
22+
public class Apache5HttpClientLongRunningRequestTest extends SdkHttpClientLongRunningRequestTestSuite {
23+
24+
@Override
25+
protected SdkHttpClient createSdkHttpClient(AttributeMap config) {
26+
return Apache5HttpClient.builder().buildWithDefaults(config);
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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.http.crt;
17+
18+
import org.junit.jupiter.api.BeforeAll;
19+
import software.amazon.awssdk.crt.Log;
20+
import software.amazon.awssdk.http.SdkAsyncHttpClientLongRunningRequestTestSuite;
21+
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
22+
import software.amazon.awssdk.utils.AttributeMap;
23+
24+
public class AwsCrtAsyncHttpClientLongRunningRequestTest extends SdkAsyncHttpClientLongRunningRequestTestSuite {
25+
26+
@BeforeAll
27+
public static void beforeAll() {
28+
System.setProperty("aws.crt.debugnative", "true");
29+
Log.initLoggingToStdout(Log.LogLevel.Warn);
30+
}
31+
32+
@Override
33+
protected SdkAsyncHttpClient createSdkAsyncHttpClient(AttributeMap config) {
34+
return AwsCrtAsyncHttpClient.builder().buildWithDefaults(config);
35+
}
36+
37+
// Empty test; the CRT async client does not currently enforce READ_TIMEOUT. Delete this
38+
// override when connection health monitoring is re-added.
39+
@Override
40+
public void executeWhenReadTimeoutAndServerDelaysResponseFailsWithinTimeoutBound() {
41+
}
42+
43+
// Empty test; the CRT async client does not currently enforce READ_TIMEOUT. Delete this
44+
// override when connection health monitoring is re-added.
45+
@Override
46+
public void executeWhenReadTimeoutAndStreamingResponsePausesFailsWithinTimeoutBound() {
47+
}
48+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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.http.crt;
17+
18+
import org.junit.jupiter.api.BeforeAll;
19+
import software.amazon.awssdk.crt.Log;
20+
import software.amazon.awssdk.http.SdkHttpClient;
21+
import software.amazon.awssdk.http.SdkHttpClientLongRunningRequestTestSuite;
22+
import software.amazon.awssdk.utils.AttributeMap;
23+
24+
public class AwsCrtHttpClientLongRunningRequestTest extends SdkHttpClientLongRunningRequestTestSuite {
25+
26+
@BeforeAll
27+
public static void beforeAll() {
28+
System.setProperty("aws.crt.debugnative", "true");
29+
Log.initLoggingToStdout(Log.LogLevel.Warn);
30+
}
31+
32+
@Override
33+
protected SdkHttpClient createSdkHttpClient(AttributeMap config) {
34+
return AwsCrtHttpClient.builder().buildWithDefaults(config);
35+
}
36+
37+
// Empty test; the CRT sync client does not currently enforce READ_TIMEOUT. Delete this
38+
// override when connection health monitoring is re-added.
39+
@Override
40+
public void executeWhenReadTimeoutAndServerDelaysResponseFailsWithinTimeoutBound() {
41+
}
42+
43+
// Empty test; the CRT sync client does not currently enforce READ_TIMEOUT. Delete this
44+
// override when connection health monitoring is re-added.
45+
@Override
46+
public void executeWhenReadTimeoutAndStreamingResponsePausesFailsWithinTimeoutBound() {
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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.http.nio.netty;
17+
18+
import software.amazon.awssdk.http.SdkAsyncHttpClientLongRunningRequestTestSuite;
19+
import software.amazon.awssdk.http.async.SdkAsyncHttpClient;
20+
import software.amazon.awssdk.utils.AttributeMap;
21+
22+
public class NettyAsyncHttpClientLongRunningRequestTest extends SdkAsyncHttpClientLongRunningRequestTestSuite {
23+
24+
@Override
25+
protected SdkAsyncHttpClient createSdkAsyncHttpClient(AttributeMap config) {
26+
return NettyNioAsyncHttpClient.builder().buildWithDefaults(config);
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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.http.urlconnection;
17+
18+
import software.amazon.awssdk.http.SdkHttpClient;
19+
import software.amazon.awssdk.http.SdkHttpClientLongRunningRequestTestSuite;
20+
import software.amazon.awssdk.utils.AttributeMap;
21+
22+
public class UrlConnectionHttpClientLongRunningRequestTest extends SdkHttpClientLongRunningRequestTestSuite {
23+
24+
@Override
25+
protected SdkHttpClient createSdkHttpClient(AttributeMap config) {
26+
return UrlConnectionHttpClient.builder().buildWithDefaults(config);
27+
}
28+
29+
// Empty test; UrlConnectionHttpClient does not maintain a connection pool.
30+
@Override
31+
public void executeWhenConnectionAcquireTimeoutAndPoolExhaustedFailsWithinTimeoutBound() {
32+
}
33+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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.http;
17+
18+
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
19+
import static com.github.tomakehurst.wiremock.client.WireMock.any;
20+
import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
21+
22+
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
23+
import java.time.Duration;
24+
import java.util.concurrent.CompletableFuture;
25+
import java.util.concurrent.ExecutionException;
26+
import java.util.concurrent.TimeUnit;
27+
import java.util.concurrent.TimeoutException;
28+
29+
/**
30+
* Shared helpers for the long-running request test suites.
31+
*/
32+
public final class LongRunningRequestTestSupport {
33+
34+
public static final Duration CONFIGURED_TIMEOUT = Duration.ofSeconds(2);
35+
public static final Duration SERVER_DELAY = Duration.ofSeconds(10);
36+
public static final Duration TIME_BOUND_SAFETY_MARGIN = Duration.ofSeconds(10);
37+
public static final Duration HANG_DELAY = Duration.ofMinutes(1);
38+
39+
private LongRunningRequestTestSupport() {
40+
}
41+
42+
/**
43+
* Simulates long-polling and synchronous-invoke-with-extended-wait (SFN getActivityTask, SQS receiveMessage,
44+
* Lambda invoke): server delays the entire response.
45+
*/
46+
public static void stubLongPolling(WireMockExtension mockServer) {
47+
mockServer.stubFor(any(urlPathEqualTo("/"))
48+
.willReturn(aResponse().withStatus(200)
49+
.withBody("hello")
50+
.withFixedDelay((int) SERVER_DELAY.toMillis())));
51+
}
52+
53+
/**
54+
* Simulates streaming APIs (Transcribe Streaming, Kinesis subscribeToShard): server dribbles body chunks with
55+
* gaps between them.
56+
*/
57+
public static void stubStreamingWithPauses(WireMockExtension mockServer) {
58+
mockServer.stubFor(any(urlPathEqualTo("/"))
59+
.willReturn(aResponse().withStatus(200)
60+
.withBody("hello")
61+
.withChunkedDribbleDelay(2, (int) SERVER_DELAY.toMillis())));
62+
}
63+
64+
/**
65+
* Hangs indefinitely so a holding request can exhaust a single-slot pool while another racing request
66+
* exercises the acquire timeout.
67+
*/
68+
public static void stubHanging(WireMockExtension mockServer) {
69+
mockServer.stubFor(any(urlPathEqualTo("/"))
70+
.willReturn(aResponse().withStatus(200)
71+
.withBody("hello")
72+
.withFixedDelay((int) HANG_DELAY.toMillis())));
73+
}
74+
75+
public static void assertFailsWithinTimeBound(CompletableFuture<?> future, Duration expectedTimeout) {
76+
Duration maxWait = expectedTimeout.plus(TIME_BOUND_SAFETY_MARGIN);
77+
78+
try {
79+
future.get(maxWait.toMillis(), TimeUnit.MILLISECONDS);
80+
throw new AssertionError("Expected request to throw an exception but it completed successfully");
81+
} catch (TimeoutException e) {
82+
future.cancel(true);
83+
throw new AssertionError(
84+
"Expected request to fail within " + maxWait + " but it was still running - client appears to hang",
85+
e);
86+
} catch (InterruptedException e) {
87+
Thread.currentThread().interrupt();
88+
throw new AssertionError("Unexpected interruption while waiting for request to fail", e);
89+
} catch (ExecutionException e) {
90+
// expected
91+
}
92+
}
93+
}

0 commit comments

Comments
 (0)