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