59
59
import java .io .PipedInputStream ;
60
60
import java .io .PipedOutputStream ;
61
61
import java .net .InetSocketAddress ;
62
+ import java .net .ServerSocket ;
62
63
import java .net .Socket ;
63
64
import java .net .SocketAddress ;
64
65
import java .util .ArrayDeque ;
69
70
import java .util .concurrent .Executor ;
70
71
import java .util .concurrent .ExecutorService ;
71
72
import java .util .concurrent .Executors ;
73
+ import java .util .concurrent .Future ;
72
74
import java .util .concurrent .TimeUnit ;
73
75
import okio .Buffer ;
74
76
import okio .BufferedSource ;
@@ -96,14 +98,14 @@ public class OkHttpServerTransportTest {
96
98
private ServerTransportListener transportListener
97
99
= mock (ServerTransportListener .class , delegatesTo (mockTransportListener ));
98
100
private OkHttpServerTransport serverTransport ;
99
- private final PipeSocket socket = new PipeSocket ();
101
+ private final ExecutorService threadPool = Executors .newCachedThreadPool ();
102
+ private final SocketPair socketPair = SocketPair .create (threadPool );
100
103
private final FrameWriter clientFrameWriter
101
- = new Http2 ().newWriter (Okio .buffer (Okio .sink (socket . inputStreamSource )), true );
104
+ = new Http2 ().newWriter (Okio .buffer (Okio .sink (socketPair . getClientOutputStream () )), true );
102
105
private final FrameReader clientFrameReader
103
- = new Http2 ().newReader (Okio .buffer (Okio .source (socket . outputStreamSink )), true );
106
+ = new Http2 ().newReader (Okio .buffer (Okio .source (socketPair . getClientInputStream () )), true );
104
107
private final FrameReader .Handler clientFramesRead = mock (FrameReader .Handler .class );
105
108
private final DataFrameHandler clientDataFrames = mock (DataFrameHandler .class );
106
- private ExecutorService threadPool = Executors .newCachedThreadPool ();
107
109
private HandshakerSocketFactory handshakerSocketFactory
108
110
= mock (HandshakerSocketFactory .class , delegatesTo (new PlaintextHandshakerSocketFactory ()));
109
111
private final FakeClock fakeClock = new FakeClock ();
@@ -142,7 +144,11 @@ public void setUp() throws Exception {
142
144
@ After
143
145
public void tearDown () throws Exception {
144
146
threadPool .shutdownNow ();
145
- socket .closeSourceAndSink ();
147
+ try {
148
+ socketPair .client .close ();
149
+ } finally {
150
+ socketPair .server .close ();
151
+ }
146
152
}
147
153
148
154
@ Test
@@ -172,7 +178,7 @@ public void maxConnectionAge() throws Exception {
172
178
verifyGracefulShutdown (1 );
173
179
pingPong ();
174
180
fakeClock .forwardNanos (TimeUnit .SECONDS .toNanos (3 ));
175
- assertThat (socket .isClosed ()).isTrue ();
181
+ assertThat (socketPair . server .isClosed ()).isTrue ();
176
182
}
177
183
178
184
@ Test
@@ -254,7 +260,7 @@ public void startThenShutdownTwice() throws Exception {
254
260
@ Test
255
261
public void shutdownDuringHandshake () throws Exception {
256
262
doAnswer (invocation -> {
257
- socket .getInputStream ().read ();
263
+ (( Socket ) invocation . getArguments ()[ 0 ]) .getInputStream ().read ();
258
264
throw new IOException ("handshake purposefully failed" );
259
265
}).when (handshakerSocketFactory ).handshake (any (Socket .class ), any (Attributes .class ));
260
266
serverBuilder .transportExecutor (threadPool );
@@ -268,7 +274,7 @@ public void shutdownDuringHandshake() throws Exception {
268
274
@ Test
269
275
public void shutdownNowDuringHandshake () throws Exception {
270
276
doAnswer (invocation -> {
271
- socket .getInputStream ().read ();
277
+ (( Socket ) invocation . getArguments ()[ 0 ]) .getInputStream ().read ();
272
278
throw new IOException ("handshake purposefully failed" );
273
279
}).when (handshakerSocketFactory ).handshake (any (Socket .class ), any (Attributes .class ));
274
280
serverBuilder .transportExecutor (threadPool );
@@ -282,12 +288,12 @@ public void shutdownNowDuringHandshake() throws Exception {
282
288
@ Test
283
289
public void clientCloseDuringHandshake () throws Exception {
284
290
doAnswer (invocation -> {
285
- socket .getInputStream ().read ();
291
+ (( Socket ) invocation . getArguments ()[ 0 ]) .getInputStream ().read ();
286
292
throw new IOException ("handshake purposefully failed" );
287
293
}).when (handshakerSocketFactory ).handshake (any (Socket .class ), any (Attributes .class ));
288
294
serverBuilder .transportExecutor (threadPool );
289
295
initTransport ();
290
- socket .close ();
296
+ socketPair . client .close ();
291
297
292
298
verify (transportListener , timeout (TIME_OUT_MS )).transportTerminated ();
293
299
verify (transportListener , never ()).transportReady (any (Attributes .class ));
@@ -296,7 +302,7 @@ public void clientCloseDuringHandshake() throws Exception {
296
302
@ Test
297
303
public void closeDuringHttp2Preface () throws Exception {
298
304
initTransport ();
299
- socket .close ();
305
+ socketPair . client .close ();
300
306
301
307
verify (transportListener , timeout (TIME_OUT_MS )).transportTerminated ();
302
308
verify (transportListener , never ()).transportReady (any (Attributes .class ));
@@ -307,7 +313,7 @@ public void noSettingsDuringHttp2HandshakeSettings() throws Exception {
307
313
initTransport ();
308
314
clientFrameWriter .connectionPreface ();
309
315
clientFrameWriter .flush ();
310
- socket .close ();
316
+ socketPair . client .close ();
311
317
312
318
verify (transportListener , timeout (TIME_OUT_MS )).transportTerminated ();
313
319
verify (transportListener , never ()).transportReady (any (Attributes .class ));
@@ -329,7 +335,7 @@ public void startThenClientDisconnect() throws Exception {
329
335
initTransport ();
330
336
handshake ();
331
337
332
- socket . closeSourceAndSink ();
338
+ socketPair . client . close ();
333
339
verify (transportListener , timeout (TIME_OUT_MS )).transportTerminated ();
334
340
}
335
341
@@ -1086,8 +1092,8 @@ public void channelzStats() throws Exception {
1086
1092
assertThat (stats .data .messagesReceived ).isEqualTo (0 );
1087
1093
assertThat (stats .data .remoteFlowControlWindow ).isEqualTo (30000 ); // Lower bound
1088
1094
assertThat (stats .data .localFlowControlWindow ).isEqualTo (66535 );
1089
- assertThat (stats .local ).isEqualTo (new InetSocketAddress ( "127.0.0.1" , 4000 ));
1090
- assertThat (stats .remote ).isEqualTo (new InetSocketAddress ( "127.0.0.2" , 5000 ));
1095
+ assertThat (stats .local ).isEqualTo (socketPair . server . getLocalSocketAddress ( ));
1096
+ assertThat (stats .remote ).isEqualTo (socketPair . server . getRemoteSocketAddress ( ));
1091
1097
}
1092
1098
1093
1099
@ Test
@@ -1188,7 +1194,7 @@ public void keepAliveEnforcer_noticesActive() throws Exception {
1188
1194
private void initTransport () throws Exception {
1189
1195
serverTransport = new OkHttpServerTransport (
1190
1196
new OkHttpServerTransport .Config (serverBuilder , Arrays .asList ()),
1191
- socket );
1197
+ socketPair . server );
1192
1198
serverTransport .start (transportListener );
1193
1199
}
1194
1200
@@ -1357,61 +1363,44 @@ static String getContent(InputStream message) throws IOException {
1357
1363
}
1358
1364
}
1359
1365
1360
- private static class PipeSocket extends Socket {
1361
- private final PipedOutputStream outputStream = new PipedOutputStream ();
1362
- private final PipedInputStream outputStreamSink = new PipedInputStream ();
1363
- private final PipedOutputStream inputStreamSource = new PipedOutputStream ();
1364
- private final PipedInputStream inputStream = new PipedInputStream ();
1366
+ private static class SocketPair {
1367
+ public final Socket client ;
1368
+ public final Socket server ;
1369
+
1370
+ public SocketPair (Socket client , Socket server ) {
1371
+ this .client = client ;
1372
+ this .server = server ;
1373
+ }
1365
1374
1366
- public PipeSocket () {
1375
+ public InputStream getClientInputStream () {
1367
1376
try {
1368
- outputStreamSink .connect (outputStream );
1369
- inputStream .connect (inputStreamSource );
1377
+ return client .getInputStream ();
1370
1378
} catch (IOException ex ) {
1371
- throw new AssertionError (ex );
1379
+ throw new RuntimeException (ex );
1372
1380
}
1373
1381
}
1374
1382
1375
- @ Override
1376
- public synchronized void close () throws IOException {
1383
+ public OutputStream getClientOutputStream () {
1377
1384
try {
1378
- outputStream .close ();
1379
- } finally {
1380
- inputStream .close ();
1381
- // PipedInputStream can only be woken by PipedOutputStream, so PipedOutputStream.close() is
1382
- // a better imitation of Socket.close().
1383
- inputStreamSource .close ();
1384
- super .close ();
1385
+ return client .getOutputStream ();
1386
+ } catch (IOException ex ) {
1387
+ throw new RuntimeException (ex );
1385
1388
}
1386
1389
}
1387
1390
1388
- public void closeSourceAndSink () throws IOException {
1391
+ public static SocketPair create ( ExecutorService threadPool ) {
1389
1392
try {
1390
- outputStreamSink .close ();
1391
- } finally {
1392
- inputStreamSource .close ();
1393
+ try (ServerSocket serverSocket = new ServerSocket (0 )) {
1394
+ Future <Socket > serverFuture = threadPool .submit (() -> serverSocket .accept ());
1395
+ Socket client = new Socket ();
1396
+ client .connect (serverSocket .getLocalSocketAddress ());
1397
+ Socket server = serverFuture .get ();
1398
+ return new SocketPair (client , server );
1399
+ }
1400
+ } catch (Exception ex ) {
1401
+ throw new RuntimeException (ex );
1393
1402
}
1394
1403
}
1395
-
1396
- @ Override
1397
- public SocketAddress getLocalSocketAddress () {
1398
- return new InetSocketAddress ("127.0.0.1" , 4000 );
1399
- }
1400
-
1401
- @ Override
1402
- public SocketAddress getRemoteSocketAddress () {
1403
- return new InetSocketAddress ("127.0.0.2" , 5000 );
1404
- }
1405
-
1406
- @ Override
1407
- public OutputStream getOutputStream () {
1408
- return outputStream ;
1409
- }
1410
-
1411
- @ Override
1412
- public InputStream getInputStream () {
1413
- return inputStream ;
1414
- }
1415
1404
}
1416
1405
1417
1406
private interface DataFrameHandler {
0 commit comments