http-2 0.7.0 → 0.8.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.
@@ -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