http-2 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,215 +1,223 @@
1
- require "helper"
1
+ require 'helper'
2
2
 
3
- describe HTTP2::Connection do
3
+ RSpec.describe HTTP2::Connection do
4
4
  before(:each) do
5
5
  @conn = Client.new
6
6
  end
7
7
 
8
8
  let(:f) { Framer.new }
9
9
 
10
- context "initialization and settings" do
11
- it "should raise error if first frame is not SETTINGS" do
10
+ context 'initialization and settings' do
11
+ it 'should raise error if first frame is not SETTINGS' do
12
12
  (FRAME_TYPES - [SETTINGS]).each do |frame|
13
- frame = set_stream_id(f.generate(frame), 0x0)
13
+ frame = set_stream_id(f.generate(frame.deep_dup), 0x0)
14
14
  expect { @conn.dup << frame }.to raise_error(ProtocolError)
15
15
  end
16
16
 
17
- expect { @conn << f.generate(SETTINGS) }.to_not raise_error
18
- @conn.state.should eq :connected
17
+ expect { @conn << f.generate(SETTINGS.dup) }.to_not raise_error
18
+ expect(@conn.state).to eq :connected
19
19
  end
20
20
 
21
- it "should raise error if SETTINGS stream != 0" do
22
- frame = set_stream_id(f.generate(SETTINGS), 0x1)
21
+ it 'should raise error if SETTINGS stream != 0' do
22
+ frame = set_stream_id(f.generate(SETTINGS.dup), 0x1)
23
23
  expect { @conn << frame }.to raise_error(ProtocolError)
24
24
  end
25
25
  end
26
26
 
27
- context "settings synchronization" do
28
- it "should reflect outgoing settings when ack is received" do
29
- @conn.local_settings[:settings_header_table_size].should eq 4096
27
+ context 'settings synchronization' do
28
+ it 'should reflect outgoing settings when ack is received' do
29
+ expect(@conn.local_settings[:settings_header_table_size]).to eq 4096
30
30
  @conn.settings(settings_header_table_size: 256)
31
- @conn.local_settings[:settings_header_table_size].should eq 4096
31
+ expect(@conn.local_settings[:settings_header_table_size]).to eq 4096
32
32
 
33
33
  ack = { type: :settings, stream: 0, payload: [], flags: [:ack] }
34
34
  @conn << f.generate(ack)
35
35
 
36
- @conn.local_settings[:settings_header_table_size].should eq 256
36
+ expect(@conn.local_settings[:settings_header_table_size]).to eq 256
37
37
  end
38
38
 
39
- it "should reflect incoming settings when SETTINGS is received" do
40
- @conn.remote_settings[:settings_header_table_size].should eq 4096
39
+ it 'should reflect incoming settings when SETTINGS is received' do
40
+ expect(@conn.remote_settings[:settings_header_table_size]).to eq 4096
41
41
  settings = SETTINGS.dup
42
42
  settings[:payload] = [[:settings_header_table_size, 256]]
43
43
 
44
44
  @conn << f.generate(settings)
45
45
 
46
- @conn.remote_settings[:settings_header_table_size].should eq 256
46
+ expect(@conn.remote_settings[:settings_header_table_size]).to eq 256
47
47
  end
48
48
 
49
- it "should send SETTINGS ACK when SETTINGS is received" do
49
+ it 'should send SETTINGS ACK when SETTINGS is received' do
50
50
  settings = SETTINGS.dup
51
51
  settings[:payload] = [[:settings_header_table_size, 256]]
52
52
 
53
- @conn.should_receive(:send) do |frame|
54
- frame[:type].should eq :settings
55
- frame[:flags].should eq [:ack]
56
- frame[:payload].should eq []
53
+ expect(@conn).to receive(:send) do |frame|
54
+ expect(frame[:type]).to eq :settings
55
+ expect(frame[:flags]).to eq [:ack]
56
+ expect(frame[:payload]).to eq []
57
57
  end
58
58
 
59
59
  @conn << f.generate(settings)
60
60
  end
61
61
  end
62
62
 
63
- context "stream management" do
64
- it "should initialize to default stream limit (100)" do
65
- @conn.local_settings[:settings_max_concurrent_streams].should eq 100
63
+ context 'stream management' do
64
+ it 'should initialize to default stream limit (100)' do
65
+ expect(@conn.local_settings[:settings_max_concurrent_streams]).to eq 100
66
66
  end
67
67
 
68
- it "should change stream limit to received SETTINGS value" do
69
- @conn << f.generate(SETTINGS)
70
- @conn.remote_settings[:settings_max_concurrent_streams].should eq 10
68
+ it 'should change stream limit to received SETTINGS value' do
69
+ @conn << f.generate(SETTINGS.dup)
70
+ expect(@conn.remote_settings[:settings_max_concurrent_streams]).to eq 10
71
71
  end
72
72
 
73
- it "should count open streams against stream limit" do
73
+ it 'should count open streams against stream limit' do
74
74
  s = @conn.new_stream
75
- @conn.active_stream_count.should eq 0
75
+ expect(@conn.active_stream_count).to eq 0
76
76
  s.receive HEADERS
77
- @conn.active_stream_count.should eq 1
77
+ expect(@conn.active_stream_count).to eq 1
78
78
  end
79
79
 
80
- it "should not count reserved streams against stream limit" do
80
+ it 'should not count reserved streams against stream limit' do
81
81
  s1 = @conn.new_stream
82
82
  s1.receive PUSH_PROMISE
83
- @conn.active_stream_count.should eq 0
83
+ expect(@conn.active_stream_count).to eq 0
84
84
 
85
85
  s2 = @conn.new_stream
86
- s2.send PUSH_PROMISE
87
- @conn.active_stream_count.should eq 0
86
+ s2.send PUSH_PROMISE.deep_dup
87
+ expect(@conn.active_stream_count).to eq 0
88
88
 
89
89
  # transition to half closed
90
90
  s1.receive HEADERS
91
- s2.send HEADERS
92
- @conn.active_stream_count.should eq 2
91
+ s2.send HEADERS.deep_dup
92
+ expect(@conn.active_stream_count).to eq 2
93
93
 
94
94
  # transition to closed
95
95
  s1.receive DATA
96
- s2.send DATA
97
- @conn.active_stream_count.should eq 0
96
+ s2.send DATA.dup
97
+ expect(@conn.active_stream_count).to eq 0
98
98
  end
99
99
 
100
- it "should not exceed stream limit set by peer" do
101
- @conn << f.generate(SETTINGS)
100
+ it 'should not exceed stream limit set by peer' do
101
+ @conn << f.generate(SETTINGS.dup)
102
102
 
103
- expect {
103
+ expect do
104
104
  10.times do
105
105
  s = @conn.new_stream
106
- s.send HEADERS
106
+ s.send HEADERS.deep_dup
107
107
  end
108
- }.to_not raise_error
108
+ end.to_not raise_error
109
109
 
110
110
  expect { @conn.new_stream }.to raise_error(StreamLimitExceeded)
111
111
  end
112
112
 
113
- it "should initialize stream with HEADERS priority value" do
114
- @conn << f.generate(SETTINGS)
113
+ it 'should initialize stream with HEADERS priority value' do
114
+ @conn << f.generate(SETTINGS.dup)
115
115
 
116
116
  stream, headers = nil, HEADERS.dup
117
117
  headers[:weight] = 20
118
118
  headers[:stream_dependency] = 0
119
119
  headers[:exclusive] = false
120
120
 
121
- @conn.on(:stream) {|s| stream = s }
121
+ @conn.on(:stream) { |s| stream = s }
122
122
  @conn << f.generate(headers)
123
123
 
124
- stream.weight.should eq 20
124
+ expect(stream.weight).to eq 20
125
+ end
126
+
127
+ it 'should initialize idle stream on PRIORITY frame' do
128
+ @conn << f.generate(SETTINGS.dup)
129
+
130
+ stream = nil
131
+ @conn.on(:stream) { |s| stream = s }
132
+ @conn << f.generate(PRIORITY.dup)
133
+
134
+ expect(stream.state).to eq :idle
125
135
  end
126
136
  end
127
137
 
128
- context "Headers pre/post processing" do
129
- it "should not concatenate multiple occurences of a header field with the same name" do
138
+ context 'Headers pre/post processing' do
139
+ it 'should not concatenate multiple occurences of a header field with the same name' do
130
140
  input = [
131
- ["Content-Type", "text/html"],
132
- ["Cache-Control", "max-age=60, private"],
133
- ["Cache-Control", "must-revalidate"],
141
+ ['Content-Type', 'text/html'],
142
+ ['Cache-Control', 'max-age=60, private'],
143
+ ['Cache-Control', 'must-revalidate'],
134
144
  ]
135
145
  expected = [
136
- ["content-type", "text/html"],
137
- ["cache-control", "max-age=60, private"],
138
- ["cache-control", "must-revalidate"],
146
+ ['content-type', 'text/html'],
147
+ ['cache-control', 'max-age=60, private'],
148
+ ['cache-control', 'must-revalidate'],
139
149
  ]
140
150
  headers = []
141
151
  @conn.on(:frame) do |bytes|
142
- bytes.force_encoding('binary')
143
152
  # bytes[3]: frame's type field
144
- [1,5,9].include?(bytes[3].ord) and headers << f.parse(bytes)
153
+ headers << f.parse(bytes) if [1, 5, 9].include?(bytes[3].ord)
145
154
  end
146
155
 
147
156
  stream = @conn.new_stream
148
157
  stream.headers(input)
149
158
 
150
- headers.size.should eq 1
159
+ expect(headers.size).to eq 1
151
160
  emitted = Decompressor.new.decode(headers.first[:payload])
152
- emitted.should match_array(expected)
161
+ expect(emitted).to match_array(expected)
153
162
  end
154
163
 
155
- it "should not split zero-concatenated header field values" do
164
+ it 'should not split zero-concatenated header field values' do
156
165
  input = [
157
- ["cache-control", "max-age=60, private\0must-revalidate"],
158
- ["content-type", "text/html"],
159
- ["cookie", "a=b\0c=d; e=f"],
166
+ ['cache-control', "max-age=60, private\0must-revalidate"],
167
+ ['content-type', 'text/html'],
168
+ ['cookie', "a=b\0c=d; e=f"],
160
169
  ]
161
170
  expected = [
162
- ["cache-control", "max-age=60, private\0must-revalidate"],
163
- ["content-type", "text/html"],
164
- ["cookie", "a=b\0c=d; e=f"],
171
+ ['cache-control', "max-age=60, private\0must-revalidate"],
172
+ ['content-type', 'text/html'],
173
+ ['cookie', "a=b\0c=d; e=f"],
165
174
  ]
166
175
 
167
176
  result = nil
168
177
  @conn.on(:stream) do |stream|
169
- stream.on(:headers) {|h| result = h}
178
+ stream.on(:headers) { |h| result = h }
170
179
  end
171
180
 
172
181
  srv = Server.new
173
- srv.on(:frame) {|bytes| @conn << bytes}
182
+ srv.on(:frame) { |bytes| @conn << bytes }
174
183
  stream = srv.new_stream
175
184
  stream.headers(input)
176
185
 
177
- result.should eq expected
178
-
186
+ expect(result).to eq expected
179
187
  end
180
188
  end
181
189
 
182
- context "flow control" do
183
- it "should initialize to default flow window" do
184
- @conn.remote_window.should eq DEFAULT_FLOW_WINDOW
190
+ context 'flow control' do
191
+ it 'should initialize to default flow window' do
192
+ expect(@conn.remote_window).to eq DEFAULT_FLOW_WINDOW
185
193
  end
186
194
 
187
- it "should update connection and stream windows on SETTINGS" do
195
+ it 'should update connection and stream windows on SETTINGS' do
188
196
  settings, data = SETTINGS.dup, DATA.dup
189
197
  settings[:payload] = [[:settings_initial_window_size, 1024]]
190
- data[:payload] = 'x'*2048
198
+ data[:payload] = 'x' * 2048
191
199
 
192
200
  stream = @conn.new_stream
193
201
 
194
- stream.send HEADERS
202
+ stream.send HEADERS.deep_dup
195
203
  stream.send data
196
- stream.remote_window.should eq (DEFAULT_FLOW_WINDOW - 2048)
197
- @conn.remote_window.should eq (DEFAULT_FLOW_WINDOW - 2048)
204
+ expect(stream.remote_window).to eq(DEFAULT_FLOW_WINDOW - 2048)
205
+ expect(@conn.remote_window).to eq(DEFAULT_FLOW_WINDOW - 2048)
198
206
 
199
207
  @conn << f.generate(settings)
200
- @conn.remote_window.should eq -1024
201
- stream.remote_window.should eq -1024
208
+ expect(@conn.remote_window).to eq(-1024)
209
+ expect(stream.remote_window).to eq(-1024)
202
210
  end
203
211
 
204
- it "should initialize streams with window specified by peer" do
212
+ it 'should initialize streams with window specified by peer' do
205
213
  settings = SETTINGS.dup
206
214
  settings[:payload] = [[:settings_initial_window_size, 1024]]
207
215
 
208
216
  @conn << f.generate(settings)
209
- @conn.new_stream.remote_window.should eq 1024
217
+ expect(@conn.new_stream.remote_window).to eq 1024
210
218
  end
211
219
 
212
- it "should observe connection flow control" do
220
+ it 'should observe connection flow control' do
213
221
  settings, data = SETTINGS.dup, DATA.dup
214
222
  settings[:payload] = [[:settings_initial_window_size, 1000]]
215
223
 
@@ -217,60 +225,60 @@ describe HTTP2::Connection do
217
225
  s1 = @conn.new_stream
218
226
  s2 = @conn.new_stream
219
227
 
220
- s1.send HEADERS
221
- s1.send data.merge({payload: "x" * 900})
222
- @conn.remote_window.should eq 100
228
+ s1.send HEADERS.deep_dup
229
+ s1.send data.merge(payload: 'x' * 900)
230
+ expect(@conn.remote_window).to eq 100
223
231
 
224
- s2.send HEADERS
225
- s2.send data.merge({payload: "x" * 200})
226
- @conn.remote_window.should eq 0
227
- @conn.buffered_amount.should eq 100
232
+ s2.send HEADERS.deep_dup
233
+ s2.send data.merge(payload: 'x' * 200)
234
+ expect(@conn.remote_window).to eq 0
235
+ expect(@conn.buffered_amount).to eq 100
228
236
 
229
- @conn << f.generate(WINDOW_UPDATE.merge({stream: 0, increment: 1000}))
230
- @conn.buffered_amount.should eq 0
231
- @conn.remote_window.should eq 900
237
+ @conn << f.generate(WINDOW_UPDATE.merge(stream: 0, increment: 1000))
238
+ expect(@conn.buffered_amount).to eq 0
239
+ expect(@conn.remote_window).to eq 900
232
240
  end
233
241
  end
234
242
 
235
- context "framing" do
236
- it "should buffer incomplete frames" do
243
+ context 'framing' do
244
+ it 'should buffer incomplete frames' do
237
245
  settings = SETTINGS.dup
238
246
  settings[:payload] = [[:settings_initial_window_size, 1000]]
239
247
  @conn << f.generate(settings)
240
248
 
241
- frame = f.generate(WINDOW_UPDATE.merge({stream: 0, increment: 1000}))
249
+ frame = f.generate(WINDOW_UPDATE.merge(stream: 0, increment: 1000))
242
250
  @conn << frame
243
- @conn.remote_window.should eq 2000
251
+ expect(@conn.remote_window).to eq 2000
244
252
 
245
- @conn << frame.slice!(0,1)
253
+ @conn << frame.slice!(0, 1)
246
254
  @conn << frame
247
- @conn.remote_window.should eq 3000
255
+ expect(@conn.remote_window).to eq 3000
248
256
  end
249
257
 
250
- it "should decompress header blocks regardless of stream state" do
258
+ it 'should decompress header blocks regardless of stream state' do
251
259
  req_headers = [
252
- ["content-length", "20"],
253
- ["x-my-header", "first"]
260
+ ['content-length', '20'],
261
+ ['x-my-header', 'first'],
254
262
  ]
255
263
 
256
264
  cc = Compressor.new
257
265
  headers = HEADERS.dup
258
266
  headers[:payload] = cc.encode(req_headers)
259
267
 
260
- @conn << f.generate(SETTINGS)
268
+ @conn << f.generate(SETTINGS.dup)
261
269
  @conn.on(:stream) do |stream|
262
- stream.should_receive(:<<) do |frame|
263
- frame[:payload].should eq req_headers
270
+ expect(stream).to receive(:<<) do |frame|
271
+ expect(frame[:payload]).to eq req_headers
264
272
  end
265
273
  end
266
274
 
267
275
  @conn << f.generate(headers)
268
276
  end
269
277
 
270
- it "should decode non-contiguous header blocks" do
278
+ it 'should decode non-contiguous header blocks' do
271
279
  req_headers = [
272
- ["content-length", "15"],
273
- ["x-my-header", "first"]
280
+ ['content-length', '15'],
281
+ ['x-my-header', 'first'],
274
282
  ]
275
283
 
276
284
  cc = Compressor.new
@@ -278,17 +286,17 @@ describe HTTP2::Connection do
278
286
 
279
287
  # Header block fragment might not complete for decompression
280
288
  payload = cc.encode(req_headers)
281
- h1[:payload] = payload.slice!(0, payload.size/2) # first half
289
+ h1[:payload] = payload.slice!(0, payload.size / 2) # first half
282
290
  h1[:stream] = 5
283
291
  h1[:flags] = []
284
292
 
285
293
  h2[:payload] = payload # the remaining
286
294
  h2[:stream] = 5
287
295
 
288
- @conn << f.generate(SETTINGS)
296
+ @conn << f.generate(SETTINGS.dup)
289
297
  @conn.on(:stream) do |stream|
290
- stream.should_receive(:<<) do |frame|
291
- frame[:payload].should eq req_headers
298
+ expect(stream).to receive(:<<) do |frame|
299
+ expect(frame[:payload]).to eq req_headers
292
300
  end
293
301
  end
294
302
 
@@ -296,65 +304,61 @@ describe HTTP2::Connection do
296
304
  @conn << f.generate(h2)
297
305
  end
298
306
 
299
- it "should require that split header blocks are a contiguous sequence" do
300
- headers, continutation = HEADERS.dup, CONTINUATION.dup
307
+ it 'should require that split header blocks are a contiguous sequence' do
308
+ headers = HEADERS.dup
301
309
  headers[:flags] = []
302
310
 
303
- @conn << f.generate(SETTINGS)
311
+ @conn << f.generate(SETTINGS.dup)
304
312
  @conn << f.generate(headers)
305
313
  (FRAME_TYPES - [CONTINUATION]).each do |frame|
306
- expect { @conn << f.generate(frame) }.to raise_error(ProtocolError)
314
+ expect { @conn << f.generate(frame.deep_dup) }.to raise_error(ProtocolError)
307
315
  end
308
316
  end
309
317
 
310
- it "should raise compression error on encode of invalid frame" do
311
- @conn << f.generate(SETTINGS)
318
+ it 'should raise compression error on encode of invalid frame' do
319
+ @conn << f.generate(SETTINGS.dup)
312
320
  stream = @conn.new_stream
313
321
 
314
- expect {
315
- stream.headers({"name" => Float::INFINITY})
316
- }.to raise_error(CompressionError)
322
+ expect do
323
+ stream.headers('name' => Float::INFINITY)
324
+ end.to raise_error(CompressionError)
317
325
  end
318
326
 
319
- it "should raise connection error on decode of invalid frame" do
320
- @conn << f.generate(SETTINGS)
327
+ it 'should raise connection error on decode of invalid frame' do
328
+ @conn << f.generate(SETTINGS.dup)
321
329
  frame = f.generate(DATA.dup) # Receiving DATA on unopened stream 1 is an error.
322
330
  # Connection errors emit protocol error frames
323
331
  expect { @conn << frame }.to raise_error(ProtocolError)
324
332
  end
325
333
 
326
- it "should emit encoded frames via on(:frame)" do
334
+ it 'should emit encoded frames via on(:frame)' do
327
335
  bytes = nil
328
- @conn.on(:frame) {|d| bytes = d }
336
+ @conn.on(:frame) { |d| bytes = d }
329
337
  @conn.settings(settings_max_concurrent_streams: 10,
330
338
  settings_initial_window_size: 0x7fffffff)
331
339
 
332
- bytes.should eq f.generate(SETTINGS)
340
+ expect(bytes).to eq f.generate(SETTINGS.dup)
333
341
  end
334
342
 
335
- it "should compress stream headers" do
343
+ it 'should compress stream headers' do
336
344
  @conn.on(:frame) do |bytes|
337
- bytes.force_encoding('binary')
338
- bytes.should_not match('get')
339
- bytes.should_not match('http')
340
- bytes.should_not match('www.example.org') # should be huffman encoded
345
+ expect(bytes).not_to include('get')
346
+ expect(bytes).not_to include('http')
347
+ expect(bytes).not_to include('www.example.org') # should be huffman encoded
341
348
  end
342
349
 
343
350
  stream = @conn.new_stream
344
- stream.headers({
345
- ':method' => 'get',
346
- ':scheme' => 'http',
347
- ':authority' => 'www.example.org',
348
- ':path' => '/resource'
349
- })
351
+ stream.headers(':method' => 'get',
352
+ ':scheme' => 'http',
353
+ ':authority' => 'www.example.org',
354
+ ':path' => '/resource')
350
355
  end
351
356
 
352
- it "should generate CONTINUATION if HEADERS is too long" do
357
+ it 'should generate CONTINUATION if HEADERS is too long' do
353
358
  headers = []
354
359
  @conn.on(:frame) do |bytes|
355
- bytes.force_encoding('binary')
356
360
  # bytes[3]: frame's type field
357
- [1,5,9].include?(bytes[3].ord) and headers << f.parse(bytes)
361
+ headers << f.parse(bytes) if [1, 5, 9].include?(bytes[3].ord)
358
362
  end
359
363
 
360
364
  stream = @conn.new_stream
@@ -363,23 +367,22 @@ describe HTTP2::Connection do
363
367
  ':scheme' => 'http',
364
368
  ':authority' => 'www.example.org',
365
369
  ':path' => '/resource',
366
- 'custom' => 'q' * 44000,
370
+ 'custom' => 'q' * 44_000,
367
371
  }, end_stream: true)
368
- headers.size.should eq 3
369
- headers[0][:type].should eq :headers
370
- headers[1][:type].should eq :continuation
371
- headers[2][:type].should eq :continuation
372
- headers[0][:flags].should eq [:end_stream]
373
- headers[1][:flags].should eq []
374
- headers[2][:flags].should eq [:end_headers]
372
+ expect(headers.size).to eq 3
373
+ expect(headers[0][:type]).to eq :headers
374
+ expect(headers[1][:type]).to eq :continuation
375
+ expect(headers[2][:type]).to eq :continuation
376
+ expect(headers[0][:flags]).to eq [:end_stream]
377
+ expect(headers[1][:flags]).to eq []
378
+ expect(headers[2][:flags]).to eq [:end_headers]
375
379
  end
376
380
 
377
- it "should not generate CONTINUATION if HEADERS fits exactly in a frame" do
381
+ it 'should not generate CONTINUATION if HEADERS fits exactly in a frame' do
378
382
  headers = []
379
383
  @conn.on(:frame) do |bytes|
380
- bytes.force_encoding('binary')
381
384
  # bytes[3]: frame's type field
382
- [1,5,9].include?(bytes[3].ord) and headers << f.parse(bytes)
385
+ headers << f.parse(bytes) if [1, 5, 9].include?(bytes[3].ord)
383
386
  end
384
387
 
385
388
  stream = @conn.new_stream
@@ -388,21 +391,20 @@ describe HTTP2::Connection do
388
391
  ':scheme' => 'http',
389
392
  ':authority' => 'www.example.org',
390
393
  ':path' => '/resource',
391
- 'custom' => 'q' * 18682, # this number should be updated when Huffman table is changed
394
+ 'custom' => 'q' * 18_682, # this number should be updated when Huffman table is changed
392
395
  }, end_stream: true)
393
- headers[0][:length].should eq @conn.remote_settings[:settings_max_frame_size]
394
- headers.size.should eq 1
395
- headers[0][:type].should eq :headers
396
- headers[0][:flags].should include(:end_headers)
397
- headers[0][:flags].should include(:end_stream)
396
+ expect(headers[0][:length]).to eq @conn.remote_settings[:settings_max_frame_size]
397
+ expect(headers.size).to eq 1
398
+ expect(headers[0][:type]).to eq :headers
399
+ expect(headers[0][:flags]).to include(:end_headers)
400
+ expect(headers[0][:flags]).to include(:end_stream)
398
401
  end
399
402
 
400
- it "should not generate CONTINUATION if HEADERS fits exactly in a frame" do
403
+ it 'should not generate CONTINUATION if HEADERS fits exactly in a frame' do
401
404
  headers = []
402
405
  @conn.on(:frame) do |bytes|
403
- bytes.force_encoding('binary')
404
406
  # bytes[3]: frame's type field
405
- [1,5,9].include?(bytes[3].ord) and headers << f.parse(bytes)
407
+ headers << f.parse(bytes) if [1, 5, 9].include?(bytes[3].ord)
406
408
  end
407
409
 
408
410
  stream = @conn.new_stream
@@ -411,20 +413,19 @@ describe HTTP2::Connection do
411
413
  ':scheme' => 'http',
412
414
  ':authority' => 'www.example.org',
413
415
  ':path' => '/resource',
414
- 'custom' => 'q' * 18682, # this number should be updated when Huffman table is changed
416
+ 'custom' => 'q' * 18_682, # this number should be updated when Huffman table is changed
415
417
  }, end_stream: true)
416
- headers[0][:length].should eq @conn.remote_settings[:settings_max_frame_size]
417
- headers.size.should eq 1
418
- headers[0][:type].should eq :headers
419
- headers[0][:flags].should include(:end_headers)
420
- headers[0][:flags].should include(:end_stream)
418
+ expect(headers[0][:length]).to eq @conn.remote_settings[:settings_max_frame_size]
419
+ expect(headers.size).to eq 1
420
+ expect(headers[0][:type]).to eq :headers
421
+ expect(headers[0][:flags]).to include(:end_headers)
422
+ expect(headers[0][:flags]).to include(:end_stream)
421
423
  end
422
424
 
423
- it "should generate CONTINUATION if HEADERS exceed the max payload by one byte" do
425
+ it 'should generate CONTINUATION if HEADERS exceed the max payload by one byte' do
424
426
  headers = []
425
427
  @conn.on(:frame) do |bytes|
426
- bytes.force_encoding('binary')
427
- [1,5,9].include?(bytes[3].ord) and headers << f.parse(bytes)
428
+ headers << f.parse(bytes) if [1, 5, 9].include?(bytes[3].ord)
428
429
  end
429
430
 
430
431
  stream = @conn.new_stream
@@ -433,145 +434,148 @@ describe HTTP2::Connection do
433
434
  ':scheme' => 'http',
434
435
  ':authority' => 'www.example.org',
435
436
  ':path' => '/resource',
436
- 'custom' => 'q' * 18683, # this number should be updated when Huffman table is changed
437
+ 'custom' => 'q' * 18_683, # this number should be updated when Huffman table is changed
437
438
  }, end_stream: true)
438
- headers[0][:length].should eq @conn.remote_settings[:settings_max_frame_size]
439
- headers[1][:length].should eq 1
440
- headers.size.should eq 2
441
- headers[0][:type].should eq :headers
442
- headers[1][:type].should eq :continuation
443
- headers[0][:flags].should eq [:end_stream]
444
- headers[1][:flags].should eq [:end_headers]
439
+ expect(headers[0][:length]).to eq @conn.remote_settings[:settings_max_frame_size]
440
+ expect(headers[1][:length]).to eq 1
441
+ expect(headers.size).to eq 2
442
+ expect(headers[0][:type]).to eq :headers
443
+ expect(headers[1][:type]).to eq :continuation
444
+ expect(headers[0][:flags]).to eq [:end_stream]
445
+ expect(headers[1][:flags]).to eq [:end_headers]
445
446
  end
446
447
  end
447
448
 
448
- context "connection management" do
449
- it "should raise error on invalid connection header" do
449
+ context 'connection management' do
450
+ it 'should raise error on invalid connection header' do
450
451
  srv = Server.new
451
- expect { srv << f.generate(SETTINGS) }.to raise_error(HandshakeError)
452
+ expect { srv << f.generate(SETTINGS.dup) }.to raise_error(HandshakeError)
452
453
 
453
454
  srv = Server.new
454
- expect {
455
+ expect do
455
456
  srv << CONNECTION_PREFACE_MAGIC
456
- srv << f.generate(SETTINGS)
457
- }.to_not raise_error
457
+ srv << f.generate(SETTINGS.dup)
458
+ end.to_not raise_error
458
459
  end
459
460
 
460
- it "should respond to PING frames" do
461
- @conn << f.generate(SETTINGS)
462
- @conn.should_receive(:send) do |frame|
463
- frame[:type].should eq :ping
464
- frame[:flags].should eq [:ack]
465
- frame[:payload].should eq "12345678"
461
+ it 'should respond to PING frames' do
462
+ @conn << f.generate(SETTINGS.dup)
463
+ expect(@conn).to receive(:send) do |frame|
464
+ expect(frame[:type]).to eq :ping
465
+ expect(frame[:flags]).to eq [:ack]
466
+ expect(frame[:payload]).to eq '12345678'
466
467
  end
467
468
 
468
- @conn << f.generate(PING)
469
+ @conn << f.generate(PING.dup)
469
470
  end
470
471
 
471
- it "should fire callback on PONG" do
472
- @conn << f.generate(SETTINGS)
472
+ it 'should fire callback on PONG' do
473
+ @conn << f.generate(SETTINGS.dup)
473
474
 
474
475
  pong = nil
475
- @conn.ping("12345678") {|d| pong = d }
476
- @conn << f.generate(PONG)
477
- pong.should eq "12345678"
476
+ @conn.ping('12345678') { |d| pong = d }
477
+ @conn << f.generate(PONG.dup)
478
+ expect(pong).to eq '12345678'
478
479
  end
479
480
 
480
- it "should fire callback on receipt of GOAWAY" do
481
+ it 'should fire callback on receipt of GOAWAY' do
481
482
  last_stream, payload, error = nil
482
- @conn << f.generate(SETTINGS)
483
- @conn.on(:goaway) {|s,e,p| last_stream = s; error = e; payload = p}
484
- @conn << f.generate(GOAWAY.merge({last_stream: 17, payload: "test"}))
483
+ @conn << f.generate(SETTINGS.dup)
484
+ @conn.on(:goaway) do |s, e, p|
485
+ last_stream = s
486
+ error = e
487
+ payload = p
488
+ end
489
+ @conn << f.generate(GOAWAY.merge(last_stream: 17, payload: 'test'))
485
490
 
486
- last_stream.should eq 17
487
- error.should eq :no_error
488
- payload.should eq "test"
491
+ expect(last_stream).to eq 17
492
+ expect(error).to eq :no_error
493
+ expect(payload).to eq 'test'
489
494
  end
490
495
 
491
- it "should raise error when opening new stream after sending GOAWAY" do
496
+ it 'should raise error when opening new stream after sending GOAWAY' do
492
497
  @conn.goaway
493
498
  expect { @conn.new_stream }.to raise_error(ConnectionClosed)
494
499
  end
495
500
 
496
- it "should raise error when opening new stream after receiving GOAWAY" do
497
- @conn << f.generate(SETTINGS)
498
- @conn << f.generate(GOAWAY)
501
+ it 'should raise error when opening new stream after receiving GOAWAY' do
502
+ @conn << f.generate(SETTINGS.dup)
503
+ @conn << f.generate(GOAWAY.dup)
499
504
  expect { @conn.new_stream }.to raise_error(ConnectionClosed)
500
505
  end
501
506
 
502
- it "should process connection management frames after GOAWAY" do
503
- @conn << f.generate(SETTINGS)
504
- @conn << f.generate(HEADERS)
505
- @conn << f.generate(GOAWAY)
506
- @conn << f.generate(HEADERS.merge({stream: 7}))
507
- @conn << f.generate(PUSH_PROMISE)
507
+ it 'should process connection management frames after GOAWAY' do
508
+ @conn << f.generate(SETTINGS.dup)
509
+ @conn << f.generate(HEADERS.dup)
510
+ @conn << f.generate(GOAWAY.dup)
511
+ @conn << f.generate(HEADERS.merge(stream: 7))
512
+ @conn << f.generate(PUSH_PROMISE.dup)
508
513
 
509
- @conn.active_stream_count.should eq 1
514
+ expect(@conn.active_stream_count).to eq 1
510
515
  end
511
516
 
512
- it "should raise error on frame for invalid stream ID" do
513
- @conn << f.generate(SETTINGS)
517
+ it 'should raise error on frame for invalid stream ID' do
518
+ @conn << f.generate(SETTINGS.dup)
514
519
 
515
- expect {
516
- @conn << f.generate(DATA.dup.merge({:stream => 31}))
517
- }.to raise_error(ProtocolError)
520
+ expect do
521
+ @conn << f.generate(DATA.dup.merge(stream: 31))
522
+ end.to raise_error(ProtocolError)
518
523
  end
519
524
 
520
- it "should send GOAWAY frame on connection error" do
525
+ it 'should send GOAWAY frame on connection error' do
521
526
  stream = @conn.new_stream
522
527
 
523
- @conn.should_receive(:encode) do |frame|
524
- frame[:type].should eq :settings
528
+ expect(@conn).to receive(:encode) do |frame|
529
+ expect(frame[:type]).to eq :settings
525
530
  [frame]
526
531
  end
527
- @conn.should_receive(:encode) do |frame|
528
- frame[:type].should eq :goaway
529
- frame[:last_stream].should eq stream.id
530
- frame[:error].should eq :protocol_error
532
+ expect(@conn).to receive(:encode) do |frame|
533
+ expect(frame[:type]).to eq :goaway
534
+ expect(frame[:last_stream]).to eq stream.id
535
+ expect(frame[:error]).to eq :protocol_error
531
536
  [frame]
532
537
  end
533
538
 
534
- expect { @conn << f.generate(DATA) }.to raise_error(ProtocolError)
539
+ expect { @conn << f.generate(DATA.dup) }.to raise_error(ProtocolError)
535
540
  end
536
541
  end
537
542
 
538
- context "API" do
539
- it ".settings should emit SETTINGS frames" do
540
- @conn.should_receive(:send) do |frame|
541
- frame[:type].should eq :settings
542
- frame[:payload].should eq([
543
+ context 'API' do
544
+ it '.settings should emit SETTINGS frames' do
545
+ expect(@conn).to receive(:send) do |frame|
546
+ expect(frame[:type]).to eq :settings
547
+ expect(frame[:payload]).to eq([
543
548
  [:settings_max_concurrent_streams, 10],
544
549
  [:settings_initial_window_size, 0x7fffffff],
545
550
  ])
546
- frame[:stream].should eq 0
551
+ expect(frame[:stream]).to eq 0
547
552
  end
548
553
 
549
554
  @conn.settings(settings_max_concurrent_streams: 10,
550
555
  settings_initial_window_size: 0x7fffffff)
551
556
  end
552
557
 
553
- it ".ping should generate PING frames" do
554
- @conn.should_receive(:send) do |frame|
555
- frame[:type].should eq :ping
556
- frame[:payload].should eq "somedata"
558
+ it '.ping should generate PING frames' do
559
+ expect(@conn).to receive(:send) do |frame|
560
+ expect(frame[:type]).to eq :ping
561
+ expect(frame[:payload]).to eq 'somedata'
557
562
  end
558
563
 
559
- @conn.ping("somedata")
564
+ @conn.ping('somedata')
560
565
  end
561
566
 
562
- it ".goaway should generate GOAWAY frame with last processed stream ID" do
563
- @conn << f.generate(SETTINGS)
564
- @conn << f.generate(HEADERS.merge({stream: 17}))
567
+ it '.goaway should generate GOAWAY frame with last processed stream ID' do
568
+ @conn << f.generate(SETTINGS.dup)
569
+ @conn << f.generate(HEADERS.merge(stream: 17))
565
570
 
566
- @conn.should_receive(:send) do |frame|
567
- frame[:type].should eq :goaway
568
- frame[:last_stream].should eq 17
569
- frame[:error].should eq :internal_error
570
- frame[:payload].should eq "payload"
571
+ expect(@conn).to receive(:send) do |frame|
572
+ expect(frame[:type]).to eq :goaway
573
+ expect(frame[:last_stream]).to eq 17
574
+ expect(frame[:error]).to eq :internal_error
575
+ expect(frame[:payload]).to eq 'payload'
571
576
  end
572
577
 
573
- @conn.goaway(:internal_error, "payload")
578
+ @conn.goaway(:internal_error, 'payload')
574
579
  end
575
-
576
580
  end
577
581
  end