Skip to content

Commit c8416b9

Browse files
committed
large response test
1 parent 600520c commit c8416b9

File tree

1 file changed

+149
-0
lines changed

1 file changed

+149
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/*
2+
* Copyright (c) 2015-2024 AsyncHttpClient Project. 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+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.asynchttpclient;
17+
18+
import com.sun.net.httpserver.HttpExchange;
19+
import com.sun.net.httpserver.HttpHandler;
20+
import com.sun.net.httpserver.HttpServer;
21+
import io.netty.handler.codec.http.HttpHeaders;
22+
import java.io.IOException;
23+
import java.io.OutputStream;
24+
import java.net.InetSocketAddress;
25+
import java.nio.charset.StandardCharsets;
26+
import java.time.Duration;
27+
import java.util.concurrent.TimeUnit;
28+
import java.util.concurrent.atomic.AtomicInteger;
29+
import java.util.concurrent.atomic.AtomicLong;
30+
import org.apache.commons.io.FileUtils;
31+
import org.jetbrains.annotations.Nullable;
32+
import org.junit.jupiter.api.AfterAll;
33+
import org.junit.jupiter.api.BeforeAll;
34+
import org.junit.jupiter.api.Test;
35+
import org.junit.jupiter.api.Timeout;
36+
import org.slf4j.Logger;
37+
import org.slf4j.LoggerFactory;
38+
39+
import static org.junit.jupiter.api.Assertions.assertEquals;
40+
41+
42+
public class LargeResponseTest {
43+
private static Logger LOG = LoggerFactory.getLogger(LargeResponseTest.class);
44+
private static final int textSize = 200_000;
45+
private static final byte[] textBytes = "z".repeat(textSize).getBytes(StandardCharsets.UTF_8);
46+
47+
private static final long responseSize = ((long)textSize) * (2_000_000L);
48+
49+
private static HttpServer HTTP_SERVER;
50+
51+
private static AsyncHttpClient createClient() {
52+
AsyncHttpClientConfig config = new DefaultAsyncHttpClientConfig.Builder()
53+
.setEnableAutomaticDecompression(true)
54+
.setCompressionEnforced(true)
55+
.setReadTimeout(Duration.ofMinutes(3))
56+
.setRequestTimeout(Duration.ofMinutes(3))
57+
.setConnectTimeout(Duration.ofSeconds(1))
58+
.build();
59+
return new DefaultAsyncHttpClient(config);
60+
}
61+
62+
@BeforeAll
63+
static void setupServer() throws Exception {
64+
HTTP_SERVER = HttpServer.create(new InetSocketAddress(0), 0);
65+
66+
HTTP_SERVER.createContext("/large").setHandler(new HttpHandler() {
67+
@Override
68+
public void handle(HttpExchange exchange)
69+
throws IOException {
70+
exchange.sendResponseHeaders(200, 0);
71+
long bytesWritten = 0;
72+
OutputStream out = exchange.getResponseBody();
73+
while (bytesWritten < responseSize) {
74+
out.write(textBytes);
75+
out.flush();
76+
bytesWritten += textBytes.length;
77+
}
78+
out.close();
79+
}
80+
});
81+
82+
HTTP_SERVER.start();
83+
}
84+
85+
@AfterAll
86+
static void stopServer() {
87+
if (HTTP_SERVER != null) {
88+
HTTP_SERVER.stop(0);
89+
}
90+
}
91+
92+
@Test
93+
@Timeout(value = 3, unit = TimeUnit.MINUTES)
94+
void handleLargeResponse() throws Throwable {
95+
AtomicInteger status = new AtomicInteger(-1);
96+
AtomicLong bytesReceived = new AtomicLong();
97+
AtomicInteger throwableCount = new AtomicInteger();
98+
AtomicInteger bodyPartCount = new AtomicInteger();
99+
100+
try (AsyncHttpClient client = createClient()) {
101+
Request request = new RequestBuilder("GET")
102+
.setUrl("http://localhost:" + HTTP_SERVER.getAddress().getPort() + "/large")
103+
.build();
104+
var future = client.executeRequest(request, new AsyncHandler<Object>() {
105+
@Override
106+
public State onStatusReceived(HttpResponseStatus responseStatus)
107+
throws Exception {
108+
status.set(responseStatus.getStatusCode());
109+
return State.CONTINUE;
110+
}
111+
112+
@Override
113+
public State onHeadersReceived(HttpHeaders headers)
114+
throws Exception {
115+
return State.CONTINUE;
116+
}
117+
118+
@Override
119+
public State onBodyPartReceived(HttpResponseBodyPart bodyPart)
120+
throws Exception {
121+
bodyPartCount.incrementAndGet();
122+
bytesReceived.addAndGet(bodyPart.length());
123+
return State.CONTINUE;
124+
}
125+
126+
@Override
127+
public void onThrowable(Throwable t) {
128+
throwableCount.incrementAndGet();
129+
}
130+
131+
@Override
132+
public @Nullable Object onCompleted()
133+
throws Exception {
134+
return null;
135+
}
136+
});
137+
138+
future.get(3, TimeUnit.MINUTES);
139+
140+
assertEquals(200, status.get());
141+
assertEquals(0, throwableCount.get());
142+
assertEquals(responseSize, bytesReceived.get());
143+
144+
LOG.info("Body part count: " + bodyPartCount);
145+
LOG.info("Body part average size: " + FileUtils.byteCountToDisplaySize(responseSize / bodyPartCount.get()));
146+
LOG.info("Response size: " + FileUtils.byteCountToDisplaySize(responseSize));
147+
}
148+
}
149+
}

0 commit comments

Comments
 (0)