1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
require "test_helper"
using BinaryString
class FlowControlTest < Minitest::Test
def test_flow_control_window_update_server
open_server_connection { |con|
before_ws = con.recv_remaining_window
con.window_update(500)
last = sent_frames.last
assert_equal(:window_update, last.type)
assert_equal(0, last.stream_id)
assert_equal(500, last.payload.uint32)
assert_equal(before_ws + 500, con.recv_remaining_window)
}
end
def test_flow_control_window_update_stream
open_new_stream { |stream|
before_ws = stream.recv_remaining_window
stream.window_update(500)
last = sent_frames.last
assert_equal(:window_update, last.type)
assert_equal(stream.id, last.stream_id)
assert_equal(500, last.payload.uint32)
assert_equal(before_ws + 500, stream.recv_remaining_window)
}
end
def test_flow_control_window_update_zero
open_new_stream { |stream|
assert_stream_error(:protocol_error) {
stream.receive_frame Frame.new(type: :window_update,
stream_id: stream.id,
payload: "".push_uint32(0))
}
}
end
def test_flow_control_window_update_frame_size
open_new_stream { |stream|
assert_connection_error(:frame_size_error) {
stream.receive_frame Frame.new(type: :window_update,
stream_id: stream.id,
payload: "".push_uint16(0))
}
}
end
def test_flow_control_dont_send_data_exceeding_send_window
open_new_stream { |stream|
con = stream.connection
con << Frame.new(type: :settings,
stream_id: 0,
payload: "".push_uint16(Frame::SETTINGS_TYPE[:initial_window_size])
.push_uint32(4*2+1)).assemble
# only extend stream window size
con << Frame.new(type: :window_update,
stream_id: stream.id,
payload: "".push_uint32(100)).assemble
10.times { |i|
stream.send Frame.new(type: :data,
stream_id: stream.id,
payload: "".push_uint32(i))
}
last = sent_frames.last
assert_equal(1, last.payload.uint32)
}
end
def test_flow_control_dont_send_data_upto_updated_send_window
open_new_stream { |stream|
con = stream.connection
con << Frame.new(type: :settings,
stream_id: 0,
payload: "".push_uint16(Frame::SETTINGS_TYPE[:initial_window_size])
.push_uint32(4*2+1)).assemble
10.times { |i|
stream.send Frame.new(type: :data,
stream_id: stream.id,
payload: "".push_uint32(i))
}
# only extend stream window size
con << Frame.new(type: :window_update,
stream_id: stream.id,
payload: "".push_uint32(100)).assemble
# and extend connection window size
con << Frame.new(type: :window_update,
stream_id: 0,
payload: "".push_uint32(4*2+1)).assemble
last = sent_frames.last
assert_equal(3, last.payload.uint32)
}
end
def test_flow_control_update_send_initial_window_size
open_new_stream { |stream|
con = stream.connection
con << Frame.new(type: :settings,
stream_id: 0,
payload: "".push_uint16(Frame::SETTINGS_TYPE[:initial_window_size])
.push_uint32(4*2+1)).assemble
10.times { |i|
stream.send Frame.new(type: :data,
stream_id: stream.id,
payload: "".push_uint32(i))
}
# only extend stream window size
con << Frame.new(type: :window_update,
stream_id: stream.id,
payload: "".push_uint32(100)).assemble
# and update initial window size
con << Frame.new(type: :settings,
stream_id: 0,
payload: "".push_uint16(Frame::SETTINGS_TYPE[:initial_window_size])
.push_uint32(4*4+1)).assemble
last = sent_frames.reverse.find { |f| f.type == :data }
assert_equal(3, last.payload.uint32)
}
end
def test_flow_control_recv_window_exceeded
prepare = ->(&blk) {
open_new_stream { |stream|
con = stream.connection
con.settings(initial_window_size: 24)
blk.call(con, stream)
}
}
prepare.call { |con, stream|
con.window_update(500) # extend only connection
con << Frame.headers(stream.id, "", end_headers: true).assemble
assert_stream_error(:flow_control_error) {
con << Frame.data(stream.id, "\x00" * 30, end_stream: true).assemble
}
}
prepare.call { |con, stream|
stream.window_update(500) # extend only stream
con << Frame.headers(stream.id, "", end_headers: true).assemble
assert_connection_error(:flow_control_error) {
con << Frame.data(stream.id, "\x00" * 30, end_stream: true).assemble
}
}
end
def test_flow_control_update_recv_initial_window_size
open_new_stream { |stream|
con = stream.connection
con.settings(initial_window_size: 24)
stream.window_update(1)
con << Frame.headers(stream.id, "", end_headers: true).assemble
con << Frame.data(stream.id, "\x00" * 20, end_stream: true).assemble
assert_equal(4, con.recv_remaining_window)
assert_equal(5, stream.recv_remaining_window)
con.settings(initial_window_size: 60)
assert_equal(40, con.recv_remaining_window)
assert_equal(41, stream.recv_remaining_window)
}
end
end
|