Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/test/jdk/java/net/httpclient/AbstractThrowingSubscribers.java
66644 views
1
/*
2
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
import com.sun.net.httpserver.HttpServer;
25
import com.sun.net.httpserver.HttpsConfigurator;
26
import com.sun.net.httpserver.HttpsServer;
27
import jdk.test.lib.net.SimpleSSLContext;
28
import org.testng.ITestContext;
29
import org.testng.ITestResult;
30
import org.testng.SkipException;
31
import org.testng.annotations.AfterTest;
32
import org.testng.annotations.AfterClass;
33
import org.testng.annotations.BeforeMethod;
34
import org.testng.annotations.BeforeTest;
35
import org.testng.annotations.DataProvider;
36
import org.testng.annotations.Test;
37
38
import javax.net.ssl.SSLContext;
39
import java.io.BufferedReader;
40
import java.io.IOException;
41
import java.io.InputStream;
42
import java.io.InputStreamReader;
43
import java.io.OutputStream;
44
import java.io.UncheckedIOException;
45
import java.net.InetAddress;
46
import java.net.InetSocketAddress;
47
import java.net.URI;
48
import java.net.http.HttpClient;
49
import java.net.http.HttpHeaders;
50
import java.net.http.HttpRequest;
51
import java.net.http.HttpResponse;
52
import java.net.http.HttpResponse.BodyHandler;
53
import java.net.http.HttpResponse.BodyHandlers;
54
import java.net.http.HttpResponse.BodySubscriber;
55
import java.nio.ByteBuffer;
56
import java.nio.charset.StandardCharsets;
57
import java.util.Arrays;
58
import java.util.EnumSet;
59
import java.util.List;
60
import java.util.concurrent.CompletableFuture;
61
import java.util.concurrent.CompletionStage;
62
import java.util.concurrent.ConcurrentHashMap;
63
import java.util.concurrent.ConcurrentMap;
64
import java.util.concurrent.Executor;
65
import java.util.concurrent.Executors;
66
import java.util.concurrent.Flow;
67
import java.util.concurrent.atomic.AtomicLong;
68
import java.util.concurrent.atomic.AtomicReference;
69
import java.util.function.Consumer;
70
import java.util.function.Predicate;
71
import java.util.function.Supplier;
72
import java.util.stream.Collectors;
73
import java.util.stream.Stream;
74
75
import static java.lang.System.out;
76
import static java.lang.String.format;
77
import static java.nio.charset.StandardCharsets.UTF_8;
78
import static org.testng.Assert.assertEquals;
79
import static org.testng.Assert.assertTrue;
80
81
public abstract class AbstractThrowingSubscribers implements HttpServerAdapters {
82
83
SSLContext sslContext;
84
HttpTestServer httpTestServer; // HTTP/1.1 [ 4 servers ]
85
HttpTestServer httpsTestServer; // HTTPS/1.1
86
HttpTestServer http2TestServer; // HTTP/2 ( h2c )
87
HttpTestServer https2TestServer; // HTTP/2 ( h2 )
88
String httpURI_fixed;
89
String httpURI_chunk;
90
String httpsURI_fixed;
91
String httpsURI_chunk;
92
String http2URI_fixed;
93
String http2URI_chunk;
94
String https2URI_fixed;
95
String https2URI_chunk;
96
97
static final int ITERATION_COUNT = 1;
98
// a shared executor helps reduce the amount of threads created by the test
99
static final Executor executor = new TestExecutor(Executors.newCachedThreadPool());
100
static final ConcurrentMap<String, Throwable> FAILURES = new ConcurrentHashMap<>();
101
static volatile boolean tasksFailed;
102
static final AtomicLong serverCount = new AtomicLong();
103
static final AtomicLong clientCount = new AtomicLong();
104
static final long start = System.nanoTime();
105
public static String now() {
106
long now = System.nanoTime() - start;
107
long secs = now / 1000_000_000;
108
long mill = (now % 1000_000_000) / 1000_000;
109
long nan = now % 1000_000;
110
return String.format("[%d s, %d ms, %d ns] ", secs, mill, nan);
111
}
112
113
final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE;
114
private volatile HttpClient sharedClient;
115
116
static class TestExecutor implements Executor {
117
final AtomicLong tasks = new AtomicLong();
118
Executor executor;
119
TestExecutor(Executor executor) {
120
this.executor = executor;
121
}
122
123
@Override
124
public void execute(Runnable command) {
125
long id = tasks.incrementAndGet();
126
executor.execute(() -> {
127
try {
128
command.run();
129
} catch (Throwable t) {
130
tasksFailed = true;
131
System.out.printf(now() + "Task %s failed: %s%n", id, t);
132
System.err.printf(now() + "Task %s failed: %s%n", id, t);
133
FAILURES.putIfAbsent("Task " + id, t);
134
throw t;
135
}
136
});
137
}
138
}
139
140
protected boolean stopAfterFirstFailure() {
141
return Boolean.getBoolean("jdk.internal.httpclient.debug");
142
}
143
144
final AtomicReference<SkipException> skiptests = new AtomicReference<>();
145
void checkSkip() {
146
var skip = skiptests.get();
147
if (skip != null) throw skip;
148
}
149
static String name(ITestResult result) {
150
var params = result.getParameters();
151
return result.getName()
152
+ (params == null ? "()" : Arrays.toString(result.getParameters()));
153
}
154
155
@BeforeMethod
156
void beforeMethod(ITestContext context) {
157
if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) {
158
if (skiptests.get() == null) {
159
SkipException skip = new SkipException("some tests failed");
160
skip.setStackTrace(new StackTraceElement[0]);
161
skiptests.compareAndSet(null, skip);
162
}
163
}
164
}
165
166
@AfterClass
167
static final void printFailedTests(ITestContext context) {
168
out.println("\n=========================");
169
try {
170
// Exceptions should already have been added to FAILURES
171
// var failed = context.getFailedTests().getAllResults().stream()
172
// .collect(Collectors.toMap(r -> name(r), ITestResult::getThrowable));
173
// FAILURES.putAll(failed);
174
175
out.printf("%n%sCreated %d servers and %d clients%n",
176
now(), serverCount.get(), clientCount.get());
177
if (FAILURES.isEmpty()) return;
178
out.println("Failed tests: ");
179
FAILURES.entrySet().forEach((e) -> {
180
out.printf("\t%s: %s%n", e.getKey(), e.getValue());
181
e.getValue().printStackTrace(out);
182
e.getValue().printStackTrace();
183
});
184
if (tasksFailed) {
185
System.out.println("WARNING: Some tasks failed");
186
}
187
} finally {
188
out.println("\n=========================\n");
189
}
190
}
191
192
private String[] uris() {
193
return new String[] {
194
httpURI_fixed,
195
httpURI_chunk,
196
httpsURI_fixed,
197
httpsURI_chunk,
198
http2URI_fixed,
199
http2URI_chunk,
200
https2URI_fixed,
201
https2URI_chunk,
202
};
203
}
204
205
static AtomicLong URICOUNT = new AtomicLong();
206
207
@DataProvider(name = "sanity")
208
public Object[][] sanity() {
209
String[] uris = uris();
210
Object[][] result = new Object[uris.length * 2][];
211
int i = 0;
212
for (boolean sameClient : List.of(false, true)) {
213
for (String uri: uris()) {
214
result[i++] = new Object[] {uri, sameClient};
215
}
216
}
217
assert i == uris.length * 2;
218
return result;
219
}
220
221
@DataProvider(name = "variants")
222
public Object[][] variants(ITestContext context) {
223
if (stopAfterFirstFailure() && context.getFailedTests().size() > 0) {
224
return new Object[0][];
225
}
226
String[] uris = uris();
227
Object[][] result = new Object[uris.length * 2 * 2][];
228
int i = 0;
229
for (Thrower thrower : List.of(
230
new UncheckedIOExceptionThrower(),
231
new UncheckedCustomExceptionThrower())) {
232
for (boolean sameClient : List.of(false, true)) {
233
for (String uri : uris()) {
234
result[i++] = new Object[]{uri, sameClient, thrower};
235
}
236
}
237
}
238
assert i == uris.length * 2 * 2;
239
return result;
240
}
241
242
private HttpClient makeNewClient() {
243
clientCount.incrementAndGet();
244
HttpClient client = HttpClient.newBuilder()
245
.proxy(HttpClient.Builder.NO_PROXY)
246
.executor(executor)
247
.sslContext(sslContext)
248
.build();
249
return TRACKER.track(client);
250
}
251
252
HttpClient newHttpClient(boolean share) {
253
if (!share) return makeNewClient();
254
HttpClient shared = sharedClient;
255
if (shared != null) return shared;
256
synchronized (this) {
257
shared = sharedClient;
258
if (shared == null) {
259
shared = sharedClient = makeNewClient();
260
}
261
return shared;
262
}
263
}
264
265
enum SubscriberType {
266
INLINE, // In line subscribers complete their CF on ON_COMPLETE
267
// e.g. BodySubscribers::ofString
268
OFFLINE; // Off line subscribers complete their CF immediately
269
// but require the client to pull the data after the
270
// CF completes (e.g. BodySubscribers::ofInputStream)
271
}
272
273
static EnumSet<Where> excludes(SubscriberType type) {
274
EnumSet<Where> set = EnumSet.noneOf(Where.class);
275
276
if (type == SubscriberType.OFFLINE) {
277
// Throwing on onSubscribe needs some more work
278
// for the case of InputStream, where the body has already
279
// completed by the time the subscriber is subscribed.
280
// The only way we have at that point to relay the exception
281
// is to call onError on the subscriber, but should we if
282
// Subscriber::onSubscribed has thrown an exception and
283
// not completed normally?
284
set.add(Where.ON_SUBSCRIBE);
285
}
286
287
// Don't know how to make the stack reliably cause onError
288
// to be called without closing the connection.
289
// And how do we get the exception if onError throws anyway?
290
set.add(Where.ON_ERROR);
291
292
return set;
293
}
294
295
//@Test(dataProvider = "sanity")
296
protected void testSanityImpl(String uri, boolean sameClient)
297
throws Exception {
298
HttpClient client = null;
299
String uri2 = uri + "-" + URICOUNT.incrementAndGet() + "/sanity";
300
out.printf("%ntestSanity(%s, %b)%n", uri2, sameClient);
301
for (int i=0; i< ITERATION_COUNT; i++) {
302
if (!sameClient || client == null)
303
client = newHttpClient(sameClient);
304
305
HttpRequest req = HttpRequest.newBuilder(URI.create(uri2))
306
.build();
307
BodyHandler<String> handler =
308
new ThrowingBodyHandler((w) -> {},
309
BodyHandlers.ofString());
310
HttpResponse<String> response = client.send(req, handler);
311
String body = response.body();
312
assertEquals(URI.create(body).getPath(), URI.create(uri2).getPath());
313
}
314
}
315
316
//@Test(dataProvider = "variants")
317
protected void testThrowingAsStringImpl(String uri,
318
boolean sameClient,
319
Thrower thrower)
320
throws Exception
321
{
322
uri = uri + "-" + URICOUNT.incrementAndGet();
323
String test = format("testThrowingAsString(%s, %b, %s)",
324
uri, sameClient, thrower);
325
testThrowing(test, uri, sameClient, BodyHandlers::ofString,
326
this::shouldHaveThrown, thrower,false,
327
excludes(SubscriberType.INLINE));
328
}
329
330
//@Test(dataProvider = "variants")
331
protected void testThrowingAsLinesImpl(String uri,
332
boolean sameClient,
333
Thrower thrower)
334
throws Exception
335
{
336
uri = uri + "-" + URICOUNT.incrementAndGet();
337
String test = format("testThrowingAsLines(%s, %b, %s)",
338
uri, sameClient, thrower);
339
testThrowing(test, uri, sameClient, BodyHandlers::ofLines,
340
this::checkAsLines, thrower,false,
341
excludes(SubscriberType.OFFLINE));
342
}
343
344
//@Test(dataProvider = "variants")
345
protected void testThrowingAsInputStreamImpl(String uri,
346
boolean sameClient,
347
Thrower thrower)
348
throws Exception
349
{
350
uri = uri + "-" + URICOUNT.incrementAndGet();
351
String test = format("testThrowingAsInputStream(%s, %b, %s)",
352
uri, sameClient, thrower);
353
testThrowing(test, uri, sameClient, BodyHandlers::ofInputStream,
354
this::checkAsInputStream, thrower,false,
355
excludes(SubscriberType.OFFLINE));
356
}
357
358
//@Test(dataProvider = "variants")
359
protected void testThrowingAsStringAsyncImpl(String uri,
360
boolean sameClient,
361
Thrower thrower)
362
throws Exception
363
{
364
uri = uri + "-" + URICOUNT.incrementAndGet();
365
String test = format("testThrowingAsStringAsync(%s, %b, %s)",
366
uri, sameClient, thrower);
367
testThrowing(test, uri, sameClient, BodyHandlers::ofString,
368
this::shouldHaveThrown, thrower, true,
369
excludes(SubscriberType.INLINE));
370
}
371
372
//@Test(dataProvider = "variants")
373
protected void testThrowingAsLinesAsyncImpl(String uri,
374
boolean sameClient,
375
Thrower thrower)
376
throws Exception
377
{
378
uri = uri + "-" + URICOUNT.incrementAndGet();
379
String test = format("testThrowingAsLinesAsync(%s, %b, %s)",
380
uri, sameClient, thrower);
381
testThrowing(test, uri, sameClient, BodyHandlers::ofLines,
382
this::checkAsLines, thrower,true,
383
excludes(SubscriberType.OFFLINE));
384
}
385
386
//@Test(dataProvider = "variants")
387
protected void testThrowingAsInputStreamAsyncImpl(String uri,
388
boolean sameClient,
389
Thrower thrower)
390
throws Exception
391
{
392
uri = uri + "-" + URICOUNT.incrementAndGet();
393
String test = format("testThrowingAsInputStreamAsync(%s, %b, %s)",
394
uri, sameClient, thrower);
395
testThrowing(test, uri, sameClient, BodyHandlers::ofInputStream,
396
this::checkAsInputStream, thrower,true,
397
excludes(SubscriberType.OFFLINE));
398
}
399
400
private <T,U> void testThrowing(String name, String uri, boolean sameClient,
401
Supplier<BodyHandler<T>> handlers,
402
Finisher finisher, Thrower thrower,
403
boolean async, EnumSet<Where> excludes)
404
throws Exception
405
{
406
checkSkip();
407
out.printf("%n%s%s%n", now(), name);
408
try {
409
testThrowing(uri, sameClient, handlers, finisher, thrower, async, excludes);
410
} catch (Error | Exception x) {
411
FAILURES.putIfAbsent(name, x);
412
throw x;
413
}
414
}
415
416
private <T,U> void testThrowing(String uri, boolean sameClient,
417
Supplier<BodyHandler<T>> handlers,
418
Finisher finisher, Thrower thrower,
419
boolean async,
420
EnumSet<Where> excludes)
421
throws Exception
422
{
423
HttpClient client = null;
424
for (Where where : EnumSet.complementOf(excludes)) {
425
426
if (!sameClient || client == null)
427
client = newHttpClient(sameClient);
428
String uri2 = uri + "-" + where;
429
HttpRequest req = HttpRequest.
430
newBuilder(URI.create(uri2))
431
.build();
432
BodyHandler<T> handler =
433
new ThrowingBodyHandler(where.select(thrower), handlers.get());
434
System.out.println("try throwing in " + where);
435
HttpResponse<T> response = null;
436
if (async) {
437
try {
438
response = client.sendAsync(req, handler).join();
439
} catch (Error | Exception x) {
440
Throwable cause = findCause(x, thrower);
441
if (cause == null) throw causeNotFound(where, x);
442
System.out.println(now() + "Got expected exception: " + cause);
443
}
444
} else {
445
try {
446
response = client.send(req, handler);
447
} catch (Error | Exception t) {
448
// synchronous send will rethrow exceptions
449
Throwable throwable = t.getCause();
450
assert throwable != null;
451
452
if (thrower.test(throwable)) {
453
System.out.println(now() + "Got expected exception: " + throwable);
454
} else throw causeNotFound(where, t);
455
}
456
}
457
if (response != null) {
458
finisher.finish(where, response, thrower);
459
}
460
}
461
}
462
463
enum Where {
464
BODY_HANDLER, ON_SUBSCRIBE, ON_NEXT, ON_COMPLETE, ON_ERROR, GET_BODY, BODY_CF;
465
public Consumer<Where> select(Consumer<Where> consumer) {
466
return new Consumer<Where>() {
467
@Override
468
public void accept(Where where) {
469
if (Where.this == where) {
470
consumer.accept(where);
471
}
472
}
473
};
474
}
475
}
476
477
static AssertionError causeNotFound(Where w, Throwable t) {
478
return new AssertionError("Expected exception not found in " + w, t);
479
}
480
481
interface Thrower extends Consumer<Where>, Predicate<Throwable> {
482
483
}
484
485
interface Finisher<T,U> {
486
U finish(Where w, HttpResponse<T> resp, Thrower thrower) throws IOException;
487
}
488
489
final <T,U> U shouldHaveThrown(Where w, HttpResponse<T> resp, Thrower thrower) {
490
String msg = "Expected exception not thrown in " + w
491
+ "\n\tReceived: " + resp
492
+ "\n\tWith body: " + resp.body();
493
System.out.println(msg);
494
throw new RuntimeException(msg);
495
}
496
497
final List<String> checkAsLines(Where w, HttpResponse<Stream<String>> resp, Thrower thrower) {
498
switch(w) {
499
case BODY_HANDLER: return shouldHaveThrown(w, resp, thrower);
500
case GET_BODY: return shouldHaveThrown(w, resp, thrower);
501
case BODY_CF: return shouldHaveThrown(w, resp, thrower);
502
default: break;
503
}
504
List<String> result = null;
505
try {
506
result = resp.body().collect(Collectors.toList());
507
} catch (Error | Exception x) {
508
Throwable cause = findCause(x, thrower);
509
if (cause != null) {
510
out.println(now() + "Got expected exception in " + w + ": " + cause);
511
return result;
512
}
513
throw causeNotFound(w, x);
514
}
515
return shouldHaveThrown(w, resp, thrower);
516
}
517
518
final List<String> checkAsInputStream(Where w, HttpResponse<InputStream> resp,
519
Thrower thrower)
520
throws IOException
521
{
522
switch(w) {
523
case BODY_HANDLER: return shouldHaveThrown(w, resp, thrower);
524
case GET_BODY: return shouldHaveThrown(w, resp, thrower);
525
case BODY_CF: return shouldHaveThrown(w, resp, thrower);
526
default: break;
527
}
528
List<String> result = null;
529
try (InputStreamReader r1 = new InputStreamReader(resp.body(), UTF_8);
530
BufferedReader r = new BufferedReader(r1)) {
531
try {
532
result = r.lines().collect(Collectors.toList());
533
} catch (Error | Exception x) {
534
Throwable cause = findCause(x, thrower);
535
if (cause != null) {
536
out.println(now() + "Got expected exception in " + w + ": " + cause);
537
return result;
538
}
539
throw causeNotFound(w, x);
540
}
541
}
542
return shouldHaveThrown(w, resp, thrower);
543
}
544
545
private static Throwable findCause(Throwable x,
546
Predicate<Throwable> filter) {
547
while (x != null && !filter.test(x)) x = x.getCause();
548
return x;
549
}
550
551
static final class UncheckedCustomExceptionThrower implements Thrower {
552
@Override
553
public void accept(Where where) {
554
out.println(now() + "Throwing in " + where);
555
throw new UncheckedCustomException(where.name());
556
}
557
558
@Override
559
public boolean test(Throwable throwable) {
560
return UncheckedCustomException.class.isInstance(throwable);
561
}
562
563
@Override
564
public String toString() {
565
return "UncheckedCustomExceptionThrower";
566
}
567
}
568
569
static final class UncheckedIOExceptionThrower implements Thrower {
570
@Override
571
public void accept(Where where) {
572
out.println(now() + "Throwing in " + where);
573
throw new UncheckedIOException(new CustomIOException(where.name()));
574
}
575
576
@Override
577
public boolean test(Throwable throwable) {
578
return UncheckedIOException.class.isInstance(throwable)
579
&& CustomIOException.class.isInstance(throwable.getCause());
580
}
581
582
@Override
583
public String toString() {
584
return "UncheckedIOExceptionThrower";
585
}
586
}
587
588
static final class UncheckedCustomException extends RuntimeException {
589
UncheckedCustomException(String message) {
590
super(message);
591
}
592
UncheckedCustomException(String message, Throwable cause) {
593
super(message, cause);
594
}
595
}
596
597
static final class CustomIOException extends IOException {
598
CustomIOException(String message) {
599
super(message);
600
}
601
CustomIOException(String message, Throwable cause) {
602
super(message, cause);
603
}
604
}
605
606
static final class ThrowingBodyHandler<T> implements BodyHandler<T> {
607
final Consumer<Where> throwing;
608
final BodyHandler<T> bodyHandler;
609
ThrowingBodyHandler(Consumer<Where> throwing, BodyHandler<T> bodyHandler) {
610
this.throwing = throwing;
611
this.bodyHandler = bodyHandler;
612
}
613
@Override
614
public BodySubscriber<T> apply(HttpResponse.ResponseInfo rinfo) {
615
throwing.accept(Where.BODY_HANDLER);
616
BodySubscriber<T> subscriber = bodyHandler.apply(rinfo);
617
return new ThrowingBodySubscriber(throwing, subscriber);
618
}
619
}
620
621
static final class ThrowingBodySubscriber<T> implements BodySubscriber<T> {
622
private final BodySubscriber<T> subscriber;
623
volatile boolean onSubscribeCalled;
624
final Consumer<Where> throwing;
625
ThrowingBodySubscriber(Consumer<Where> throwing, BodySubscriber<T> subscriber) {
626
this.throwing = throwing;
627
this.subscriber = subscriber;
628
}
629
630
@Override
631
public void onSubscribe(Flow.Subscription subscription) {
632
//out.println("onSubscribe ");
633
onSubscribeCalled = true;
634
throwing.accept(Where.ON_SUBSCRIBE);
635
subscriber.onSubscribe(subscription);
636
}
637
638
@Override
639
public void onNext(List<ByteBuffer> item) {
640
// out.println("onNext " + item);
641
assertTrue(onSubscribeCalled);
642
throwing.accept(Where.ON_NEXT);
643
subscriber.onNext(item);
644
}
645
646
@Override
647
public void onError(Throwable throwable) {
648
//out.println("onError");
649
assertTrue(onSubscribeCalled);
650
throwing.accept(Where.ON_ERROR);
651
subscriber.onError(throwable);
652
}
653
654
@Override
655
public void onComplete() {
656
//out.println("onComplete");
657
assertTrue(onSubscribeCalled, "onComplete called before onSubscribe");
658
throwing.accept(Where.ON_COMPLETE);
659
subscriber.onComplete();
660
}
661
662
@Override
663
public CompletionStage<T> getBody() {
664
throwing.accept(Where.GET_BODY);
665
try {
666
throwing.accept(Where.BODY_CF);
667
} catch (Throwable t) {
668
return CompletableFuture.failedFuture(t);
669
}
670
return subscriber.getBody();
671
}
672
}
673
674
675
@BeforeTest
676
public void setup() throws Exception {
677
sslContext = new SimpleSSLContext().get();
678
if (sslContext == null)
679
throw new AssertionError("Unexpected null sslContext");
680
681
// HTTP/1.1
682
HttpTestHandler h1_fixedLengthHandler = new HTTP_FixedLengthHandler();
683
HttpTestHandler h1_chunkHandler = new HTTP_ChunkedHandler();
684
InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
685
httpTestServer = HttpTestServer.of(HttpServer.create(sa, 0));
686
httpTestServer.addHandler(h1_fixedLengthHandler, "/http1/fixed");
687
httpTestServer.addHandler(h1_chunkHandler, "/http1/chunk");
688
httpURI_fixed = "http://" + httpTestServer.serverAuthority() + "/http1/fixed/x";
689
httpURI_chunk = "http://" + httpTestServer.serverAuthority() + "/http1/chunk/x";
690
691
HttpsServer httpsServer = HttpsServer.create(sa, 0);
692
httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext));
693
httpsTestServer = HttpTestServer.of(httpsServer);
694
httpsTestServer.addHandler(h1_fixedLengthHandler, "/https1/fixed");
695
httpsTestServer.addHandler(h1_chunkHandler, "/https1/chunk");
696
httpsURI_fixed = "https://" + httpsTestServer.serverAuthority() + "/https1/fixed/x";
697
httpsURI_chunk = "https://" + httpsTestServer.serverAuthority() + "/https1/chunk/x";
698
699
// HTTP/2
700
HttpTestHandler h2_fixedLengthHandler = new HTTP_FixedLengthHandler();
701
HttpTestHandler h2_chunkedHandler = new HTTP_ChunkedHandler();
702
703
http2TestServer = HttpTestServer.of(new Http2TestServer("localhost", false, 0));
704
http2TestServer.addHandler(h2_fixedLengthHandler, "/http2/fixed");
705
http2TestServer.addHandler(h2_chunkedHandler, "/http2/chunk");
706
http2URI_fixed = "http://" + http2TestServer.serverAuthority() + "/http2/fixed/x";
707
http2URI_chunk = "http://" + http2TestServer.serverAuthority() + "/http2/chunk/x";
708
709
https2TestServer = HttpTestServer.of(new Http2TestServer("localhost", true, sslContext));
710
https2TestServer.addHandler(h2_fixedLengthHandler, "/https2/fixed");
711
https2TestServer.addHandler(h2_chunkedHandler, "/https2/chunk");
712
https2URI_fixed = "https://" + https2TestServer.serverAuthority() + "/https2/fixed/x";
713
https2URI_chunk = "https://" + https2TestServer.serverAuthority() + "/https2/chunk/x";
714
715
serverCount.addAndGet(4);
716
httpTestServer.start();
717
httpsTestServer.start();
718
http2TestServer.start();
719
https2TestServer.start();
720
}
721
722
@AfterTest
723
public void teardown() throws Exception {
724
String sharedClientName =
725
sharedClient == null ? null : sharedClient.toString();
726
sharedClient = null;
727
Thread.sleep(100);
728
AssertionError fail = TRACKER.check(500);
729
try {
730
httpTestServer.stop();
731
httpsTestServer.stop();
732
http2TestServer.stop();
733
https2TestServer.stop();
734
} finally {
735
if (fail != null) {
736
if (sharedClientName != null) {
737
System.err.println("Shared client name is: " + sharedClientName);
738
}
739
throw fail;
740
}
741
}
742
}
743
744
static class HTTP_FixedLengthHandler implements HttpTestHandler {
745
@Override
746
public void handle(HttpTestExchange t) throws IOException {
747
out.println("HTTP_FixedLengthHandler received request to " + t.getRequestURI());
748
try (InputStream is = t.getRequestBody()) {
749
is.readAllBytes();
750
}
751
byte[] resp = t.getRequestURI().toString().getBytes(StandardCharsets.UTF_8);
752
t.sendResponseHeaders(200, resp.length); //fixed content length
753
try (OutputStream os = t.getResponseBody()) {
754
os.write(resp);
755
}
756
}
757
}
758
759
static class HTTP_ChunkedHandler implements HttpTestHandler {
760
@Override
761
public void handle(HttpTestExchange t) throws IOException {
762
out.println("HTTP_ChunkedHandler received request to " + t.getRequestURI());
763
byte[] resp = t.getRequestURI().toString().getBytes(StandardCharsets.UTF_8);
764
try (InputStream is = t.getRequestBody()) {
765
is.readAllBytes();
766
}
767
t.sendResponseHeaders(200, -1); // chunked/variable
768
try (OutputStream os = t.getResponseBody()) {
769
os.write(resp);
770
}
771
}
772
}
773
774
}
775
776