15
15
16
16
package io .netty .handler .codec .http2 ;
17
17
18
- import static io .netty .buffer .Unpooled .EMPTY_BUFFER ;
19
- import static io .netty .handler .codec .http2 .Http2CodecUtil .DEFAULT_MAX_FRAME_SIZE ;
20
- import static io .netty .handler .codec .http2 .Http2CodecUtil .DEFAULT_PRIORITY_WEIGHT ;
21
- import static io .netty .handler .codec .http2 .Http2CodecUtil .SMALLEST_MAX_CONCURRENT_STREAMS ;
22
- import static io .netty .handler .codec .http2 .Http2Error .CANCEL ;
23
- import static io .netty .handler .codec .http2 .Http2Stream .State .HALF_CLOSED_LOCAL ;
24
- import static org .junit .jupiter .api .Assertions .assertEquals ;
25
- import static org .junit .jupiter .api .Assertions .assertFalse ;
26
- import static org .junit .jupiter .api .Assertions .assertNotNull ;
27
- import static org .junit .jupiter .api .Assertions .assertNull ;
28
- import static org .junit .jupiter .api .Assertions .assertTrue ;
29
- import static org .mockito .Mockito .any ;
30
- import static org .mockito .Mockito .anyBoolean ;
31
- import static org .mockito .Mockito .anyInt ;
32
- import static org .mockito .Mockito .anyLong ;
33
- import static org .mockito .Mockito .anyShort ;
34
- import static org .mockito .Mockito .eq ;
35
- import static org .mockito .Mockito .doAnswer ;
36
- import static org .mockito .Mockito .mock ;
37
- import static org .mockito .Mockito .never ;
38
- import static org .mockito .Mockito .times ;
39
- import static org .mockito .Mockito .verify ;
40
- import static org .mockito .Mockito .when ;
41
-
42
18
import io .netty .buffer .ByteBuf ;
43
19
import io .netty .buffer .Unpooled ;
44
20
import io .netty .buffer .UnpooledByteBufAllocator ;
57
33
import org .junit .jupiter .api .AfterEach ;
58
34
import org .junit .jupiter .api .BeforeEach ;
59
35
import org .junit .jupiter .api .Test ;
36
+ import org .junit .jupiter .params .ParameterizedTest ;
37
+ import org .junit .jupiter .params .provider .ValueSource ;
60
38
import org .mockito .ArgumentCaptor ;
61
39
import org .mockito .Mock ;
62
40
import org .mockito .MockitoAnnotations ;
67
45
import java .util .ArrayList ;
68
46
import java .util .List ;
69
47
48
+ import static io .netty .buffer .Unpooled .EMPTY_BUFFER ;
49
+ import static io .netty .handler .codec .http2 .Http2CodecUtil .DEFAULT_MAX_FRAME_SIZE ;
50
+ import static io .netty .handler .codec .http2 .Http2CodecUtil .DEFAULT_PRIORITY_WEIGHT ;
51
+ import static io .netty .handler .codec .http2 .Http2CodecUtil .SMALLEST_MAX_CONCURRENT_STREAMS ;
52
+ import static io .netty .handler .codec .http2 .Http2Error .CANCEL ;
53
+ import static io .netty .handler .codec .http2 .Http2PromisedRequestVerifier .ALWAYS_VERIFY ;
54
+ import static io .netty .handler .codec .http2 .Http2Stream .State .HALF_CLOSED_LOCAL ;
55
+ import static org .junit .jupiter .api .Assertions .assertEquals ;
56
+ import static org .junit .jupiter .api .Assertions .assertFalse ;
57
+ import static org .junit .jupiter .api .Assertions .assertInstanceOf ;
58
+ import static org .junit .jupiter .api .Assertions .assertNotNull ;
59
+ import static org .junit .jupiter .api .Assertions .assertNull ;
60
+ import static org .junit .jupiter .api .Assertions .assertTrue ;
61
+ import static org .mockito .Mockito .any ;
62
+ import static org .mockito .Mockito .anyBoolean ;
63
+ import static org .mockito .Mockito .anyInt ;
64
+ import static org .mockito .Mockito .anyLong ;
65
+ import static org .mockito .Mockito .anyShort ;
66
+ import static org .mockito .Mockito .doAnswer ;
67
+ import static org .mockito .Mockito .eq ;
68
+ import static org .mockito .Mockito .mock ;
69
+ import static org .mockito .Mockito .never ;
70
+ import static org .mockito .Mockito .times ;
71
+ import static org .mockito .Mockito .verify ;
72
+ import static org .mockito .Mockito .when ;
73
+
70
74
/**
71
75
* Tests for {@link StreamBufferingEncoder}.
72
76
*/
@@ -126,8 +130,8 @@ public void setup() throws Exception {
126
130
DefaultHttp2ConnectionEncoder defaultEncoder =
127
131
new DefaultHttp2ConnectionEncoder (connection , writer );
128
132
encoder = new StreamBufferingEncoder (defaultEncoder );
129
- DefaultHttp2ConnectionDecoder decoder =
130
- new DefaultHttp2ConnectionDecoder ( connection , encoder , mock (Http2FrameReader .class ));
133
+ DefaultHttp2ConnectionDecoder decoder = new DefaultHttp2ConnectionDecoder (
134
+ connection , encoder , mock (Http2FrameReader .class ), ALWAYS_VERIFY , false );
131
135
Http2ConnectionHandler handler = new Http2ConnectionHandlerBuilder ()
132
136
.frameListener (mock (Http2FrameListener .class ))
133
137
.codec (decoder , encoder ).build ();
@@ -184,7 +188,6 @@ public void multipleWritesToActiveStream() {
184
188
185
189
@ Test
186
190
public void ensureCanCreateNextStreamWhenStreamCloses () {
187
- encoder .writeSettingsAck (ctx , newPromise ());
188
191
setMaxConcurrentStreams (1 );
189
192
190
193
encoderWriteHeaders (3 , newPromise ());
@@ -209,10 +212,10 @@ public void ensureCanCreateNextStreamWhenStreamCloses() {
209
212
assertEquals (1 , encoder .numBufferedStreams ());
210
213
}
211
214
212
- @ Test
213
- public void alternatingWritesToActiveAndBufferedStreams () {
214
- encoder . writeSettingsAck ( ctx , newPromise ());
215
- setMaxConcurrentStreams (1 );
215
+ @ ParameterizedTest ( name = "{displayName} [{index}]: autoAckSettings={0}" )
216
+ @ ValueSource ( booleans = { true , false })
217
+ public void alternatingWritesToActiveAndBufferedStreams ( boolean autoAckSettings ) {
218
+ setMaxConcurrentStreams (autoAckSettings , 1 );
216
219
217
220
encoderWriteHeaders (3 , newPromise ());
218
221
assertEquals (0 , encoder .numBufferedStreams ());
@@ -230,7 +233,6 @@ public void alternatingWritesToActiveAndBufferedStreams() {
230
233
231
234
@ Test
232
235
public void bufferingNewStreamFailsAfterGoAwayReceived () throws Http2Exception {
233
- encoder .writeSettingsAck (ctx , newPromise ());
234
236
setMaxConcurrentStreams (0 );
235
237
connection .goAwayReceived (1 , 8 , EMPTY_BUFFER );
236
238
@@ -243,7 +245,6 @@ public void bufferingNewStreamFailsAfterGoAwayReceived() throws Http2Exception {
243
245
244
246
@ Test
245
247
public void receivingGoAwayFailsBufferedStreams () throws Http2Exception {
246
- encoder .writeSettingsAck (ctx , newPromise ());
247
248
setMaxConcurrentStreams (5 );
248
249
249
250
int streamId = 3 ;
@@ -271,19 +272,17 @@ public void receivingGoAwayFailsBufferedStreams() throws Http2Exception {
271
272
272
273
@ Test
273
274
public void receivingGoAwayFailsNewStreamIfMaxConcurrentStreamsReached () throws Http2Exception {
274
- encoder .writeSettingsAck (ctx , newPromise ());
275
275
setMaxConcurrentStreams (1 );
276
276
encoderWriteHeaders (3 , newPromise ());
277
277
connection .goAwayReceived (11 , 8 , EMPTY_BUFFER );
278
278
ChannelFuture f = encoderWriteHeaders (5 , newPromise ());
279
279
280
- assertTrue ( f .cause () instanceof Http2GoAwayException );
280
+ assertInstanceOf ( Http2GoAwayException . class , f .cause ());
281
281
assertEquals (0 , encoder .numBufferedStreams ());
282
282
}
283
283
284
284
@ Test
285
285
public void sendingGoAwayShouldNotFailStreams () {
286
- encoder .writeSettingsAck (ctx , newPromise ());
287
286
setMaxConcurrentStreams (1 );
288
287
289
288
when (writer .writeHeaders (any (ChannelHandlerContext .class ), anyInt (), any (Http2Headers .class ), anyInt (),
@@ -308,10 +307,10 @@ public void sendingGoAwayShouldNotFailStreams() {
308
307
assertFalse (f3 .isDone ());
309
308
}
310
309
311
- @ Test
312
- public void endStreamDoesNotFailBufferedStream () {
313
- encoder . writeSettingsAck ( ctx , newPromise ());
314
- setMaxConcurrentStreams (0 );
310
+ @ ParameterizedTest ( name = "{displayName} [{index}]: autoAckSettings={0}" )
311
+ @ ValueSource ( booleans = { true , false })
312
+ public void endStreamDoesNotFailBufferedStream ( boolean autoAckSettings ) {
313
+ setMaxConcurrentStreams (autoAckSettings , 0 );
315
314
316
315
encoderWriteHeaders (3 , newPromise ());
317
316
assertEquals (1 , encoder .numBufferedStreams ());
@@ -323,8 +322,7 @@ public void endStreamDoesNotFailBufferedStream() {
323
322
324
323
// Simulate that we received a SETTINGS frame which
325
324
// increased MAX_CONCURRENT_STREAMS to 1.
326
- setMaxConcurrentStreams (1 );
327
- encoder .writeSettingsAck (ctx , newPromise ());
325
+ setMaxConcurrentStreams (autoAckSettings , 1 );
328
326
329
327
assertEquals (1 , connection .numActiveStreams ());
330
328
assertEquals (0 , encoder .numBufferedStreams ());
@@ -333,7 +331,6 @@ public void endStreamDoesNotFailBufferedStream() {
333
331
334
332
@ Test
335
333
public void rstStreamClosesBufferedStream () {
336
- encoder .writeSettingsAck (ctx , newPromise ());
337
334
setMaxConcurrentStreams (0 );
338
335
339
336
encoderWriteHeaders (3 , newPromise ());
@@ -345,10 +342,10 @@ public void rstStreamClosesBufferedStream() {
345
342
assertEquals (0 , encoder .numBufferedStreams ());
346
343
}
347
344
348
- @ Test
349
- public void bufferUntilActiveStreamsAreReset () throws Exception {
350
- encoder . writeSettingsAck ( ctx , newPromise ());
351
- setMaxConcurrentStreams (1 );
345
+ @ ParameterizedTest ( name = "{displayName} [{index}]: autoAckSettings={0}" )
346
+ @ ValueSource ( booleans = { true , false })
347
+ public void bufferUntilActiveStreamsAreReset ( boolean autoAckSettings ) throws Exception {
348
+ setMaxConcurrentStreams (autoAckSettings , 1 );
352
349
353
350
encoderWriteHeaders (3 , newPromise ());
354
351
assertEquals (0 , encoder .numBufferedStreams ());
@@ -379,10 +376,10 @@ public void bufferUntilActiveStreamsAreReset() throws Exception {
379
376
assertEquals (0 , encoder .numBufferedStreams ());
380
377
}
381
378
382
- @ Test
383
- public void bufferUntilMaxStreamsIncreased () {
384
- encoder . writeSettingsAck ( ctx , newPromise ());
385
- setMaxConcurrentStreams (2 );
379
+ @ ParameterizedTest ( name = "{displayName} [{index}]: autoAckSettings={0}" )
380
+ @ ValueSource ( booleans = { true , false })
381
+ public void bufferUntilMaxStreamsIncreased ( boolean autoAckSettings ) {
382
+ setMaxConcurrentStreams (autoAckSettings , 2 );
386
383
387
384
encoderWriteHeaders (3 , newPromise ());
388
385
encoderWriteHeaders (5 , newPromise ());
@@ -397,8 +394,7 @@ public void bufferUntilMaxStreamsIncreased() {
397
394
398
395
// Simulate that we received a SETTINGS frame which
399
396
// increased MAX_CONCURRENT_STREAMS to 5.
400
- setMaxConcurrentStreams (5 );
401
- encoder .writeSettingsAck (ctx , newPromise ());
397
+ setMaxConcurrentStreams (autoAckSettings , 5 );
402
398
403
399
assertEquals (0 , encoder .numBufferedStreams ());
404
400
writeVerifyWriteHeaders (times (1 ), 7 );
@@ -411,8 +407,9 @@ public void bufferUntilMaxStreamsIncreased() {
411
407
assertEquals (5 , connection .local ().numActiveStreams ());
412
408
}
413
409
414
- @ Test
415
- public void bufferUntilSettingsReceived () throws Http2Exception {
410
+ @ ParameterizedTest (name = "{displayName} [{index}]: autoAckSettings={0}" )
411
+ @ ValueSource (booleans = {true , false })
412
+ public void bufferUntilSettingsReceived (boolean autoAckSettings ) {
416
413
int initialLimit = SMALLEST_MAX_CONCURRENT_STREAMS ;
417
414
int numStreams = initialLimit * 2 ;
418
415
for (int ix = 0 , nextStreamId = 3 ; ix < numStreams ; ++ix , nextStreamId += 2 ) {
@@ -426,7 +423,7 @@ public void bufferUntilSettingsReceived() throws Http2Exception {
426
423
assertEquals (numStreams / 2 , encoder .numBufferedStreams ());
427
424
428
425
// Simulate that we received a SETTINGS frame.
429
- setMaxConcurrentStreams (initialLimit * 2 );
426
+ setMaxConcurrentStreams (autoAckSettings , initialLimit * 2 );
430
427
431
428
assertEquals (0 , encoder .numBufferedStreams ());
432
429
assertEquals (numStreams , connection .local ().numActiveStreams ());
@@ -471,7 +468,6 @@ public void exhaustedStreamsDoNotBuffer() throws Http2Exception {
471
468
472
469
@ Test
473
470
public void closedBufferedStreamReleasesByteBuf () {
474
- encoder .writeSettingsAck (ctx , newPromise ());
475
471
setMaxConcurrentStreams (0 );
476
472
ByteBuf data = mock (ByteBuf .class );
477
473
ChannelFuture f1 = encoderWriteHeaders (3 , newPromise ());
@@ -525,8 +521,20 @@ private void testStreamId(int nextStreamId) throws Http2Exception {
525
521
}
526
522
527
523
private void setMaxConcurrentStreams (int newValue ) {
524
+ setMaxConcurrentStreams (true , newValue );
525
+ }
526
+
527
+ private void setMaxConcurrentStreams (boolean autoAckSettings , int newValue ) {
528
528
try {
529
- encoder .remoteSettings (new Http2Settings ().maxConcurrentStreams (newValue ));
529
+ Http2Settings settings = new Http2Settings ().maxConcurrentStreams (newValue );
530
+ // Mimic behavior of DefaultHttp2ConnectionDecoder.onSettingsRead:
531
+ if (autoAckSettings ) {
532
+ encoder .writeSettingsAck (ctx , newPromise ());
533
+ encoder .remoteSettings (settings );
534
+ } else {
535
+ encoder .consumeReceivedSettings (settings );
536
+ encoder .writeSettingsAck (ctx , newPromise ());
537
+ }
530
538
// Flush the remote flow controller to write data
531
539
encoder .flowController ().writePendingBytes ();
532
540
} catch (Http2Exception e ) {
0 commit comments