1 #include "quiche/http2/adapter/callback_visitor.h"
2
3 #include "absl/container/flat_hash_map.h"
4 #include "quiche/http2/adapter/http2_protocol.h"
5 #include "quiche/http2/adapter/mock_nghttp2_callbacks.h"
6 #include "quiche/http2/adapter/nghttp2_adapter.h"
7 #include "quiche/http2/adapter/nghttp2_test_utils.h"
8 #include "quiche/http2/adapter/test_frame_sequence.h"
9 #include "quiche/http2/adapter/test_utils.h"
10 #include "quiche/common/platform/api/quiche_test.h"
11
12 namespace http2 {
13 namespace adapter {
14 namespace test {
15 namespace {
16
17 using testing::_;
18 using testing::IsEmpty;
19 using testing::Pair;
20 using testing::UnorderedElementsAre;
21
22 enum FrameType {
23 DATA,
24 HEADERS,
25 PRIORITY,
26 RST_STREAM,
27 SETTINGS,
28 PUSH_PROMISE,
29 PING,
30 GOAWAY,
31 WINDOW_UPDATE,
32 CONTINUATION,
33 };
34
35 // Tests connection-level events.
TEST(ClientCallbackVisitorUnitTest,ConnectionFrames)36 TEST(ClientCallbackVisitorUnitTest, ConnectionFrames) {
37 testing::StrictMock<MockNghttp2Callbacks> callbacks;
38 CallbackVisitor visitor(Perspective::kClient,
39 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
40
41 testing::InSequence seq;
42
43 // SETTINGS
44 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, SETTINGS, _)));
45 visitor.OnFrameHeader(0, 0, SETTINGS, 0);
46
47 visitor.OnSettingsStart();
48 EXPECT_CALL(callbacks, OnFrameRecv(IsSettings(testing::IsEmpty())));
49 visitor.OnSettingsEnd();
50
51 // PING
52 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, PING, _)));
53 visitor.OnFrameHeader(0, 8, PING, 0);
54
55 EXPECT_CALL(callbacks, OnFrameRecv(IsPing(42)));
56 visitor.OnPing(42, false);
57
58 // WINDOW_UPDATE
59 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, WINDOW_UPDATE, _)));
60 visitor.OnFrameHeader(0, 4, WINDOW_UPDATE, 0);
61
62 EXPECT_CALL(callbacks, OnFrameRecv(IsWindowUpdate(1000)));
63 visitor.OnWindowUpdate(0, 1000);
64
65 // PING ack
66 EXPECT_CALL(callbacks,
67 OnBeginFrame(HasFrameHeader(0, PING, NGHTTP2_FLAG_ACK)));
68 visitor.OnFrameHeader(0, 8, PING, 1);
69
70 EXPECT_CALL(callbacks, OnFrameRecv(IsPingAck(247)));
71 visitor.OnPing(247, true);
72
73 // GOAWAY
74 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, GOAWAY, 0)));
75 visitor.OnFrameHeader(0, 19, GOAWAY, 0);
76
77 EXPECT_CALL(callbacks, OnFrameRecv(IsGoAway(5, NGHTTP2_ENHANCE_YOUR_CALM,
78 "calm down!!")));
79 visitor.OnGoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!");
80
81 EXPECT_EQ(visitor.stream_map_size(), 0);
82 }
83
TEST(ClientCallbackVisitorUnitTest,StreamFrames)84 TEST(ClientCallbackVisitorUnitTest, StreamFrames) {
85 testing::StrictMock<MockNghttp2Callbacks> callbacks;
86 CallbackVisitor visitor(Perspective::kClient,
87 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
88 absl::flat_hash_map<Http2StreamId, int> stream_close_counts;
89 visitor.set_stream_close_listener(
90 [&stream_close_counts](Http2StreamId stream_id) {
91 ++stream_close_counts[stream_id];
92 });
93
94 testing::InSequence seq;
95
96 EXPECT_EQ(visitor.stream_map_size(), 0);
97
98 // HEADERS on stream 1
99 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, HEADERS, _)));
100 visitor.OnFrameHeader(1, 23, HEADERS, 4);
101
102 EXPECT_CALL(callbacks,
103 OnBeginHeaders(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
104 visitor.OnBeginHeadersForStream(1);
105
106 EXPECT_EQ(visitor.stream_map_size(), 1);
107
108 EXPECT_CALL(callbacks, OnHeader(_, ":status", "200", _));
109 visitor.OnHeaderForStream(1, ":status", "200");
110
111 EXPECT_CALL(callbacks, OnHeader(_, "server", "my-fake-server", _));
112 visitor.OnHeaderForStream(1, "server", "my-fake-server");
113
114 EXPECT_CALL(callbacks,
115 OnHeader(_, "date", "Tue, 6 Apr 2021 12:54:01 GMT", _));
116 visitor.OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT");
117
118 EXPECT_CALL(callbacks, OnHeader(_, "trailer", "x-server-status", _));
119 visitor.OnHeaderForStream(1, "trailer", "x-server-status");
120
121 EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
122 visitor.OnEndHeadersForStream(1);
123
124 // DATA for stream 1
125 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, DATA, 0)));
126 visitor.OnFrameHeader(1, 26, DATA, 0);
127
128 visitor.OnBeginDataForStream(1, 26);
129 EXPECT_CALL(callbacks, OnDataChunkRecv(0, 1, "This is the response body."));
130 EXPECT_CALL(callbacks, OnFrameRecv(IsData(1, _, 0)));
131 visitor.OnDataForStream(1, "This is the response body.");
132
133 // Trailers for stream 1, with a different nghttp2 "category".
134 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, HEADERS, _)));
135 visitor.OnFrameHeader(1, 23, HEADERS, 4);
136
137 EXPECT_CALL(callbacks, OnBeginHeaders(IsHeaders(1, _, NGHTTP2_HCAT_HEADERS)));
138 visitor.OnBeginHeadersForStream(1);
139
140 EXPECT_CALL(callbacks, OnHeader(_, "x-server-status", "OK", _));
141 visitor.OnHeaderForStream(1, "x-server-status", "OK");
142
143 EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, _, NGHTTP2_HCAT_HEADERS)));
144 visitor.OnEndHeadersForStream(1);
145
146 EXPECT_THAT(stream_close_counts, IsEmpty());
147
148 // RST_STREAM on stream 3
149 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(3, RST_STREAM, 0)));
150 visitor.OnFrameHeader(3, 4, RST_STREAM, 0);
151
152 // No change in stream map size.
153 EXPECT_EQ(visitor.stream_map_size(), 1);
154 EXPECT_THAT(stream_close_counts, IsEmpty());
155
156 EXPECT_CALL(callbacks, OnFrameRecv(IsRstStream(3, NGHTTP2_INTERNAL_ERROR)));
157 visitor.OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR);
158
159 EXPECT_CALL(callbacks, OnStreamClose(3, NGHTTP2_INTERNAL_ERROR));
160 visitor.OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR);
161
162 EXPECT_THAT(stream_close_counts, UnorderedElementsAre(Pair(3, 1)));
163
164 // More stream close events
165 EXPECT_CALL(callbacks,
166 OnBeginFrame(HasFrameHeader(1, DATA, NGHTTP2_FLAG_END_STREAM)));
167 visitor.OnFrameHeader(1, 0, DATA, 1);
168
169 EXPECT_CALL(callbacks, OnFrameRecv(IsData(1, _, NGHTTP2_FLAG_END_STREAM)));
170 visitor.OnBeginDataForStream(1, 0);
171 EXPECT_TRUE(visitor.OnEndStream(1));
172
173 EXPECT_CALL(callbacks, OnStreamClose(1, NGHTTP2_NO_ERROR));
174 visitor.OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR);
175
176 // Stream map is empty again after both streams were closed.
177 EXPECT_EQ(visitor.stream_map_size(), 0);
178 EXPECT_THAT(stream_close_counts,
179 UnorderedElementsAre(Pair(3, 1), Pair(1, 1)));
180
181 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(5, RST_STREAM, _)));
182 visitor.OnFrameHeader(5, 4, RST_STREAM, 0);
183
184 EXPECT_CALL(callbacks, OnFrameRecv(IsRstStream(5, NGHTTP2_REFUSED_STREAM)));
185 visitor.OnRstStream(5, Http2ErrorCode::REFUSED_STREAM);
186
187 EXPECT_CALL(callbacks, OnStreamClose(5, NGHTTP2_REFUSED_STREAM));
188 visitor.OnCloseStream(5, Http2ErrorCode::REFUSED_STREAM);
189
190 EXPECT_EQ(visitor.stream_map_size(), 0);
191 EXPECT_THAT(stream_close_counts,
192 UnorderedElementsAre(Pair(3, 1), Pair(1, 1), Pair(5, 1)));
193 }
194
TEST(ClientCallbackVisitorUnitTest,HeadersWithContinuation)195 TEST(ClientCallbackVisitorUnitTest, HeadersWithContinuation) {
196 testing::StrictMock<MockNghttp2Callbacks> callbacks;
197 CallbackVisitor visitor(Perspective::kClient,
198 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
199
200 testing::InSequence seq;
201
202 // HEADERS on stream 1
203 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, HEADERS, 0x0)));
204 ASSERT_TRUE(visitor.OnFrameHeader(1, 23, HEADERS, 0x0));
205
206 EXPECT_CALL(callbacks,
207 OnBeginHeaders(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
208 visitor.OnBeginHeadersForStream(1);
209
210 EXPECT_CALL(callbacks, OnHeader(_, ":status", "200", _));
211 visitor.OnHeaderForStream(1, ":status", "200");
212
213 EXPECT_CALL(callbacks, OnHeader(_, "server", "my-fake-server", _));
214 visitor.OnHeaderForStream(1, "server", "my-fake-server");
215
216 EXPECT_CALL(callbacks,
217 OnBeginFrame(HasFrameHeader(1, CONTINUATION, END_HEADERS_FLAG)));
218 ASSERT_TRUE(visitor.OnFrameHeader(1, 23, CONTINUATION, END_HEADERS_FLAG));
219
220 EXPECT_CALL(callbacks,
221 OnHeader(_, "date", "Tue, 6 Apr 2021 12:54:01 GMT", _));
222 visitor.OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT");
223
224 EXPECT_CALL(callbacks, OnHeader(_, "trailer", "x-server-status", _));
225 visitor.OnHeaderForStream(1, "trailer", "x-server-status");
226
227 EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
228 visitor.OnEndHeadersForStream(1);
229 }
230
TEST(ClientCallbackVisitorUnitTest,ContinuationNoHeaders)231 TEST(ClientCallbackVisitorUnitTest, ContinuationNoHeaders) {
232 testing::StrictMock<MockNghttp2Callbacks> callbacks;
233 CallbackVisitor visitor(Perspective::kClient,
234 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
235 // Because no stream precedes the CONTINUATION frame, the stream ID does not
236 // match, and the method returns false.
237 EXPECT_FALSE(visitor.OnFrameHeader(1, 23, CONTINUATION, END_HEADERS_FLAG));
238 }
239
TEST(ClientCallbackVisitorUnitTest,ContinuationWrongPrecedingType)240 TEST(ClientCallbackVisitorUnitTest, ContinuationWrongPrecedingType) {
241 testing::StrictMock<MockNghttp2Callbacks> callbacks;
242 CallbackVisitor visitor(Perspective::kClient,
243 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
244
245 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, WINDOW_UPDATE, _)));
246 visitor.OnFrameHeader(1, 4, WINDOW_UPDATE, 0);
247
248 // Because the CONTINUATION frame does not follow HEADERS, the method returns
249 // false.
250 EXPECT_FALSE(visitor.OnFrameHeader(1, 23, CONTINUATION, END_HEADERS_FLAG));
251 }
252
TEST(ClientCallbackVisitorUnitTest,ContinuationWrongStream)253 TEST(ClientCallbackVisitorUnitTest, ContinuationWrongStream) {
254 testing::StrictMock<MockNghttp2Callbacks> callbacks;
255 CallbackVisitor visitor(Perspective::kClient,
256 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
257 // HEADERS on stream 1
258 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, HEADERS, 0x0)));
259 ASSERT_TRUE(visitor.OnFrameHeader(1, 23, HEADERS, 0x0));
260
261 EXPECT_CALL(callbacks,
262 OnBeginHeaders(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
263 visitor.OnBeginHeadersForStream(1);
264
265 EXPECT_CALL(callbacks, OnHeader(_, ":status", "200", _));
266 visitor.OnHeaderForStream(1, ":status", "200");
267
268 EXPECT_CALL(callbacks, OnHeader(_, "server", "my-fake-server", _));
269 visitor.OnHeaderForStream(1, "server", "my-fake-server");
270
271 // The CONTINUATION stream ID does not match the one from the HEADERS.
272 EXPECT_FALSE(visitor.OnFrameHeader(3, 23, CONTINUATION, END_HEADERS_FLAG));
273 }
274
TEST(ClientCallbackVisitorUnitTest,ResetAndGoaway)275 TEST(ClientCallbackVisitorUnitTest, ResetAndGoaway) {
276 testing::StrictMock<MockNghttp2Callbacks> callbacks;
277 CallbackVisitor visitor(Perspective::kClient,
278 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
279
280 testing::InSequence seq;
281
282 // RST_STREAM on stream 1
283 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, RST_STREAM, 0x0)));
284 EXPECT_TRUE(visitor.OnFrameHeader(1, 13, RST_STREAM, 0x0));
285
286 EXPECT_CALL(callbacks, OnFrameRecv(IsRstStream(1, NGHTTP2_INTERNAL_ERROR)));
287 visitor.OnRstStream(1, Http2ErrorCode::INTERNAL_ERROR);
288
289 EXPECT_CALL(callbacks, OnStreamClose(1, NGHTTP2_INTERNAL_ERROR));
290 EXPECT_TRUE(visitor.OnCloseStream(1, Http2ErrorCode::INTERNAL_ERROR));
291
292 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, GOAWAY, 0x0)));
293 EXPECT_TRUE(visitor.OnFrameHeader(0, 13, GOAWAY, 0x0));
294
295 EXPECT_CALL(callbacks,
296 OnFrameRecv(IsGoAway(3, NGHTTP2_ENHANCE_YOUR_CALM, "calma te")));
297 EXPECT_TRUE(
298 visitor.OnGoAway(3, Http2ErrorCode::ENHANCE_YOUR_CALM, "calma te"));
299
300 EXPECT_CALL(callbacks, OnStreamClose(5, NGHTTP2_STREAM_CLOSED))
301 .WillOnce(testing::Return(NGHTTP2_ERR_CALLBACK_FAILURE));
302 EXPECT_FALSE(visitor.OnCloseStream(5, Http2ErrorCode::STREAM_CLOSED));
303 }
304
TEST(ServerCallbackVisitorUnitTest,ConnectionFrames)305 TEST(ServerCallbackVisitorUnitTest, ConnectionFrames) {
306 testing::StrictMock<MockNghttp2Callbacks> callbacks;
307 CallbackVisitor visitor(Perspective::kServer,
308 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
309
310 testing::InSequence seq;
311
312 // SETTINGS
313 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, SETTINGS, _)));
314 visitor.OnFrameHeader(0, 0, SETTINGS, 0);
315
316 visitor.OnSettingsStart();
317 EXPECT_CALL(callbacks, OnFrameRecv(IsSettings(testing::IsEmpty())));
318 visitor.OnSettingsEnd();
319
320 // PING
321 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, PING, _)));
322 visitor.OnFrameHeader(0, 8, PING, 0);
323
324 EXPECT_CALL(callbacks, OnFrameRecv(IsPing(42)));
325 visitor.OnPing(42, false);
326
327 // WINDOW_UPDATE
328 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, WINDOW_UPDATE, _)));
329 visitor.OnFrameHeader(0, 4, WINDOW_UPDATE, 0);
330
331 EXPECT_CALL(callbacks, OnFrameRecv(IsWindowUpdate(1000)));
332 visitor.OnWindowUpdate(0, 1000);
333
334 // PING ack
335 EXPECT_CALL(callbacks,
336 OnBeginFrame(HasFrameHeader(0, PING, NGHTTP2_FLAG_ACK)));
337 visitor.OnFrameHeader(0, 8, PING, 1);
338
339 EXPECT_CALL(callbacks, OnFrameRecv(IsPingAck(247)));
340 visitor.OnPing(247, true);
341
342 EXPECT_EQ(visitor.stream_map_size(), 0);
343 }
344
TEST(ServerCallbackVisitorUnitTest,StreamFrames)345 TEST(ServerCallbackVisitorUnitTest, StreamFrames) {
346 testing::StrictMock<MockNghttp2Callbacks> callbacks;
347 CallbackVisitor visitor(Perspective::kServer,
348 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
349
350 testing::InSequence seq;
351
352 // HEADERS on stream 1
353 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(
354 1, HEADERS, NGHTTP2_FLAG_END_HEADERS)));
355 visitor.OnFrameHeader(1, 23, HEADERS, 4);
356
357 EXPECT_CALL(callbacks, OnBeginHeaders(IsHeaders(1, NGHTTP2_FLAG_END_HEADERS,
358 NGHTTP2_HCAT_REQUEST)));
359 visitor.OnBeginHeadersForStream(1);
360
361 EXPECT_EQ(visitor.stream_map_size(), 1);
362
363 EXPECT_CALL(callbacks, OnHeader(_, ":method", "POST", _));
364 visitor.OnHeaderForStream(1, ":method", "POST");
365
366 EXPECT_CALL(callbacks, OnHeader(_, ":path", "/example/path", _));
367 visitor.OnHeaderForStream(1, ":path", "/example/path");
368
369 EXPECT_CALL(callbacks, OnHeader(_, ":scheme", "https", _));
370 visitor.OnHeaderForStream(1, ":scheme", "https");
371
372 EXPECT_CALL(callbacks, OnHeader(_, ":authority", "example.com", _));
373 visitor.OnHeaderForStream(1, ":authority", "example.com");
374
375 EXPECT_CALL(callbacks, OnHeader(_, "accept", "text/html", _));
376 visitor.OnHeaderForStream(1, "accept", "text/html");
377
378 EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, NGHTTP2_FLAG_END_HEADERS,
379 NGHTTP2_HCAT_REQUEST)));
380 visitor.OnEndHeadersForStream(1);
381
382 // DATA on stream 1
383 EXPECT_CALL(callbacks,
384 OnBeginFrame(HasFrameHeader(1, DATA, NGHTTP2_FLAG_END_STREAM)));
385 visitor.OnFrameHeader(1, 25, DATA, NGHTTP2_FLAG_END_STREAM);
386
387 visitor.OnBeginDataForStream(1, 25);
388 EXPECT_CALL(callbacks, OnDataChunkRecv(NGHTTP2_FLAG_END_STREAM, 1,
389 "This is the request body."));
390 EXPECT_CALL(callbacks, OnFrameRecv(IsData(1, _, NGHTTP2_FLAG_END_STREAM)));
391 visitor.OnDataForStream(1, "This is the request body.");
392 EXPECT_TRUE(visitor.OnEndStream(1));
393
394 EXPECT_CALL(callbacks, OnStreamClose(1, NGHTTP2_NO_ERROR));
395 visitor.OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR);
396
397 EXPECT_EQ(visitor.stream_map_size(), 0);
398
399 // RST_STREAM on stream 3
400 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(3, RST_STREAM, 0)));
401 visitor.OnFrameHeader(3, 4, RST_STREAM, 0);
402
403 EXPECT_CALL(callbacks, OnFrameRecv(IsRstStream(3, NGHTTP2_INTERNAL_ERROR)));
404 visitor.OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR);
405
406 EXPECT_CALL(callbacks, OnStreamClose(3, NGHTTP2_INTERNAL_ERROR));
407 visitor.OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR);
408
409 EXPECT_EQ(visitor.stream_map_size(), 0);
410 }
411
TEST(ServerCallbackVisitorUnitTest,DataWithPadding)412 TEST(ServerCallbackVisitorUnitTest, DataWithPadding) {
413 testing::StrictMock<MockNghttp2Callbacks> callbacks;
414 CallbackVisitor visitor(Perspective::kServer,
415 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
416
417 const size_t kPaddingLength = 39;
418 const uint8_t kFlags = NGHTTP2_FLAG_PADDED | NGHTTP2_FLAG_END_STREAM;
419
420 testing::InSequence seq;
421
422 // DATA on stream 1
423 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, DATA, kFlags)));
424 EXPECT_TRUE(visitor.OnFrameHeader(1, 25 + kPaddingLength, DATA, kFlags));
425
426 EXPECT_TRUE(visitor.OnBeginDataForStream(1, 25 + kPaddingLength));
427
428 // Padding before data.
429 EXPECT_TRUE(visitor.OnDataPaddingLength(1, kPaddingLength));
430
431 EXPECT_CALL(callbacks,
432 OnDataChunkRecv(kFlags, 1, "This is the request body."));
433 EXPECT_CALL(callbacks, OnFrameRecv(IsData(1, _, kFlags, kPaddingLength)));
434 EXPECT_TRUE(visitor.OnDataForStream(1, "This is the request body."));
435 EXPECT_TRUE(visitor.OnEndStream(1));
436
437 EXPECT_CALL(callbacks, OnStreamClose(1, NGHTTP2_NO_ERROR));
438 visitor.OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR);
439
440 // DATA on stream 3
441 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(3, DATA, kFlags)));
442 EXPECT_TRUE(visitor.OnFrameHeader(3, 25 + kPaddingLength, DATA, kFlags));
443
444 EXPECT_TRUE(visitor.OnBeginDataForStream(3, 25 + kPaddingLength));
445
446 // Data before padding.
447 EXPECT_CALL(callbacks,
448 OnDataChunkRecv(kFlags, 3, "This is the request body."));
449 EXPECT_TRUE(visitor.OnDataForStream(3, "This is the request body."));
450
451 EXPECT_CALL(callbacks, OnFrameRecv(IsData(3, _, kFlags, kPaddingLength)));
452 EXPECT_TRUE(visitor.OnDataPaddingLength(3, kPaddingLength));
453 EXPECT_TRUE(visitor.OnEndStream(3));
454
455 EXPECT_CALL(callbacks, OnStreamClose(3, NGHTTP2_NO_ERROR));
456 visitor.OnCloseStream(3, Http2ErrorCode::HTTP2_NO_ERROR);
457
458 // DATA on stream 5
459 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(5, DATA, kFlags)));
460 EXPECT_TRUE(visitor.OnFrameHeader(5, 25 + kPaddingLength, DATA, kFlags));
461
462 EXPECT_TRUE(visitor.OnBeginDataForStream(5, 25 + kPaddingLength));
463
464 // Error during padding.
465 EXPECT_CALL(callbacks,
466 OnDataChunkRecv(kFlags, 5, "This is the request body."));
467 EXPECT_TRUE(visitor.OnDataForStream(5, "This is the request body."));
468
469 EXPECT_CALL(callbacks, OnFrameRecv(IsData(5, _, kFlags, kPaddingLength)))
470 .WillOnce(testing::Return(NGHTTP2_ERR_CALLBACK_FAILURE));
471 EXPECT_TRUE(visitor.OnDataPaddingLength(5, kPaddingLength));
472 EXPECT_FALSE(visitor.OnEndStream(3));
473
474 EXPECT_CALL(callbacks, OnStreamClose(5, NGHTTP2_NO_ERROR));
475 visitor.OnCloseStream(5, Http2ErrorCode::HTTP2_NO_ERROR);
476 }
477
478 // In the case of a Content-Length mismatch where the header value is larger
479 // than the actual data for the stream, nghttp2 will call
480 // `on_begin_frame_callback` and `on_data_chunk_recv_callback`, but not the
481 // `on_frame_recv_callback`.
TEST(ServerCallbackVisitorUnitTest,MismatchedContentLengthCallbacks)482 TEST(ServerCallbackVisitorUnitTest, MismatchedContentLengthCallbacks) {
483 testing::StrictMock<MockNghttp2Callbacks> callbacks;
484 CallbackVisitor visitor(Perspective::kServer,
485 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
486 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
487
488 const std::string frames = TestFrameSequence()
489 .ClientPreface()
490 .Headers(1,
491 {{":method", "POST"},
492 {":scheme", "https"},
493 {":authority", "example.com"},
494 {":path", "/"},
495 {"content-length", "50"}},
496 /*fin=*/false)
497 .Data(1, "Less than 50 bytes.", true)
498 .Serialize();
499
500 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(0, SETTINGS, _)));
501
502 EXPECT_CALL(callbacks, OnFrameRecv(IsSettings(testing::IsEmpty())));
503
504 // HEADERS on stream 1
505 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(
506 1, HEADERS, NGHTTP2_FLAG_END_HEADERS)));
507
508 EXPECT_CALL(callbacks, OnBeginHeaders(IsHeaders(1, NGHTTP2_FLAG_END_HEADERS,
509 NGHTTP2_HCAT_REQUEST)));
510
511 EXPECT_CALL(callbacks, OnHeader(_, ":method", "POST", _));
512 EXPECT_CALL(callbacks, OnHeader(_, ":path", "/", _));
513 EXPECT_CALL(callbacks, OnHeader(_, ":scheme", "https", _));
514 EXPECT_CALL(callbacks, OnHeader(_, ":authority", "example.com", _));
515 EXPECT_CALL(callbacks, OnHeader(_, "content-length", "50", _));
516 EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, NGHTTP2_FLAG_END_HEADERS,
517 NGHTTP2_HCAT_REQUEST)));
518
519 // DATA on stream 1
520 EXPECT_CALL(callbacks,
521 OnBeginFrame(HasFrameHeader(1, DATA, NGHTTP2_FLAG_END_STREAM)));
522
523 EXPECT_CALL(callbacks, OnDataChunkRecv(NGHTTP2_FLAG_END_STREAM, 1,
524 "Less than 50 bytes."));
525
526 // Like nghttp2, CallbackVisitor does not pass on a call to OnFrameRecv in the
527 // case of Content-Length mismatch.
528
529 int64_t result = adapter->ProcessBytes(frames);
530 EXPECT_EQ(frames.size(), result);
531 }
532
TEST(ServerCallbackVisitorUnitTest,HeadersAfterFin)533 TEST(ServerCallbackVisitorUnitTest, HeadersAfterFin) {
534 testing::StrictMock<MockNghttp2Callbacks> callbacks;
535 CallbackVisitor visitor(Perspective::kServer,
536 *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
537
538 testing::InSequence seq;
539
540 // HEADERS on stream 1
541 EXPECT_CALL(
542 callbacks,
543 OnBeginFrame(HasFrameHeader(
544 1, HEADERS, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM)));
545 visitor.OnFrameHeader(1, 23, HEADERS, 5);
546
547 EXPECT_CALL(callbacks,
548 OnBeginHeaders(IsHeaders(
549 1, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
550 NGHTTP2_HCAT_REQUEST)));
551 EXPECT_TRUE(visitor.OnBeginHeadersForStream(1));
552
553 EXPECT_EQ(visitor.stream_map_size(), 1);
554
555 EXPECT_CALL(callbacks, OnHeader).Times(5);
556 visitor.OnHeaderForStream(1, ":method", "POST");
557 visitor.OnHeaderForStream(1, ":path", "/example/path");
558 visitor.OnHeaderForStream(1, ":scheme", "https");
559 visitor.OnHeaderForStream(1, ":authority", "example.com");
560 visitor.OnHeaderForStream(1, "accept", "text/html");
561
562 EXPECT_CALL(callbacks,
563 OnFrameRecv(IsHeaders(
564 1, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM,
565 NGHTTP2_HCAT_REQUEST)));
566 visitor.OnEndHeadersForStream(1);
567
568 EXPECT_TRUE(visitor.OnEndStream(1));
569
570 EXPECT_CALL(callbacks, OnStreamClose(1, NGHTTP2_NO_ERROR));
571 visitor.OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR);
572
573 EXPECT_EQ(visitor.stream_map_size(), 0);
574
575 // Invalid repeat HEADERS on closed stream 1
576 EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(
577 1, HEADERS, NGHTTP2_FLAG_END_HEADERS)));
578 visitor.OnFrameHeader(1, 23, HEADERS, 4);
579
580 EXPECT_CALL(callbacks, OnBeginHeaders(IsHeaders(1, NGHTTP2_FLAG_END_HEADERS,
581 NGHTTP2_HCAT_HEADERS)));
582 EXPECT_TRUE(visitor.OnBeginHeadersForStream(1));
583
584 // The visitor should not revive streams that have already been closed.
585 EXPECT_EQ(visitor.stream_map_size(), 0);
586 }
587
588 } // namespace
589 } // namespace test
590 } // namespace adapter
591 } // namespace http2
592