Skip to content

Commit 1a0a0e4

Browse files
committed
Merge branch 'main' into crt_updates
2 parents 9a406f3 + 4ca824d commit 1a0a0e4

9 files changed

Lines changed: 113 additions & 143 deletions

File tree

.builder/actions/localhost_test.py

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,56 @@
11
import Builder
2+
import subprocess
3+
import socket
24
import sys
5+
import time
36
import os
47

58

69
class LocalhostTest(Builder.Action):
710

11+
def start(self, env):
12+
python = sys.executable
13+
venv_path = os.path.join(env.root_dir,'crt','aws-c-http','tests','mock_server', '.venv')
14+
15+
result = env.shell.exec(python, '-m', 'venv', venv_path)
16+
if result.returncode != 0:
17+
print("Could not start a virtual environment. The localhost integration tests will fail.", file=sys.stderr)
18+
return
19+
20+
python = os.path.join(venv_path, "bin", "python")
21+
22+
result = env.shell.exec(python, '-m', 'pip', 'install', 'h11', 'h2', 'trio')
23+
if result.returncode != 0:
24+
print("Could not install python HTTP dependencies. The localhost integration tests will fail.", file=sys.stderr)
25+
return
26+
27+
server_dir = os.path.join(env.root_dir,'crt','aws-c-http','tests','mock_server')
28+
29+
p1 = subprocess.Popen([python, "h2tls_mock_server.py"], cwd=server_dir)
30+
p2 = subprocess.Popen([python, "h2non_tls_server.py"], cwd=server_dir)
31+
p3 = subprocess.Popen([python, "h11mock_server.py"], cwd=server_dir)
32+
33+
# Wait for servers to be ready
34+
ports = [3443, 3280, 8082, 8081]
35+
for port in ports:
36+
for attempt in range(30):
37+
try:
38+
with socket.create_connection(("localhost", port), timeout=1):
39+
print(f"Server on port {port} is ready")
40+
break
41+
except (socket.error, ConnectionRefusedError, OSError):
42+
if attempt == 29:
43+
print(f"ERROR: Server on port {port} failed to start", file=sys.stderr)
44+
time.sleep(1)
45+
846
def run(self, env):
47+
self.start(env)
948
env.shell.setenv('AWS_CRT_MEMORY_TRACING', '2')
10-
actions = []
11-
if os.system("mvn -Dtest=Http2ClientLocalHostTest test -DredirectTestOutputToFile=true -DforkCount=0 \
49+
50+
if os.system("mvn test -DredirectTestOutputToFile=true -DforkCount=0 \
1251
-Daws.crt.memory.tracing=2 \
1352
-Daws.crt.debugnative=true \
14-
-Daws.crt.log.level=Debug \
53+
-Daws.crt.aws_trace_log_per_test \
1554
-Daws.crt.localhost=true"):
1655
# Failed
1756
actions.append("exit 1")
18-
19-
return Builder.Script(actions, name='aws-crt-java-test')

.github/workflows/ci.yml

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -436,16 +436,11 @@ jobs:
436436
uses: actions/checkout@v4
437437
with:
438438
submodules: true
439-
- name: Configure local host
440-
run: |
441-
python3 -m pip install h2
442-
cd crt/aws-c-http/tests/py_localhost/
443-
python3 server.py &
444-
python3 non_tls_server.py &
445439
- name: Build and test
446440
run: |
447441
python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')"
448-
python builder.pyz localhost-test -p ${{ env.PACKAGE_NAME }} --spec=downstream
442+
python builder.pyz build -p ${{ env.PACKAGE_NAME }} --variant=localhost
443+
449444
450445
localhost-test-macos:
451446
runs-on: macos-14 # latest
@@ -458,19 +453,11 @@ jobs:
458453
uses: actions/checkout@v4
459454
with:
460455
submodules: true
461-
- name: Configure local host
462-
run: |
463-
python3 -m venv .venv
464-
source .venv/bin/activate
465-
python3 -m pip install h2
466-
cd crt/aws-c-http/tests/py_localhost/
467-
python3 server.py &
468-
python3 non_tls_server.py &
469456
- name: Build and test
470457
run: |
471458
python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')"
472459
chmod a+x builder
473-
./builder localhost-test -p ${{ env.PACKAGE_NAME }} --spec=downstream
460+
./builder build -p ${{ env.PACKAGE_NAME }} --variant=localhost
474461
475462
localhost-test-win:
476463
runs-on: windows-2025 # latest
@@ -483,17 +470,10 @@ jobs:
483470
uses: actions/checkout@v4
484471
with:
485472
submodules: true
486-
- name: Configure local host
487-
run: |
488-
python -m pip install h2
489473
- name: Build and test
490474
run: |
491-
cd crt/aws-c-http/tests/py_localhost/
492-
Start-Process -NoNewWindow python .\server.py
493-
Start-Process -NoNewWindow python .\non_tls_server.py
494-
cd ../../../../
495475
python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')"
496-
python builder.pyz localhost-test -p ${{ env.PACKAGE_NAME }} downstream
476+
python builder.pyz build -p ${{ env.PACKAGE_NAME }} --variant=localhost
497477
498478
GraalVM:
499479
runs-on: ${{ matrix.os }}

builder.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,14 @@
162162
"variants":{
163163
"graalvm": {
164164
"!packages": [],
165-
"!imports": [
166-
],
165+
"!imports": [],
167166
"!test_env": {
168167
"AWS_GRAALVM_CI": true
169168
},
170169
"!build_env": {}
170+
},
171+
"localhost": {
172+
"!test_steps": ["localhost-test"]
171173
}
172174
}
173175
}

src/test/java/software/amazon/awssdk/crt/test/Http2ClientConnectionTest.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,11 @@ public class Http2ClientConnectionTest extends HttpClientTestFixture {
2828

2929
private final static int MAX_TEST_RETRIES = 5;
3030
private final static int TEST_RETRY_SLEEP_MILLIS = 2000;
31-
private final static String HOST = "https://postman-echo.com";
31+
// crt/aws-c-http/tests/mock_server includes a readme on how the server can be run locally for testing.
32+
private final static String HOST = "https://localhost:3443";
3233
private final static HttpVersion EXPECTED_VERSION = HttpVersion.HTTP_2;
3334

34-
@Before
35-
public void setUp() {
36-
// postman-echo.com in now requires TLS1.3,
37-
// but our Mac implementation doesn't support TLS1.3 yet.
38-
// The work has been planned to Dec. 2025 to support TLS1.3,
39-
// so disable the test for now. And reenable it afterward
40-
skipIfMac();
41-
}
35+
4236

4337
private void doHttp2ConnectionGetVersionTest() {
4438
try {
@@ -66,6 +60,7 @@ private void doHttp2ConnectionGetVersionTest() {
6660
public void testHttp2ConnectionGetVersion() throws Exception {
6761
skipIfAndroid();
6862
skipIfNetworkUnavailable();
63+
skipIfLocalhostUnavailable();
6964

7065
TestUtils.doRetryableTest(this::doHttp2ConnectionGetVersionTest, TestUtils::isRetryableTimeout, MAX_TEST_RETRIES, TEST_RETRY_SLEEP_MILLIS);
7166

@@ -104,6 +99,7 @@ private void doHttp2ConnectionUpdateSettingsTest() {
10499
public void testHttp2ConnectionUpdateSettings() throws Exception {
105100
skipIfAndroid();
106101
skipIfNetworkUnavailable();
102+
skipIfLocalhostUnavailable();
107103

108104
TestUtils.doRetryableTest(this::doHttp2ConnectionUpdateSettingsTest, TestUtils::isRetryableTimeout, MAX_TEST_RETRIES, TEST_RETRY_SLEEP_MILLIS);
109105

@@ -139,6 +135,7 @@ public void testHttp2ConnectionUpdateSettingsEmpty() throws Exception {
139135
skipIfAndroid();
140136
/* empty settings is allowed to send */
141137
skipIfNetworkUnavailable();
138+
skipIfLocalhostUnavailable();
142139

143140
TestUtils.doRetryableTest(this::doHttp2ConnectionUpdateSettingsEmptyTest, TestUtils::isRetryableTimeout, MAX_TEST_RETRIES, TEST_RETRY_SLEEP_MILLIS);
144141

@@ -176,6 +173,7 @@ private void doHttp2ConnectionPingTest() {
176173
public void testHttp2ConnectionPing() throws Exception {
177174
skipIfAndroid();
178175
skipIfNetworkUnavailable();
176+
skipIfLocalhostUnavailable();
179177

180178
TestUtils.doRetryableTest(this::doHttp2ConnectionPingTest, TestUtils::isRetryableTimeout, MAX_TEST_RETRIES, TEST_RETRY_SLEEP_MILLIS);
181179

@@ -220,6 +218,7 @@ private void doHttp2ConnectionPingExceptionPingDataLengthTest() {
220218
public void testHttp2ConnectionPingExceptionPingDataLength() throws Exception {
221219
skipIfAndroid();
222220
skipIfNetworkUnavailable();
221+
skipIfLocalhostUnavailable();
223222

224223
TestUtils.doRetryableTest(this::doHttp2ConnectionPingExceptionPingDataLengthTest, TestUtils::isRetryableTimeout, MAX_TEST_RETRIES, TEST_RETRY_SLEEP_MILLIS);
225224

@@ -258,6 +257,7 @@ public void testHttp2ConnectionSendGoAway() throws Exception {
258257
* for functionality
259258
*/
260259
skipIfNetworkUnavailable();
260+
skipIfLocalhostUnavailable();
261261

262262
TestUtils.doRetryableTest(this::doHttp2ConnectionSendGoAwayTest, TestUtils::isRetryableTimeout, MAX_TEST_RETRIES, TEST_RETRY_SLEEP_MILLIS);
263263

@@ -296,6 +296,7 @@ public void testHttp2ConnectionUpdateConnectionWindow() throws Exception {
296296
* for functionality
297297
*/
298298
skipIfNetworkUnavailable();
299+
skipIfLocalhostUnavailable();
299300

300301
TestUtils.doRetryableTest(this::doHttp2ConnectionUpdateConnectionWindowTest, TestUtils::isRetryableTimeout, MAX_TEST_RETRIES, TEST_RETRY_SLEEP_MILLIS);
301302

src/test/java/software/amazon/awssdk/crt/test/Http2ClientLocalHostTest.java

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import org.junit.Assert;
1919
import org.junit.Assume;
20+
import org.junit.Before;
2021
import org.junit.Test;
2122
import software.amazon.awssdk.crt.CRT;
2223
import software.amazon.awssdk.crt.CrtResource;
@@ -43,7 +44,7 @@
4344
import software.amazon.awssdk.crt.Log;
4445

4546
public class Http2ClientLocalHostTest extends HttpClientTestFixture {
46-
47+
// crt/aws-c-http/tests/mock_server includes a readme on how the server can be run locally for testing.
4748
private static final int LOCAL_HTTPS_PORT = 3443;
4849
private static final int LOCAL_HTTP_PORT = 3280;
4950

@@ -182,7 +183,7 @@ public void onResponseComplete(HttpStreamBase stream, int errorCode) {
182183
public void testParallelRequestsStressWithBody() throws Exception {
183184
skipIfAndroid();
184185
skipIfLocalhostUnavailable();
185-
URI uri = new URI(String.format("https://localhost:%d/uploadTest", LOCAL_HTTPS_PORT));
186+
URI uri = new URI(String.format("https://localhost:%d/echo", LOCAL_HTTPS_PORT));
186187
try (Http2StreamManager streamManager = createStreamManager(uri, 100)) {
187188
int numberToAcquire = 500 * 100;
188189
if (CRT.getOSIdentifier() == "linux") {
@@ -201,6 +202,7 @@ public void testParallelRequestsStressWithBody() throws Exception {
201202
final AtomicInteger numStreamsFailures = new AtomicInteger(0);
202203
for (int i = 0; i < numberToAcquire; i++) {
203204
Http2Request request = createHttp2Request("PUT", uri, bodyLength);
205+
request.addHeader(new HttpHeader("x-upload-test", "true"));
204206

205207
final CompletableFuture<Void> requestCompleteFuture = new CompletableFuture<Void>();
206208
final int expectedLength = bodyLength;
@@ -217,12 +219,11 @@ public void onResponseHeaders(HttpStreamBase stream, int responseStatusCode, int
217219
@Override
218220
public int onResponseBody(HttpStreamBase stream, byte[] bodyBytesIn){
219221
String bodyString = new String(bodyBytesIn);
220-
int receivedLength = Integer.parseInt(bodyString);
221-
222-
Assert.assertTrue(receivedLength == expectedLength);
223-
if(receivedLength!=expectedLength) {
224-
numStreamsFailures.incrementAndGet();
225-
}
222+
// Parse {"bytes": 123456} manually
223+
int start = bodyString.indexOf("\"bytes\":") + 8;
224+
int end = bodyString.indexOf("}", start);
225+
String bytesStr = bodyString.substring(start, end).trim();
226+
long receivedLength = Long.parseLong(bytesStr);
226227
return bodyString.length();
227228
}
228229

@@ -252,10 +253,9 @@ public void onResponseComplete(HttpStreamBase stream, int errorCode) {
252253
@Test
253254
public void testRequestsUploadStress() throws Exception {
254255
skipIfAndroid();
255-
/* Test that upload a 2.5GB data from local server (0.25GB for linux) */
256256
skipIfLocalhostUnavailable();
257-
258-
URI uri = new URI(String.format("https://localhost:%d/uploadTest", LOCAL_HTTPS_PORT));
257+
/* Test that upload a 2.5GB data from local server (0.25GB for linux) */
258+
URI uri = new URI(String.format("https://localhost:%d/echo", LOCAL_HTTPS_PORT));
259259
try (Http2StreamManager streamManager = createStreamManager(uri, 100)) {
260260
long bodyLength = 2500000000L;
261261
if (CRT.getOSIdentifier() == "linux") {
@@ -269,21 +269,26 @@ public void testRequestsUploadStress() throws Exception {
269269
}
270270

271271
Http2Request request = createHttp2Request("PUT", uri, bodyLength);
272+
request.addHeader(new HttpHeader("x-upload-test", "true"));
272273

273274
final CompletableFuture<Void> requestCompleteFuture = new CompletableFuture<Void>();
274275
final long expectedLength = bodyLength;
275276
CompletableFuture<Http2Stream> acquireCompleteFuture = streamManager.acquireStream(request, new HttpStreamBaseResponseHandler() {
276277
@Override
277278
public void onResponseHeaders(HttpStreamBase stream, int responseStatusCode, int blockType,
278-
HttpHeader[] nextHeaders) {
279+
HttpHeader[] nextHeaders) {
279280

280281
Assert.assertTrue(responseStatusCode == 200);
281282
}
282283

283284
@Override
284285
public int onResponseBody(HttpStreamBase stream, byte[] bodyBytesIn){
285286
String bodyString = new String(bodyBytesIn);
286-
long receivedLength = Long.parseLong(bodyString);
287+
// Parse {"bytes": 123456} manually
288+
int start = bodyString.indexOf("\"bytes\":") + 8;
289+
int end = bodyString.indexOf("}", start);
290+
String bytesStr = bodyString.substring(start, end).trim();
291+
long receivedLength = Long.parseLong(bytesStr);
287292
Assert.assertTrue(receivedLength == expectedLength);
288293
return bodyString.length();
289294
}
@@ -307,20 +312,21 @@ public void onResponseComplete(HttpStreamBase stream, int errorCode) {
307312
@Test
308313
public void testRequestsDownloadStress() throws Exception {
309314
skipIfAndroid();
310-
/* Test that download a 2.5GB data from local server */
311315
skipIfLocalhostUnavailable();
312-
URI uri = new URI(String.format("https://localhost:%d/downloadTest", LOCAL_HTTPS_PORT));
316+
/* Test that download a 2.5GB data from local server */
317+
URI uri = new URI(String.format("https://localhost:%d/echo", LOCAL_HTTPS_PORT));
313318
try (Http2StreamManager streamManager = createStreamManager(uri, 100)) {
314319
long bodyLength = 2500000000L;
315320

316321
Http2Request request = createHttp2Request("GET", uri, 0);
322+
request.addHeader(new HttpHeader("x-repeat-data", String.valueOf(bodyLength)));
317323

318324
final CompletableFuture<Void> requestCompleteFuture = new CompletableFuture<Void>();
319325
final AtomicLong receivedLength = new AtomicLong(0);
320326
CompletableFuture<Http2Stream> acquireCompleteFuture = streamManager.acquireStream(request, new HttpStreamBaseResponseHandler() {
321327
@Override
322328
public void onResponseHeaders(HttpStreamBase stream, int responseStatusCode, int blockType,
323-
HttpHeader[] nextHeaders) {
329+
HttpHeader[] nextHeaders) {
324330

325331
Assert.assertTrue(responseStatusCode == 200);
326332
}

0 commit comments

Comments
 (0)