42
42
import java .io .InputStream ;
43
43
import java .io .OutputStream ;
44
44
import java .io .UncheckedIOException ;
45
- import java .net .InetAddress ;
46
- import java .net .InetSocketAddress ;
47
45
import java .net .URI ;
48
46
import java .net .http .HttpClient ;
49
47
import java .net .http .HttpClient .Redirect ;
62
60
import java .util .concurrent .ExecutionException ;
63
61
import java .util .concurrent .ExecutorService ;
64
62
import java .util .concurrent .Executors ;
65
- import java .util .concurrent .RejectedExecutionException ;
66
63
import java .util .concurrent .TimeUnit ;
67
64
import java .util .concurrent .atomic .AtomicLong ;
68
- import java .util .function .Function ;
69
65
import jdk .httpclient .test .lib .common .HttpServerAdapters ;
70
- import jdk .httpclient .test .lib .http2 .Http2TestServer ;
71
66
import javax .net .ssl .SSLContext ;
72
- import javax .net .ssl .SSLHandshakeException ;
73
67
74
- import com .sun .net .httpserver .HttpServer ;
75
- import com .sun .net .httpserver .HttpsConfigurator ;
76
- import com .sun .net .httpserver .HttpsServer ;
77
68
import jdk .test .lib .RandomFactory ;
78
69
import jdk .test .lib .net .SimpleSSLContext ;
79
70
import org .testng .annotations .AfterTest ;
@@ -99,6 +90,7 @@ public class AsyncShutdownNow implements HttpServerAdapters {
99
90
}
100
91
static final Random RANDOM = RandomFactory .getRandom ();
101
92
93
+ ExecutorService readerService ;
102
94
SSLContext sslContext ;
103
95
HttpTestServer httpTestServer ; // HTTP/1.1 [ 4 servers ]
104
96
HttpTestServer httpsTestServer ; // HTTPS/1.1
@@ -123,7 +115,7 @@ public Object[][] positive() {
123
115
}
124
116
125
117
static final AtomicLong requestCounter = new AtomicLong ();
126
- final ReferenceTracker TRACKER = ReferenceTracker .INSTANCE ;
118
+ static final ReferenceTracker TRACKER = ReferenceTracker .INSTANCE ;
127
119
128
120
static Throwable getCause (Throwable t ) {
129
121
while (t instanceof CompletionException || t instanceof ExecutionException ) {
@@ -175,8 +167,7 @@ static void checkCause(String what, Throwable cause) {
175
167
176
168
@ Test (dataProvider = "positive" )
177
169
void testConcurrent (String uriString ) throws Exception {
178
- out .printf ("%n---- starting (%s) ----%n" , uriString );
179
- ExecutorService readerService = Executors .newCachedThreadPool ();
170
+ out .printf ("%n---- starting concurrent (%s) ----%n%n" , uriString );
180
171
HttpClient client = HttpClient .newBuilder ()
181
172
.proxy (NO_PROXY )
182
173
.followRedirects (Redirect .ALWAYS )
@@ -186,8 +177,8 @@ void testConcurrent(String uriString) throws Exception {
186
177
187
178
int step = RANDOM .nextInt (ITERATIONS );
188
179
Throwable failed = null ;
180
+ List <CompletableFuture <String >> bodies = new ArrayList <>();
189
181
try {
190
- List <CompletableFuture <String >> bodies = new ArrayList <>();
191
182
for (int i = 0 ; i < ITERATIONS ; i ++) {
192
183
URI uri = URI .create (uriString + "/concurrent/iteration-" + i );
193
184
HttpRequest request = HttpRequest .newBuilder (uri )
@@ -232,31 +223,31 @@ void testConcurrent(String uriString) throws Exception {
232
223
});
233
224
bodies .add (cf );
234
225
}
235
- CompletableFuture .allOf (bodies .toArray (new CompletableFuture <?>[0 ])).get ();
236
226
} catch (Throwable throwable ) {
237
227
failed = throwable ;
238
228
} finally {
239
- failed = cleanup (client , readerService , failed );
229
+ failed = cleanup (client , failed );
240
230
}
241
231
if (failed instanceof Exception ex ) throw ex ;
242
232
if (failed instanceof Error e ) throw e ;
243
233
assertTrue (client .isTerminated ());
234
+ // ensure that all operations are eventually terminated
235
+ CompletableFuture .allOf (bodies .toArray (new CompletableFuture <?>[0 ])).get ();
244
236
}
245
237
246
- static Throwable cleanup (HttpClient client , ExecutorService readerService , Throwable failed ) {
238
+ static Throwable cleanup (HttpClient client , Throwable failed ) {
247
239
try {
248
- try {
249
- if (client .awaitTermination (Duration .ofMillis (2000 ))) {
250
- out .println ("Client terminated within expected delay" );
251
- } else {
252
- AssertionError error = new AssertionError ("client still running" );
253
- if (failed != null ) {
254
- failed .addSuppressed (error );
255
- } else failed = error ;
256
- }
257
- } finally {
258
- readerService .shutdown ();
259
- readerService .awaitTermination (2000 , TimeUnit .MILLISECONDS );
240
+ if (client .awaitTermination (Duration .ofMillis (2000 ))) {
241
+ out .println ("Client terminated within expected delay" );
242
+ } else {
243
+ String msg = "Client %s still running: %s" .formatted (
244
+ client ,
245
+ TRACKER .diagnose (client ));
246
+ out .println (msg );
247
+ AssertionError error = new AssertionError (msg );
248
+ if (failed != null ) {
249
+ failed .addSuppressed (error );
250
+ } else failed = error ;
260
251
}
261
252
} catch (InterruptedException ie ) {
262
253
if (failed != null ) {
@@ -268,8 +259,7 @@ static Throwable cleanup(HttpClient client, ExecutorService readerService, Throw
268
259
269
260
@ Test (dataProvider = "positive" )
270
261
void testSequential (String uriString ) throws Exception {
271
- out .printf ("%n---- starting (%s) ----%n" , uriString );
272
- ExecutorService readerService = Executors .newCachedThreadPool ();
262
+ out .printf ("%n---- starting sequential (%s) ----%n%n" , uriString );
273
263
HttpClient client = HttpClient .newBuilder ()
274
264
.proxy (NO_PROXY )
275
265
.followRedirects (Redirect .ALWAYS )
@@ -339,7 +329,7 @@ void testSequential(String uriString) throws Exception {
339
329
} catch (Throwable throwable ) {
340
330
failed = throwable ;
341
331
} finally {
342
- failed = cleanup (client , readerService , failed );
332
+ failed = cleanup (client , failed );
343
333
}
344
334
if (failed instanceof Exception ex ) throw ex ;
345
335
if (failed instanceof Error e ) throw e ;
@@ -354,6 +344,7 @@ public void setup() throws Exception {
354
344
sslContext = new SimpleSSLContext ().get ();
355
345
if (sslContext == null )
356
346
throw new AssertionError ("Unexpected null sslContext" );
347
+ readerService = Executors .newCachedThreadPool ();
357
348
358
349
httpTestServer = HttpTestServer .create (HTTP_1_1 );
359
350
httpTestServer .addHandler (new ServerRequestHandler (), "/http1/exec/" );
@@ -380,6 +371,7 @@ public void teardown() throws Exception {
380
371
Thread .sleep (100 );
381
372
AssertionError fail = TRACKER .checkShutdown (5000 );
382
373
try {
374
+ shutdown (readerService );
383
375
httpTestServer .stop ();
384
376
httpsTestServer .stop ();
385
377
http2TestServer .stop ();
@@ -389,6 +381,15 @@ public void teardown() throws Exception {
389
381
}
390
382
}
391
383
384
+ static void shutdown (ExecutorService executorService ) {
385
+ try {
386
+ executorService .shutdown ();
387
+ executorService .awaitTermination (2000 , TimeUnit .MILLISECONDS );
388
+ } catch (InterruptedException ie ) {
389
+ executorService .shutdownNow ();
390
+ }
391
+ }
392
+
392
393
static class ServerRequestHandler implements HttpTestHandler {
393
394
ConcurrentHashMap <String ,String > closedRequests = new ConcurrentHashMap <>();
394
395
0 commit comments