blob: 695ad7fdfa5a651c02a265d09d370d9452d8eaa3 [file] [log] [blame]
QUICHE team8a826a22021-05-06 12:47:45 -07001#include "http2/adapter/callback_visitor.h"
2
3#include "http2/adapter/mock_nghttp2_callbacks.h"
4#include "http2/adapter/test_utils.h"
5#include "common/platform/api/quiche_test.h"
6
7namespace http2 {
8namespace adapter {
9namespace test {
10namespace {
11
12using testing::_;
13
14enum FrameType {
15 DATA,
16 HEADERS,
17 PRIORITY,
18 RST_STREAM,
19 SETTINGS,
20 PUSH_PROMISE,
21 PING,
22 GOAWAY,
23 WINDOW_UPDATE,
24};
25
26// Tests connection-level events.
27TEST(ClientCallbackVisitorUnitTest, ConnectionFrames) {
28 testing::StrictMock<MockNghttp2Callbacks> callbacks;
29 CallbackVisitor visitor(Perspective::kClient,
QUICHE team2e32eb82021-06-07 13:30:31 -070030 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
QUICHE team8a826a22021-05-06 12:47:45 -070031
32 testing::InSequence seq;
33
34 // SETTINGS
35 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, SETTINGS, _)));
36 visitor.OnFrameHeader(0, 0, SETTINGS, 0);
37
38 visitor.OnSettingsStart();
39 EXPECT_CALL(callbacks, OnFrameRecv(IsSettings(testing::IsEmpty())));
40 visitor.OnSettingsEnd();
41
42 // PING
43 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, PING, _)));
44 visitor.OnFrameHeader(0, 8, PING, 0);
45
46 EXPECT_CALL(callbacks, OnFrameRecv(IsPing(42)));
47 visitor.OnPing(42, false);
48
49 // WINDOW_UPDATE
50 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, WINDOW_UPDATE, _)));
51 visitor.OnFrameHeader(0, 4, WINDOW_UPDATE, 0);
52
53 EXPECT_CALL(callbacks, OnFrameRecv(IsWindowUpdate(1000)));
54 visitor.OnWindowUpdate(0, 1000);
55
56 // PING ack
57 EXPECT_CALL(callbacks,
58 OnBeginFrame(HasFrameHeader(0, PING, NGHTTP2_FLAG_ACK)));
59 visitor.OnFrameHeader(0, 8, PING, 1);
60
61 EXPECT_CALL(callbacks, OnFrameRecv(IsPingAck(247)));
62 visitor.OnPing(247, true);
63
64 // GOAWAY
65 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, GOAWAY, 0)));
66 visitor.OnFrameHeader(0, 19, GOAWAY, 0);
67
68 EXPECT_CALL(callbacks, OnFrameRecv(IsGoAway(5, NGHTTP2_ENHANCE_YOUR_CALM,
69 "calm down!!")));
70 visitor.OnGoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!");
71}
72
73TEST(ClientCallbackVisitorUnitTest, StreamFrames) {
74 testing::StrictMock<MockNghttp2Callbacks> callbacks;
75 CallbackVisitor visitor(Perspective::kClient,
QUICHE team2e32eb82021-06-07 13:30:31 -070076 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
QUICHE team8a826a22021-05-06 12:47:45 -070077
78 testing::InSequence seq;
79
80 // HEADERS on stream 1
81 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, HEADERS, _)));
82 visitor.OnFrameHeader(1, 23, HEADERS, 4);
83
84 EXPECT_CALL(callbacks,
85 OnBeginHeaders(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
86 visitor.OnBeginHeadersForStream(1);
87
88 EXPECT_CALL(callbacks, OnHeader(_, ":status", "200", _));
89 visitor.OnHeaderForStream(1, ":status", "200");
90
91 EXPECT_CALL(callbacks, OnHeader(_, "server", "my-fake-server", _));
92 visitor.OnHeaderForStream(1, "server", "my-fake-server");
93
94 EXPECT_CALL(callbacks,
95 OnHeader(_, "date", "Tue, 6 Apr 2021 12:54:01 GMT", _));
96 visitor.OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT");
97
98 EXPECT_CALL(callbacks, OnHeader(_, "trailer", "x-server-status", _));
99 visitor.OnHeaderForStream(1, "trailer", "x-server-status");
100
101 EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
102 visitor.OnEndHeadersForStream(1);
103
104 // DATA for stream 1
105 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, DATA, 0)));
106 visitor.OnFrameHeader(1, 26, DATA, 0);
107
108 visitor.OnBeginDataForStream(1, 26);
109 EXPECT_CALL(callbacks, OnDataChunkRecv(0, 1, "This is the response body."));
110 EXPECT_CALL(callbacks, OnFrameRecv(IsData(1, _, 0)));
111 visitor.OnDataForStream(1, "This is the response body.");
112
113 // Trailers for stream 1, with a different nghttp2 "category".
114 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, HEADERS, _)));
115 visitor.OnFrameHeader(1, 23, HEADERS, 4);
116
117 EXPECT_CALL(callbacks, OnBeginHeaders(IsHeaders(1, _, NGHTTP2_HCAT_HEADERS)));
118 visitor.OnBeginHeadersForStream(1);
119
120 EXPECT_CALL(callbacks, OnHeader(_, "x-server-status", "OK", _));
121 visitor.OnHeaderForStream(1, "x-server-status", "OK");
122
123 EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, _, NGHTTP2_HCAT_HEADERS)));
124 visitor.OnEndHeadersForStream(1);
125
126 // RST_STREAM on stream 3
127 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(3, RST_STREAM, 0)));
128 visitor.OnFrameHeader(3, 4, RST_STREAM, 0);
129
130 EXPECT_CALL(callbacks, OnFrameRecv(IsRstStream(3, NGHTTP2_INTERNAL_ERROR)));
131 visitor.OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR);
132
133 EXPECT_CALL(callbacks, OnStreamClose(3, NGHTTP2_INTERNAL_ERROR));
134 visitor.OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR);
135
136 // More stream close events
137 EXPECT_CALL(callbacks,
138 OnBeginFrame(HasFrameHeader(1, DATA, NGHTTP2_FLAG_END_STREAM)));
139 visitor.OnFrameHeader(1, 0, DATA, 1);
140
141 EXPECT_CALL(callbacks, OnFrameRecv(IsData(1, _, NGHTTP2_FLAG_END_STREAM)));
142 visitor.OnBeginDataForStream(1, 0);
143 visitor.OnEndStream(1);
144
145 EXPECT_CALL(callbacks, OnStreamClose(1, NGHTTP2_NO_ERROR));
146 visitor.OnCloseStream(1, Http2ErrorCode::NO_ERROR);
147
148 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(5, RST_STREAM, _)));
149 visitor.OnFrameHeader(5, 4, RST_STREAM, 0);
150
151 EXPECT_CALL(callbacks, OnFrameRecv(IsRstStream(5, NGHTTP2_REFUSED_STREAM)));
152 visitor.OnRstStream(5, Http2ErrorCode::REFUSED_STREAM);
153
154 EXPECT_CALL(callbacks, OnStreamClose(5, NGHTTP2_REFUSED_STREAM));
155 visitor.OnCloseStream(5, Http2ErrorCode::REFUSED_STREAM);
156}
157
158TEST(ServerCallbackVisitorUnitTest, ConnectionFrames) {
159 testing::StrictMock<MockNghttp2Callbacks> callbacks;
160 CallbackVisitor visitor(Perspective::kServer,
QUICHE team2e32eb82021-06-07 13:30:31 -0700161 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
QUICHE team8a826a22021-05-06 12:47:45 -0700162
163 testing::InSequence seq;
164
165 // SETTINGS
166 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, SETTINGS, _)));
167 visitor.OnFrameHeader(0, 0, SETTINGS, 0);
168
169 visitor.OnSettingsStart();
170 EXPECT_CALL(callbacks, OnFrameRecv(IsSettings(testing::IsEmpty())));
171 visitor.OnSettingsEnd();
172
173 // PING
174 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, PING, _)));
175 visitor.OnFrameHeader(0, 8, PING, 0);
176
177 EXPECT_CALL(callbacks, OnFrameRecv(IsPing(42)));
178 visitor.OnPing(42, false);
179
180 // WINDOW_UPDATE
181 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, WINDOW_UPDATE, _)));
182 visitor.OnFrameHeader(0, 4, WINDOW_UPDATE, 0);
183
184 EXPECT_CALL(callbacks, OnFrameRecv(IsWindowUpdate(1000)));
185 visitor.OnWindowUpdate(0, 1000);
186
187 // PING ack
188 EXPECT_CALL(callbacks,
189 OnBeginFrame(HasFrameHeader(0, PING, NGHTTP2_FLAG_ACK)));
190 visitor.OnFrameHeader(0, 8, PING, 1);
191
192 EXPECT_CALL(callbacks, OnFrameRecv(IsPingAck(247)));
193 visitor.OnPing(247, true);
194}
195
196TEST(ServerCallbackVisitorUnitTest, StreamFrames) {
197 testing::StrictMock<MockNghttp2Callbacks> callbacks;
198 CallbackVisitor visitor(Perspective::kServer,
QUICHE team2e32eb82021-06-07 13:30:31 -0700199 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
QUICHE team8a826a22021-05-06 12:47:45 -0700200
201 testing::InSequence seq;
202
203 // HEADERS on stream 1
204 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(
205 1, HEADERS, NGHTTP2_FLAG_END_HEADERS)));
206 visitor.OnFrameHeader(1, 23, HEADERS, 4);
207
208 EXPECT_CALL(callbacks, OnBeginHeaders(IsHeaders(1, NGHTTP2_FLAG_END_HEADERS,
209 NGHTTP2_HCAT_REQUEST)));
210 visitor.OnBeginHeadersForStream(1);
211
212 EXPECT_CALL(callbacks, OnHeader(_, ":method", "POST", _));
213 visitor.OnHeaderForStream(1, ":method", "POST");
214
215 EXPECT_CALL(callbacks, OnHeader(_, ":path", "/example/path", _));
216 visitor.OnHeaderForStream(1, ":path", "/example/path");
217
218 EXPECT_CALL(callbacks, OnHeader(_, ":scheme", "https", _));
219 visitor.OnHeaderForStream(1, ":scheme", "https");
220
221 EXPECT_CALL(callbacks, OnHeader(_, ":authority", "example.com", _));
222 visitor.OnHeaderForStream(1, ":authority", "example.com");
223
224 EXPECT_CALL(callbacks, OnHeader(_, "accept", "text/html", _));
225 visitor.OnHeaderForStream(1, "accept", "text/html");
226
227 EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, NGHTTP2_FLAG_END_HEADERS,
228 NGHTTP2_HCAT_REQUEST)));
229 visitor.OnEndHeadersForStream(1);
230
231 // DATA on stream 1
232 EXPECT_CALL(callbacks,
233 OnBeginFrame(HasFrameHeader(1, DATA, NGHTTP2_FLAG_END_STREAM)));
234 visitor.OnFrameHeader(1, 25, DATA, NGHTTP2_FLAG_END_STREAM);
235
236 visitor.OnBeginDataForStream(1, 25);
237 EXPECT_CALL(callbacks, OnDataChunkRecv(NGHTTP2_FLAG_END_STREAM, 1,
238 "This is the request body."));
239 EXPECT_CALL(callbacks, OnFrameRecv(IsData(1, _, NGHTTP2_FLAG_END_STREAM)));
240 visitor.OnDataForStream(1, "This is the request body.");
241 visitor.OnEndStream(1);
242
243 EXPECT_CALL(callbacks, OnStreamClose(1, NGHTTP2_NO_ERROR));
244 visitor.OnCloseStream(1, Http2ErrorCode::NO_ERROR);
245
246 // RST_STREAM on stream 3
247 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(3, RST_STREAM, 0)));
248 visitor.OnFrameHeader(3, 4, RST_STREAM, 0);
249
250 EXPECT_CALL(callbacks, OnFrameRecv(IsRstStream(3, NGHTTP2_INTERNAL_ERROR)));
251 visitor.OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR);
252
253 EXPECT_CALL(callbacks, OnStreamClose(3, NGHTTP2_INTERNAL_ERROR));
254 visitor.OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR);
255}
256
257} // namespace
258} // namespace test
259} // namespace adapter
260} // namespace http2