xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/adapter/callback_visitor_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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