http-2 0.10.2 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -2
  3. data/lib/http/2/buffer.rb +6 -4
  4. data/lib/http/2/client.rb +5 -1
  5. data/lib/http/2/compressor.rb +44 -36
  6. data/lib/http/2/connection.rb +76 -89
  7. data/lib/http/2/emitter.rb +4 -1
  8. data/lib/http/2/error.rb +2 -0
  9. data/lib/http/2/flow_buffer.rb +8 -3
  10. data/lib/http/2/framer.rb +83 -94
  11. data/lib/http/2/huffman.rb +19 -17
  12. data/lib/http/2/server.rb +9 -7
  13. data/lib/http/2/stream.rb +48 -48
  14. data/lib/http/2/version.rb +3 -1
  15. data/lib/http/2.rb +2 -0
  16. metadata +10 -63
  17. data/.autotest +0 -20
  18. data/.coveralls.yml +0 -1
  19. data/.gitignore +0 -20
  20. data/.gitmodules +0 -3
  21. data/.rspec +0 -5
  22. data/.rubocop.yml +0 -93
  23. data/.rubocop_todo.yml +0 -122
  24. data/.travis.yml +0 -14
  25. data/Gemfile +0 -16
  26. data/Guardfile +0 -18
  27. data/Guardfile.h2spec +0 -12
  28. data/Rakefile +0 -49
  29. data/example/Gemfile +0 -3
  30. data/example/README.md +0 -44
  31. data/example/client.rb +0 -122
  32. data/example/helper.rb +0 -19
  33. data/example/keys/server.crt +0 -20
  34. data/example/keys/server.key +0 -27
  35. data/example/server.rb +0 -139
  36. data/example/upgrade_client.rb +0 -153
  37. data/example/upgrade_server.rb +0 -203
  38. data/http-2.gemspec +0 -22
  39. data/lib/tasks/generate_huffman_table.rb +0 -166
  40. data/spec/buffer_spec.rb +0 -28
  41. data/spec/client_spec.rb +0 -188
  42. data/spec/compressor_spec.rb +0 -666
  43. data/spec/connection_spec.rb +0 -665
  44. data/spec/emitter_spec.rb +0 -54
  45. data/spec/framer_spec.rb +0 -487
  46. data/spec/h2spec/h2spec.darwin +0 -0
  47. data/spec/h2spec/output/non_secure.txt +0 -317
  48. data/spec/helper.rb +0 -147
  49. data/spec/hpack_test_spec.rb +0 -84
  50. data/spec/huffman_spec.rb +0 -68
  51. data/spec/server_spec.rb +0 -52
  52. data/spec/stream_spec.rb +0 -878
  53. data/spec/support/deep_dup.rb +0 -55
  54. data/spec/support/duplicable.rb +0 -98
data/spec/stream_spec.rb DELETED
@@ -1,878 +0,0 @@
1
- require 'helper'
2
-
3
- RSpec.describe HTTP2::Stream do
4
- include FrameHelpers
5
- before(:each) do
6
- @client = Client.new
7
- @stream = @client.new_stream
8
- end
9
-
10
- context 'stream states' do
11
- it 'should initiliaze all streams to IDLE' do
12
- expect(@stream.state).to eq :idle
13
- end
14
-
15
- it 'should set custom stream priority' do
16
- stream = @client.new_stream(weight: 3, dependency: 2, exclusive: true)
17
- expect(stream.weight).to eq 3
18
- end
19
-
20
- context 'idle' do
21
- it 'should transition to open on sent HEADERS' do
22
- @stream.send headers_frame
23
- expect(@stream.state).to eq :open
24
- end
25
- it 'should transition to open on received HEADERS' do
26
- @stream.receive headers_frame
27
- expect(@stream.state).to eq :open
28
- end
29
- it 'should transition to reserved (local) on sent PUSH_PROMISE' do
30
- @stream.send push_promise_frame
31
- expect(@stream.state).to eq :reserved_local
32
- end
33
- it 'should transition to reserved (remote) on received PUSH_PROMISE' do
34
- @stream.receive push_promise_frame
35
- expect(@stream.state).to eq :reserved_remote
36
- end
37
- it 'should reprioritize stream on sent PRIORITY' do
38
- expect { @stream.send priority_frame }.to_not raise_error
39
- expect(@stream.weight).to eq 20
40
- end
41
- it 'should reprioritize stream on received PRIORITY' do
42
- expect { @stream.send priority_frame }.to_not raise_error
43
- expect(@stream.weight).to eq 20
44
- end
45
- end
46
-
47
- context 'reserved (local)' do
48
- before(:each) { @stream.send push_promise_frame }
49
-
50
- it 'should transition on sent PUSH_PROMISE' do
51
- expect(@stream.state).to eq :reserved_local
52
- end
53
-
54
- it 'should allow HEADERS to be sent' do
55
- expect { @stream.send headers_frame }.to_not raise_error
56
- end
57
-
58
- it 'should raise error if sending invalid frames' do
59
- frame_types.reject { |frame| %i[headers rst_stream].include?(frame[:type]) }.each do |type|
60
- expect { @stream.dup.send type }.to raise_error InternalError
61
- end
62
- end
63
-
64
- it 'should raise error on receipt of invalid frames' do
65
- what_types = frame_types.reject { |frame| %i[priority window_update rst_stream].include?(frame[:type]) }
66
- what_types.each do |type|
67
- expect { @stream.dup.receive type }.to raise_error InternalError
68
- end
69
- end
70
-
71
- it 'should transition to half closed (remote) on sent HEADERS' do
72
- @stream.send headers_frame
73
- expect(@stream.state).to eq :half_closed_remote
74
- end
75
-
76
- it 'should transition to closed on sent RST_STREAM' do
77
- @stream.close
78
- expect(@stream.state).to eq :closed
79
- end
80
-
81
- it 'should transition to closed on received RST_STREAM' do
82
- @stream.receive rst_stream_frame
83
- expect(@stream.state).to eq :closed
84
- end
85
-
86
- it 'should reprioritize stream on PRIORITY' do
87
- expect { @stream.receive priority_frame }.to_not raise_error
88
- expect(@stream.weight).to eq 20
89
- end
90
-
91
- it 'should increment remote_window on received WINDOW_UPDATE' do
92
- expect { @stream.receive window_update_frame }.to_not raise_error
93
- expect(@stream.remote_window).to eq DEFAULT_FLOW_WINDOW + window_update_frame[:increment]
94
- end
95
- end
96
-
97
- context 'reserved (remote)' do
98
- before(:each) { @stream.receive push_promise_frame }
99
-
100
- it 'should transition on received PUSH_PROMISE' do
101
- expect(@stream.state).to eq :reserved_remote
102
- end
103
-
104
- it 'should raise error if sending invalid frames' do
105
- frame_types.reject { |frame| %i[priority rst_stream window_update].include?(frame[:type]) }.each do |type|
106
- expect { @stream.dup.send type }.to raise_error InternalError
107
- end
108
- end
109
-
110
- it 'should raise error on receipt of invalid frames' do
111
- frame_types.reject { |frame| %i[headers rst_stream].include?(frame[:type]) }.each do |type|
112
- expect { @stream.dup.receive type }.to raise_error InternalError
113
- end
114
- end
115
-
116
- it 'should transition to half closed (local) on received HEADERS' do
117
- @stream.receive headers_frame
118
- expect(@stream.state).to eq :half_closed_local
119
- end
120
-
121
- it 'should transition to closed on sent RST_STREAM' do
122
- @stream.close
123
- expect(@stream.state).to eq :closed
124
- end
125
-
126
- it 'should transition to closed on received RST_STREAM' do
127
- @stream.receive rst_stream_frame
128
- expect(@stream.state).to eq :closed
129
- end
130
-
131
- it 'should reprioritize stream on PRIORITY' do
132
- expect { @stream.send priority_frame }.to_not raise_error
133
- expect(@stream.weight).to eq 20
134
- end
135
-
136
- it 'should increment local_window on sent WINDOW_UPDATE' do
137
- expect { @stream.send window_update_frame }.to_not raise_error
138
- expect(@stream.local_window).to eq DEFAULT_FLOW_WINDOW + window_update_frame[:increment]
139
- end
140
- end
141
-
142
- context 'open' do
143
- before(:each) { @stream.receive headers_frame }
144
-
145
- it 'should allow any valid frames types to be sent' do
146
- (frame_types - [ping_frame, goaway_frame, settings_frame]).each do |type|
147
- expect { @stream.dup.send type.deep_dup }.to_not raise_error
148
- end
149
- end
150
-
151
- it 'should allow frames of any type to be received' do
152
- frame_types.each do |type|
153
- expect { @stream.dup.receive type }.to_not raise_error
154
- end
155
- end
156
-
157
- it 'should transition to half closed (local) if sending END_STREAM' do
158
- [data_frame, headers_frame].each do |frame|
159
- s, f = @stream.dup, frame.deep_dup
160
- f[:flags] = [:end_stream]
161
-
162
- s.send f
163
- expect(s.state).to eq :half_closed_local
164
- end
165
- end
166
-
167
- it 'should transition to half closed (remote) if receiving END_STREAM' do
168
- [data_frame, headers_frame].each do |frame|
169
- s, f = @stream.dup, frame.dup
170
- f[:flags] = [:end_stream]
171
-
172
- s.receive f
173
- expect(s.state).to eq :half_closed_remote
174
- end
175
- end
176
-
177
- it 'should transition to half closed if remote opened with END_STREAM' do
178
- s = @client.new_stream
179
- hclose = headers_frame
180
- hclose[:flags] = [:end_stream]
181
-
182
- s.receive hclose
183
- expect(s.state).to eq :half_closed_remote
184
- end
185
-
186
- it 'should transition to half closed if local opened with END_STREAM' do
187
- s = @client.new_stream
188
- hclose = headers_frame
189
- hclose[:flags] = [:end_stream]
190
-
191
- s.send hclose
192
- expect(s.state).to eq :half_closed_local
193
- end
194
-
195
- it 'should transition to closed if sending RST_STREAM' do
196
- @stream.close
197
- expect(@stream.state).to eq :closed
198
- expect(@stream).to be_closed
199
- end
200
-
201
- it 'should transition to closed if receiving RST_STREAM' do
202
- @stream.receive rst_stream_frame
203
- expect(@stream.state).to eq :closed
204
- end
205
-
206
- it 'should emit :active on open transition' do
207
- openp, openr = false, false
208
- sp = @client.new_stream
209
- sr = @client.new_stream
210
- sp.on(:active) { openp = true }
211
- sr.on(:active) { openr = true }
212
-
213
- sp.receive headers_frame
214
- sr.send headers_frame
215
-
216
- expect(openp).to be_truthy
217
- expect(openr).to be_truthy
218
- end
219
-
220
- it 'should not emit :active on transition from open' do
221
- order, stream = [], @client.new_stream
222
-
223
- stream.on(:active) { order << :active }
224
- stream.on(:half_close) { order << :half_close }
225
- stream.on(:close) { order << :close }
226
-
227
- req = headers_frame
228
- req[:flags] = [:end_headers]
229
-
230
- stream.send req
231
- stream.send data_frame
232
- expect(order).to eq [:active, :half_close]
233
- end
234
-
235
- it 'should emit :close on close transition' do
236
- closep, closer = false, false
237
- sp, sr = @stream.dup, @stream.dup
238
-
239
- sp.on(:close) { closep = true }
240
- sr.on(:close) { closer = true }
241
-
242
- sp.receive rst_stream_frame
243
- sr.close
244
-
245
- expect(closep).to be_truthy
246
- expect(closer).to be_truthy
247
- end
248
-
249
- it 'should emit :close after frame is processed' do
250
- order, stream = [], @client.new_stream
251
-
252
- stream.on(:active) { order << :active }
253
- stream.on(:data) { order << :data }
254
- stream.on(:half_close) { order << :half_close }
255
- stream.on(:close) { order << :close }
256
-
257
- req = headers_frame
258
- req[:flags] = [:end_stream, :end_headers]
259
-
260
- stream.send req
261
- stream.receive headers_frame
262
- stream.receive data_frame
263
-
264
- expect(order).to eq [:active, :half_close, :data, :close]
265
- end
266
-
267
- it 'should emit :close with reason' do
268
- reason = nil
269
- @stream.on(:close) { |r| reason = r }
270
- @stream.receive rst_stream_frame
271
- expect(reason).not_to be_nil
272
- end
273
-
274
- it 'should reprioritize stream on sent PRIORITY' do
275
- expect { @stream.send priority_frame }.to_not raise_error
276
- expect(@stream.weight).to eq 20
277
- end
278
- it 'should reprioritize stream on received PRIORITY' do
279
- expect { @stream.receive priority_frame }.to_not raise_error
280
- expect(@stream.weight).to eq 20
281
- end
282
- end
283
-
284
- context 'half closed (local)' do
285
- before(:each) { @stream.send headers_frame.merge(flags: [:end_headers, :end_stream]) }
286
-
287
- it 'should raise error on attempt to send invalid frames' do
288
- frame_types.reject { |frame| %i[priority rst_stream window_update].include?(frame[:type]) }.each do |frame|
289
- expect { @stream.dup.send frame }.to raise_error InternalError
290
- end
291
- end
292
-
293
- it 'should transition to closed on receipt of END_STREAM flag' do
294
- [data_frame, headers_frame, continuation_frame].each do |frame|
295
- s, f = @stream.dup, frame.dup
296
- f[:flags] = [:end_stream]
297
-
298
- s.receive f
299
- expect(s.state).to eq :closed
300
- end
301
- end
302
-
303
- it 'should transition to closed on receipt of RST_STREAM frame' do
304
- @stream.receive rst_stream_frame
305
- expect(@stream.state).to eq :closed
306
- end
307
-
308
- it 'should transition to closed if RST_STREAM frame is sent' do
309
- @stream.send rst_stream_frame
310
- expect(@stream.state).to eq :closed
311
- end
312
-
313
- it 'should ignore received WINDOW_UPDATE frames' do
314
- expect { @stream.receive window_update_frame }.to_not raise_error
315
- expect(@stream.state).to eq :half_closed_local
316
- end
317
-
318
- it 'should ignore received PRIORITY frames' do
319
- expect { @stream.receive priority_frame }.to_not raise_error
320
- expect(@stream.state).to eq :half_closed_local
321
- end
322
-
323
- it 'should reprioritize stream on sent PRIORITY' do
324
- expect { @stream.send priority_frame }.to_not raise_error
325
- expect(@stream.weight).to eq 20
326
- end
327
-
328
- it 'should reprioritize stream (and decendants) on received PRIORITY' do
329
- expect { @stream.receive priority_frame }.to_not raise_error
330
- expect(@stream.weight).to eq 20
331
- end
332
-
333
- it 'should increment local_window on sent WINDOW_UPDATE' do
334
- expect { @stream.send window_update_frame }.to_not raise_error
335
- expect(@stream.local_window).to eq DEFAULT_FLOW_WINDOW + window_update_frame[:increment]
336
- end
337
-
338
- it 'should emit :half_close event on transition' do
339
- order = []
340
- stream = @client.new_stream
341
- stream.on(:active) { order << :active }
342
- stream.on(:half_close) { order << :half_close }
343
-
344
- req = headers_frame
345
- req[:flags] = [:end_stream, :end_headers]
346
-
347
- stream.send req
348
- expect(order).to eq [:active, :half_close]
349
- end
350
-
351
- it 'should emit :close event on transition to closed' do
352
- closed = false
353
- @stream.on(:close) { closed = true }
354
- @stream.receive rst_stream_frame
355
-
356
- expect(@stream.state).to eq :closed
357
- expect(closed).to be_truthy
358
- end
359
- end
360
-
361
- context 'half closed (remote)' do
362
- before(:each) { @stream.receive headers_frame.merge(flags: [:end_headers, :end_stream]) }
363
-
364
- it 'should raise STREAM_CLOSED error on reciept of frames' do
365
- (frame_types - [priority_frame, rst_stream_frame, window_update_frame]).each do |frame|
366
- expect do
367
- @stream.dup.receive frame
368
- end.to raise_error(StreamClosed)
369
- end
370
- end
371
-
372
- it 'should transition to closed if END_STREAM flag is sent' do
373
- [data_frame, headers_frame].each do |frame|
374
- s, f = @stream.dup, frame.deep_dup
375
- f[:flags] = [:end_stream]
376
-
377
- s.on(:close) { expect(s.state).to eq :closed }
378
- s.send f
379
- expect(s.state).to eq :closed
380
- end
381
- end
382
-
383
- it 'should not transition to closed if END_STREAM flag is sent when overflowing window' do
384
- @stream.on(:close) { fail 'should not have closed' }
385
- data = { type: :data, flags: [], stream: @stream.id }
386
- 4.times do
387
- data = data.merge(flags: [:end_stream]) if @stream.remote_window < 16_384
388
- @stream.send data.merge(payload: 'x' * 16_384)
389
- end
390
- end
391
-
392
- it 'should transition to closed when send buffer is emptied' do
393
- o = Object.new
394
- expect(o).to receive(:tap).once
395
- @stream.on(:close) do
396
- expect(@stream.buffered_amount).to eq 0
397
- o.tap
398
- end
399
- data = { type: :data, flags: [], stream: @stream.id }
400
- 4.times do
401
- data = data.merge(flags: [:end_stream]) if @stream.remote_window < 16_384
402
- @stream.send data.merge(payload: 'x' * 16_384)
403
- end
404
- @client << Framer.new.generate(type: :window_update, stream: @stream.id, increment: 16_384)
405
- end
406
-
407
- it 'should transition to closed if RST_STREAM is sent' do
408
- @stream.close
409
- expect(@stream.state).to eq :closed
410
- end
411
-
412
- it 'should transition to closed on reciept of RST_STREAM frame' do
413
- @stream.receive rst_stream_frame
414
- expect(@stream.state).to eq :closed
415
- end
416
-
417
- it 'should ignore sent WINDOW_UPDATE frames' do
418
- expect { @stream.send window_update_frame }.to_not raise_error
419
- expect(@stream.state).to eq :half_closed_remote
420
- end
421
-
422
- it 'should increment remote_window on received WINDOW_UPDATE' do
423
- expect { @stream.receive window_update_frame }.to_not raise_error
424
- expect(@stream.remote_window).to eq DEFAULT_FLOW_WINDOW + window_update_frame[:increment]
425
- end
426
-
427
- it 'should reprioritize stream on sent PRIORITY' do
428
- expect { @stream.send priority_frame }.to_not raise_error
429
- expect(@stream.weight).to eq 20
430
- end
431
- it 'should reprioritize stream on received PRIORITY' do
432
- expect { @stream.receive priority_frame }.to_not raise_error
433
- expect(@stream.weight).to eq 20
434
- end
435
-
436
- it 'should emit :half_close event on transition' do
437
- order = []
438
- stream = @client.new_stream
439
- stream.on(:active) { order << :active }
440
- stream.on(:half_close) { order << :half_close }
441
-
442
- req = headers_frame
443
- req[:flags] = [:end_stream, :end_headers]
444
-
445
- stream.receive req
446
- expect(order).to eq [:active, :half_close]
447
- end
448
-
449
- it 'should emit :close event on close transition' do
450
- closed = false
451
- @stream.on(:close) { closed = true }
452
- @stream.close
453
-
454
- expect(@stream.state).to eq :closed
455
- expect(closed).to be_truthy
456
- end
457
- end
458
-
459
- context 'closed' do
460
- context 'remote closed stream' do
461
- before(:each) do
462
- @stream.send headers_frame.merge(flags: [:end_headers, :end_stream]) # half closed local
463
- @stream.receive headers_frame.merge(flags: [:end_headers, :end_stream]) # closed by remote
464
- end
465
-
466
- it 'should raise STREAM_CLOSED on attempt to send frames' do
467
- (frame_types - [priority_frame, rst_stream_frame]).each do |frame|
468
- expect do
469
- @stream.dup.send frame
470
- end.to raise_error(StreamClosed)
471
- end
472
- end
473
-
474
- it 'should raise STREAM_CLOSED on receipt of frame' do
475
- (frame_types - [priority_frame, rst_stream_frame, window_update_frame]).each do |frame|
476
- expect do
477
- @stream.dup.receive frame
478
- end.to raise_error(StreamClosed)
479
- end
480
- end
481
-
482
- it 'should allow PRIORITY, RST_STREAM to be sent' do
483
- expect { @stream.send priority_frame }.to_not raise_error
484
- expect { @stream.send rst_stream_frame }.to_not raise_error
485
- end
486
-
487
- it 'should allow PRIORITY, RST_STREAM to be received' do
488
- expect { @stream.receive priority_frame }.to_not raise_error
489
- expect { @stream.receive rst_stream_frame }.to_not raise_error
490
- end
491
-
492
- it 'should reprioritize stream on sent PRIORITY' do
493
- expect { @stream.send priority_frame }.to_not raise_error
494
- expect(@stream.weight).to eq 20
495
- end
496
- it 'should reprioritize stream on received PRIORITY' do
497
- expect { @stream.receive priority_frame }.to_not raise_error
498
- expect(@stream.weight).to eq 20
499
- end
500
-
501
- it 'should ignore received WINDOW_UPDATE frames' do
502
- expect { @stream.receive window_update_frame }.to_not raise_error
503
- expect(@stream.state).to eq :closed
504
- end
505
- end
506
-
507
- context 'local closed via RST_STREAM frame' do
508
- before(:each) do
509
- @stream.send headers_frame # open
510
- @stream.send rst_stream_frame # closed by local
511
- end
512
-
513
- it 'should ignore received frames' do
514
- (frame_types - [push_promise_frame]).each do |frame|
515
- expect do
516
- cb = []
517
- @stream.on(:data) { cb << :data }
518
- @stream.on(:headers) { cb << :headers }
519
- @stream.dup.receive frame.dup
520
- expect(cb).to be_empty
521
- end.to_not raise_error
522
- end
523
- end
524
-
525
- # it "should transition to reserved remote on PUSH_PROMISE" do
526
- # An endpoint might receive a PUSH_PROMISE frame after it sends
527
- # RST_STREAM. PUSH_PROMISE causes a stream to become "reserved".
528
- # ...
529
- # We're auto RST'ing PUSH streams in connection class, hence
530
- # skipping this transition for now.
531
- # end
532
- end
533
-
534
- # FIXME: Isn't this test same as "half closed (local)"?
535
- # context "local closed via END_STREAM flag" do
536
- # before(:each) do
537
- # @stream.send headers_frame # open
538
- # @stream.send data_frame # contains end_stream flag
539
- # end
540
-
541
- # it "should ignore received frames" do
542
- # frame_types.each do |frame|
543
- # expect { @stream.dup.receive frame }.to_not raise_error
544
- # end
545
- # end
546
- # end
547
- end
548
- end # end stream states
549
-
550
- # TODO: add test cases to ensure on(:priority) emitted after close
551
-
552
- context 'flow control' do
553
- it 'should initialize to default flow control window' do
554
- expect(@stream.remote_window).to eq DEFAULT_FLOW_WINDOW
555
- end
556
-
557
- it 'should update window size on DATA frames only' do
558
- @stream.send headers_frame # go to open
559
- expect(@stream.remote_window).to eq DEFAULT_FLOW_WINDOW
560
-
561
- (frame_types - [data_frame, ping_frame, goaway_frame, settings_frame]).each do |frame|
562
- s = @stream.dup
563
- s.send frame.deep_dup
564
- expect(s.remote_window).to eq DEFAULT_FLOW_WINDOW
565
- end
566
-
567
- @stream.send data_frame
568
- expect(@stream.remote_window).to eq DEFAULT_FLOW_WINDOW - data_frame[:payload].bytesize
569
- end
570
-
571
- it 'should update window size on receipt of WINDOW_UPDATE' do
572
- @stream.send headers_frame
573
- @stream.send data_frame
574
- @stream.receive window_update_frame
575
-
576
- expect(@stream.remote_window).to eq(
577
- DEFAULT_FLOW_WINDOW - data_frame[:payload].bytesize + window_update_frame[:increment],
578
- )
579
- end
580
-
581
- it 'should observe session flow control' do
582
- settings, data = settings_frame, data_frame
583
- settings[:payload] = [[:settings_initial_window_size, 1000]]
584
- settings[:stream] = 0
585
-
586
- framer = Framer.new
587
- @client << framer.generate(settings)
588
-
589
- s1 = @client.new_stream
590
- s1.send headers_frame
591
- s1.send data.merge(payload: 'x' * 900, flags: [])
592
- expect(s1.remote_window).to eq 100
593
-
594
- s1.send data.merge(payload: 'x' * 200)
595
- expect(s1.remote_window).to eq 0
596
- expect(s1.buffered_amount).to eq 100
597
-
598
- @client << framer.generate(window_update_frame.merge(stream: s1.id, increment: 1000))
599
- expect(s1.buffered_amount).to eq 0
600
- expect(s1.remote_window).to eq 900
601
- end
602
-
603
- it 'should not update window when data received is less than half of maximum local window size' do
604
- data = data_frame
605
- datalen = data[:payload].bytesize
606
- expect(@stream).not_to receive(:send) do |frame|
607
- expect(frame[:type]).to eq :window_update
608
- expect(frame[:increment]).to eq datalen
609
- end
610
- @stream.receive headers_frame
611
- @stream.receive data
612
- end
613
-
614
- it 'should update window when data received is over half of the maximum local window size' do
615
- data1 = data_frame.merge(payload: 'a'*16_384, flags: [])
616
- data2 = data_frame.merge(payload: 'a'*16_384)
617
- datalen = 16_384 * 2
618
- expect(@stream).to receive(:send) do |frame|
619
- expect(frame[:type]).to eq :window_update
620
- expect(frame[:increment]).to eq datalen
621
- end
622
- @stream.receive headers_frame
623
- @stream.receive data1
624
- @stream.receive data2
625
- end
626
- end
627
-
628
- context 'client API' do
629
- it '.reprioritize should emit PRIORITY frame' do
630
- expect(@stream).to receive(:send) do |frame|
631
- expect(frame[:type]).to eq :priority
632
- expect(frame[:weight]).to eq 30
633
- end
634
-
635
- @stream.reprioritize weight: 30
636
- end
637
-
638
- it '.reprioritize should raise error if invoked by server' do
639
- srv = Server.new
640
- stream = srv.new_stream
641
-
642
- expect { stream.reprioritize(weight: 10) }.to raise_error(InternalError)
643
- end
644
-
645
- it '.headers should emit HEADERS frames' do
646
- payload = {
647
- ':method' => 'GET',
648
- ':scheme' => 'http',
649
- ':host' => 'www.example.org',
650
- ':path' => '/resource',
651
- 'custom' => 'value',
652
- }
653
-
654
- expect(@stream).to receive(:send) do |frame|
655
- expect(frame[:type]).to eq :headers
656
- expect(frame[:payload]).to eq payload
657
- expect(frame[:flags]).to eq [:end_headers]
658
- end
659
-
660
- @stream.headers(payload, end_stream: false, end_headers: true)
661
- end
662
-
663
- it '.data should emit DATA frames' do
664
- expect(@stream).to receive(:send) do |frame|
665
- expect(frame[:type]).to eq :data
666
- expect(frame[:payload]).to eq 'text'
667
- expect(frame[:flags]).to be_empty
668
- end
669
- @stream.data('text', end_stream: false)
670
-
671
- expect(@stream).to receive(:send) do |frame|
672
- expect(frame[:flags]).to eq [:end_stream]
673
- end
674
- @stream.data('text')
675
- end
676
-
677
- it '.data should split large DATA frames' do
678
- data = 'x' * 16_384 * 2
679
-
680
- want = [
681
- { type: :data, flags: [], length: 16_384 },
682
- { type: :data, flags: [], length: 16_384 },
683
- { type: :data, flags: [:end_stream], length: 1 },
684
- ]
685
- want.each do |w|
686
- expect(@stream).to receive(:send) do |frame|
687
- expect(frame[:type]).to eq w[:type]
688
- expect(frame[:flags]).to eq w[:flags]
689
- expect(frame[:payload].bytesize).to eq w[:length]
690
- end
691
- end
692
-
693
- @stream.data(data + 'x')
694
- end
695
-
696
- it '.data should split large multibyte DATA frames' do
697
- data = '🐼' * 16_384
698
-
699
- want = [
700
- { type: :data, flags: [], length: 16_384 },
701
- { type: :data, flags: [], length: 16_384 },
702
- { type: :data, flags: [], length: 16_384 },
703
- { type: :data, flags: [], length: 16_384 },
704
- { type: :data, flags: [:end_stream], length: 1 },
705
- ]
706
- want.each do |w|
707
- expect(@stream).to receive(:send) do |frame|
708
- expect(frame[:type]).to eq w[:type]
709
- expect(frame[:flags]).to eq w[:flags]
710
- expect(frame[:payload].bytesize).to eq w[:length]
711
- end
712
- end
713
-
714
- @stream.data(data + 'x')
715
- end
716
-
717
- it '.cancel should reset stream with cancel error code' do
718
- expect(@stream).to receive(:send) do |frame|
719
- expect(frame[:type]).to eq :rst_stream
720
- expect(frame[:error]).to eq :cancel
721
- end
722
-
723
- @stream.cancel
724
- end
725
-
726
- it '.refuse should reset stream with refused stream error code' do
727
- expect(@stream).to receive(:send) do |frame|
728
- expect(frame[:type]).to eq :rst_stream
729
- expect(frame[:error]).to eq :refused_stream
730
- end
731
-
732
- @stream.refuse
733
- end
734
-
735
- it '.window_update should emit WINDOW_UPDATE frames' do
736
- expect(@stream).to receive(:send) do |frame|
737
- expect(frame[:type]).to eq :window_update
738
- expect(frame[:increment]).to eq 20
739
- end
740
- @stream.window_update(20)
741
- end
742
- end
743
-
744
- context 'server API' do
745
- before(:each) do
746
- @srv = Server.new
747
- @frm = Framer.new
748
-
749
- @client.on(:frame) { |bytes| @srv << bytes }
750
- @client_stream = @client.new_stream
751
- end
752
-
753
- it 'should emit received headers via on(:headers)' do
754
- headers, recv = REQUEST_HEADERS, nil
755
- @srv.on(:stream) do |stream|
756
- stream.on(:headers) { |h| recv = h }
757
- end
758
-
759
- @client_stream.headers(headers)
760
- expect(recv).to eq headers
761
- end
762
-
763
- it 'should emit received payload via on(:data)' do
764
- payload = 'some-payload'
765
- @srv.on(:stream) do |stream|
766
- stream.on(:data) do |recv|
767
- expect(recv).to eq payload
768
- end
769
- end
770
-
771
- @client_stream.headers(REQUEST_HEADERS)
772
- @client_stream.data(payload)
773
- end
774
-
775
- it 'should emit received priority parameters via on(:priority)' do
776
- new_weight, new_dependency = 15, @client_stream.id + 2
777
- callback_called = false
778
- @srv.on(:stream) do |stream|
779
- stream.on(:priority) do |pri|
780
- callback_called = true
781
- expect(pri.is_a?(Hash)).to be
782
- expect(pri[:weight]).to eq new_weight
783
- expect(pri[:dependency]).to eq new_dependency
784
- end
785
- end
786
-
787
- @client_stream.headers(REQUEST_HEADERS)
788
- @client_stream.reprioritize(weight: new_weight, dependency: new_dependency)
789
- expect(callback_called).to be
790
- end
791
-
792
- context 'push' do
793
- before(:each) do
794
- @srv.on(:frame) { |bytes| @client << bytes }
795
- @srv.on(:stream) do |stream|
796
- @server_stream = stream
797
- end
798
-
799
- @client_stream.headers(REQUEST_HEADERS)
800
- end
801
-
802
- it '.promise should emit server initiated stream' do
803
- push = nil
804
- @server_stream.promise(REQUEST_HEADERS) { |pstream| push = pstream }
805
- expect(push.id).to eq 2
806
- end
807
-
808
- it '.promise push stream should have parent stream' do
809
- push = nil
810
- @server_stream.promise(REQUEST_HEADERS) { |pstream| push = pstream }
811
-
812
- expect(push.state).to eq :reserved_local
813
- expect(push.parent.id).to eq @server_stream.id
814
- end
815
-
816
- context 'stream states' do
817
- it 'server: active > half close > close' do
818
- order = []
819
- @server_stream.promise(REQUEST_HEADERS) do |push|
820
- stream = push
821
-
822
- expect(push.state).to eq :reserved_local
823
- order << :reserved
824
-
825
- push.on(:active) { order << :active }
826
- push.on(:half_close) { order << :half_close }
827
- push.on(:close) { order << :close }
828
-
829
- push.headers(RESPONSE_HEADERS)
830
- push.send data_frame.merge(stream: stream.id)
831
- end
832
-
833
- expect(order).to eq [:reserved, :active, :half_close, :close]
834
- end
835
-
836
- it 'client: promise_headers > active > headers > .. > data > close' do
837
- order, headers, promise_headers = [], [], []
838
- @client.on(:promise) do |push|
839
- order << :reserved
840
-
841
- push.on(:active) { order << :active }
842
- push.on(:data) { order << :data }
843
- push.on(:half_close) { order << :half_close }
844
- push.on(:close) { order << :close }
845
-
846
- push.on(:promise_headers) do |h|
847
- order << :promise_headers
848
- promise_headers += h
849
- end
850
- push.on(:headers) do |h|
851
- order << :headers
852
- headers += h
853
- end
854
-
855
- expect(push.id).to be_even
856
- end
857
-
858
- @server_stream.promise(REQUEST_HEADERS) do |push|
859
- push.headers(RESPONSE_HEADERS)
860
- push.data('somedata')
861
- end
862
-
863
- expect(promise_headers).to eq(REQUEST_HEADERS)
864
- expect(headers).to eq(RESPONSE_HEADERS)
865
- expect(order).to eq [
866
- :reserved,
867
- :promise_headers,
868
- :active,
869
- :headers,
870
- :half_close,
871
- :data,
872
- :close,
873
- ]
874
- end
875
- end
876
- end
877
- end
878
- end