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