1 #include "quiche/http2/adapter/nghttp2_adapter.h"
2
3 #include <memory>
4
5 #include "quiche/http2/adapter/http2_protocol.h"
6 #include "quiche/http2/adapter/http2_visitor_interface.h"
7 #include "quiche/http2/adapter/mock_http2_visitor.h"
8 #include "quiche/http2/adapter/nghttp2.h"
9 #include "quiche/http2/adapter/nghttp2_test_utils.h"
10 #include "quiche/http2/adapter/oghttp2_util.h"
11 #include "quiche/http2/adapter/test_frame_sequence.h"
12 #include "quiche/http2/adapter/test_utils.h"
13 #include "quiche/common/platform/api/quiche_test.h"
14
15 namespace http2 {
16 namespace adapter {
17 namespace test {
18 namespace {
19
20 using ConnectionError = Http2VisitorInterface::ConnectionError;
21
22 using spdy::SpdyFrameType;
23 using testing::_;
24
25 enum FrameType {
26 DATA,
27 HEADERS,
28 PRIORITY,
29 RST_STREAM,
30 SETTINGS,
31 PUSH_PROMISE,
32 PING,
33 GOAWAY,
34 WINDOW_UPDATE,
35 CONTINUATION,
36 };
37
38 // This send callback assumes |source|'s pointer is a TestDataSource, and
39 // |user_data| is a Http2VisitorInterface.
TestSendCallback(nghttp2_session *,nghttp2_frame *,const uint8_t * framehd,size_t length,nghttp2_data_source * source,void * user_data)40 int TestSendCallback(nghttp2_session*, nghttp2_frame* /*frame*/,
41 const uint8_t* framehd, size_t length,
42 nghttp2_data_source* source, void* user_data) {
43 auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
44 // Send the frame header via the visitor.
45 ssize_t result = visitor->OnReadyToSend(ToStringView(framehd, 9));
46 if (result == 0) {
47 return NGHTTP2_ERR_WOULDBLOCK;
48 }
49 auto* test_source = static_cast<TestDataSource*>(source->ptr);
50 absl::string_view payload = test_source->ReadNext(length);
51 // Send the frame payload via the visitor.
52 visitor->OnReadyToSend(payload);
53 return 0;
54 }
55
TEST(NgHttp2AdapterTest,ClientConstruction)56 TEST(NgHttp2AdapterTest, ClientConstruction) {
57 testing::StrictMock<MockHttp2Visitor> visitor;
58 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
59 ASSERT_NE(nullptr, adapter);
60 EXPECT_TRUE(adapter->want_read());
61 EXPECT_FALSE(adapter->want_write());
62 EXPECT_FALSE(adapter->IsServerSession());
63 }
64
TEST(NgHttp2AdapterTest,ClientHandlesFrames)65 TEST(NgHttp2AdapterTest, ClientHandlesFrames) {
66 DataSavingVisitor visitor;
67 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
68 int result = adapter->Send();
69 EXPECT_EQ(0, result);
70 EXPECT_THAT(visitor.data(),
71 testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
72 visitor.Clear();
73
74 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
75
76 const std::string initial_frames = TestFrameSequence()
77 .ServerPreface()
78 .Ping(42)
79 .WindowUpdate(0, 1000)
80 .Serialize();
81 testing::InSequence s;
82
83 // Server preface (empty SETTINGS)
84 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
85 EXPECT_CALL(visitor, OnSettingsStart());
86 EXPECT_CALL(visitor, OnSettingsEnd());
87
88 EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
89 EXPECT_CALL(visitor, OnPing(42, false));
90 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
91 EXPECT_CALL(visitor, OnWindowUpdate(0, 1000));
92
93 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
94 EXPECT_EQ(initial_frames.size(), initial_result);
95
96 EXPECT_EQ(adapter->GetSendWindowSize(), kInitialFlowControlWindowSize + 1000);
97
98 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
99 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
100 EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, 8, 0x1));
101 EXPECT_CALL(visitor, OnFrameSent(PING, 0, 8, 0x1, 0));
102
103 result = adapter->Send();
104 // Some bytes should have been serialized.
105 EXPECT_EQ(0, result);
106 EXPECT_THAT(visitor.data(),
107 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::PING}));
108 visitor.Clear();
109
110 const std::vector<Header> headers1 =
111 ToHeaders({{":method", "GET"},
112 {":scheme", "http"},
113 {":authority", "example.com"},
114 {":path", "/this/is/request/one"}});
115
116 const std::vector<Header> headers2 =
117 ToHeaders({{":method", "GET"},
118 {":scheme", "http"},
119 {":authority", "example.com"},
120 {":path", "/this/is/request/two"}});
121
122 const std::vector<Header> headers3 =
123 ToHeaders({{":method", "GET"},
124 {":scheme", "http"},
125 {":authority", "example.com"},
126 {":path", "/this/is/request/three"}});
127
128 const char* kSentinel1 = "arbitrary pointer 1";
129 const char* kSentinel3 = "arbitrary pointer 3";
130 const int32_t stream_id1 =
131 adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
132 ASSERT_GT(stream_id1, 0);
133 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
134
135 const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
136 ASSERT_GT(stream_id2, 0);
137 QUICHE_LOG(INFO) << "Created stream: " << stream_id2;
138
139 const int32_t stream_id3 =
140 adapter->SubmitRequest(headers3, nullptr, const_cast<char*>(kSentinel3));
141 ASSERT_GT(stream_id3, 0);
142 QUICHE_LOG(INFO) << "Created stream: " << stream_id3;
143
144 const char* kSentinel2 = "arbitrary pointer 2";
145 adapter->SetStreamUserData(stream_id2, const_cast<char*>(kSentinel2));
146 adapter->SetStreamUserData(stream_id3, nullptr);
147
148 EXPECT_EQ(adapter->sources_size(), 3);
149
150 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
151 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
152 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id2, _, 0x5));
153 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id2, _, 0x5, 0));
154 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id3, _, 0x5));
155 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id3, _, 0x5, 0));
156
157 result = adapter->Send();
158 EXPECT_EQ(0, result);
159 EXPECT_THAT(visitor.data(),
160 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::HEADERS,
161 SpdyFrameType::HEADERS}));
162 visitor.Clear();
163
164 // All streams are active and have not yet received any data, so the receive
165 // window should be at the initial value.
166 EXPECT_EQ(kInitialFlowControlWindowSize,
167 adapter->GetStreamReceiveWindowSize(stream_id1));
168 EXPECT_EQ(kInitialFlowControlWindowSize,
169 adapter->GetStreamReceiveWindowSize(stream_id2));
170 EXPECT_EQ(kInitialFlowControlWindowSize,
171 adapter->GetStreamReceiveWindowSize(stream_id3));
172
173 // Upper bound on the flow control receive window should be the initial value.
174 EXPECT_EQ(kInitialFlowControlWindowSize,
175 adapter->GetStreamReceiveWindowLimit(stream_id1));
176
177 // Connection has not yet received any data.
178 EXPECT_EQ(kInitialFlowControlWindowSize, adapter->GetReceiveWindowSize());
179
180 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
181
182 EXPECT_EQ(kSentinel1, adapter->GetStreamUserData(stream_id1));
183 EXPECT_EQ(kSentinel2, adapter->GetStreamUserData(stream_id2));
184 EXPECT_EQ(nullptr, adapter->GetStreamUserData(stream_id3));
185
186 EXPECT_EQ(0, adapter->GetHpackDecoderDynamicTableSize());
187
188 const std::string stream_frames =
189 TestFrameSequence()
190 .Headers(1,
191 {{":status", "200"},
192 {"server", "my-fake-server"},
193 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
194 /*fin=*/false)
195 .Data(1, "This is the response body.")
196 .RstStream(3, Http2ErrorCode::INTERNAL_ERROR)
197 .GoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!")
198 .Serialize();
199
200 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
201 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
202 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
203 EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
204 EXPECT_CALL(visitor,
205 OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
206 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
207 EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 0));
208 EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
209 EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
210 EXPECT_CALL(visitor, OnFrameHeader(3, 4, RST_STREAM, 0));
211 EXPECT_CALL(visitor, OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR));
212 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR))
213 .WillOnce(
214 [&adapter](Http2StreamId stream_id, Http2ErrorCode /*error_code*/) {
215 adapter->RemoveStream(stream_id);
216 return true;
217 });
218 EXPECT_CALL(visitor, OnFrameHeader(0, 19, GOAWAY, 0));
219 EXPECT_CALL(visitor,
220 OnGoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!"));
221 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
222 EXPECT_EQ(stream_frames.size(), stream_result);
223
224 // First stream has received some data.
225 EXPECT_GT(kInitialFlowControlWindowSize,
226 adapter->GetStreamReceiveWindowSize(stream_id1));
227 // Second stream was closed.
228 EXPECT_EQ(-1, adapter->GetStreamReceiveWindowSize(stream_id2));
229 // Third stream has not received any data.
230 EXPECT_EQ(kInitialFlowControlWindowSize,
231 adapter->GetStreamReceiveWindowSize(stream_id3));
232
233 // One stream was closed.
234 EXPECT_EQ(adapter->sources_size(), 2);
235
236 // Connection window should be the same as the first stream.
237 EXPECT_EQ(adapter->GetReceiveWindowSize(),
238 adapter->GetStreamReceiveWindowSize(stream_id1));
239
240 // Upper bound on the flow control receive window should still be the initial
241 // value.
242 EXPECT_EQ(kInitialFlowControlWindowSize,
243 adapter->GetStreamReceiveWindowLimit(stream_id1));
244
245 EXPECT_GT(adapter->GetHpackDecoderDynamicTableSize(), 0);
246
247 // Should be 3, but this method only works for server adapters.
248 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
249
250 // Even though the client recieved a GOAWAY, streams 1 and 5 are still active.
251 EXPECT_TRUE(adapter->want_read());
252
253 EXPECT_CALL(visitor, OnFrameHeader(1, 0, DATA, 1));
254 EXPECT_CALL(visitor, OnBeginDataForStream(1, 0));
255 EXPECT_CALL(visitor, OnEndStream(1));
256 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR))
257 .WillOnce(
258 [&adapter](Http2StreamId stream_id, Http2ErrorCode /*error_code*/) {
259 adapter->RemoveStream(stream_id);
260 return true;
261 });
262 EXPECT_CALL(visitor, OnFrameHeader(5, 4, RST_STREAM, 0));
263 EXPECT_CALL(visitor, OnRstStream(5, Http2ErrorCode::REFUSED_STREAM));
264 EXPECT_CALL(visitor, OnCloseStream(5, Http2ErrorCode::REFUSED_STREAM))
265 .WillOnce(
266 [&adapter](Http2StreamId stream_id, Http2ErrorCode /*error_code*/) {
267 adapter->RemoveStream(stream_id);
268 return true;
269 });
270 adapter->ProcessBytes(TestFrameSequence()
271 .Data(1, "", true)
272 .RstStream(5, Http2ErrorCode::REFUSED_STREAM)
273 .Serialize());
274
275 // Should be 5, but this method only works for server adapters.
276 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
277
278 // After receiving END_STREAM for 1 and RST_STREAM for 5, the session no
279 // longer expects reads.
280 EXPECT_FALSE(adapter->want_read());
281 EXPECT_EQ(adapter->sources_size(), 0);
282
283 // Client will not have anything else to write.
284 EXPECT_FALSE(adapter->want_write());
285 result = adapter->Send();
286 EXPECT_EQ(0, result);
287 EXPECT_THAT(visitor.data(), testing::IsEmpty());
288 }
289
TEST(NgHttp2AdapterTest,QueuingWindowUpdateAffectsWindow)290 TEST(NgHttp2AdapterTest, QueuingWindowUpdateAffectsWindow) {
291 DataSavingVisitor visitor;
292 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
293
294 EXPECT_EQ(adapter->GetReceiveWindowSize(), kInitialFlowControlWindowSize);
295 adapter->SubmitWindowUpdate(0, 10000);
296 EXPECT_EQ(adapter->GetReceiveWindowSize(),
297 kInitialFlowControlWindowSize + 10000);
298
299 const std::vector<Header> headers =
300 ToHeaders({{":method", "GET"},
301 {":scheme", "http"},
302 {":authority", "example.com"},
303 {":path", "/this/is/request/one"}});
304 const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
305
306 EXPECT_CALL(visitor, OnBeforeFrameSent(WINDOW_UPDATE, 0, 4, 0x0));
307 EXPECT_CALL(visitor, OnFrameSent(WINDOW_UPDATE, 0, 4, 0x0, 0));
308 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
309 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
310
311 int result = adapter->Send();
312 EXPECT_EQ(0, result);
313
314 EXPECT_EQ(adapter->GetStreamReceiveWindowSize(stream_id),
315 kInitialFlowControlWindowSize);
316 adapter->SubmitWindowUpdate(1, 20000);
317 EXPECT_EQ(adapter->GetStreamReceiveWindowSize(stream_id),
318 kInitialFlowControlWindowSize + 20000);
319 }
320
TEST(NgHttp2AdapterTest,AckOfSettingInitialWindowSizeAffectsWindow)321 TEST(NgHttp2AdapterTest, AckOfSettingInitialWindowSizeAffectsWindow) {
322 DataSavingVisitor visitor;
323 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
324
325 testing::InSequence s;
326
327 const std::vector<Header> headers =
328 ToHeaders({{":method", "GET"},
329 {":scheme", "http"},
330 {":authority", "example.com"},
331 {":path", "/this/is/request/one"}});
332 const int32_t stream_id1 = adapter->SubmitRequest(headers, nullptr, nullptr);
333
334 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
335 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
336
337 int result = adapter->Send();
338 EXPECT_EQ(0, result);
339
340 const std::string initial_frames =
341 TestFrameSequence().ServerPreface().Serialize();
342 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0x0));
343 EXPECT_CALL(visitor, OnSettingsStart());
344 EXPECT_CALL(visitor, OnSettingsEnd());
345
346 int64_t parse_result = adapter->ProcessBytes(initial_frames);
347 EXPECT_EQ(initial_frames.size(), static_cast<size_t>(parse_result));
348
349 EXPECT_EQ(adapter->GetStreamReceiveWindowSize(stream_id1),
350 kInitialFlowControlWindowSize);
351 adapter->SubmitSettings({{INITIAL_WINDOW_SIZE, 80000u}});
352 // No update for the first stream, yet.
353 EXPECT_EQ(adapter->GetStreamReceiveWindowSize(stream_id1),
354 kInitialFlowControlWindowSize);
355
356 // Ack of server's initial settings.
357 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
358 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
359
360 // Outbound SETTINGS containing INITIAL_WINDOW_SIZE.
361 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
362 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
363
364 result = adapter->Send();
365 EXPECT_EQ(0, result);
366
367 // Still no update, as a SETTINGS ack has not yet been received.
368 EXPECT_EQ(adapter->GetStreamReceiveWindowSize(stream_id1),
369 kInitialFlowControlWindowSize);
370
371 const std::string settings_ack =
372 TestFrameSequence().SettingsAck().Serialize();
373
374 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0x1));
375 EXPECT_CALL(visitor, OnSettingsAck);
376
377 parse_result = adapter->ProcessBytes(settings_ack);
378 EXPECT_EQ(settings_ack.size(), static_cast<size_t>(parse_result));
379
380 // Stream window has been updated.
381 EXPECT_EQ(adapter->GetStreamReceiveWindowSize(stream_id1), 80000);
382
383 const std::vector<Header> headers2 =
384 ToHeaders({{":method", "GET"},
385 {":scheme", "http"},
386 {":authority", "example.com"},
387 {":path", "/this/is/request/two"}});
388 const int32_t stream_id2 = adapter->SubmitRequest(headers, nullptr, nullptr);
389
390 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id2, _, 0x5));
391 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id2, _, 0x5, 0));
392 result = adapter->Send();
393 EXPECT_EQ(0, result);
394
395 EXPECT_EQ(adapter->GetStreamReceiveWindowSize(stream_id2), 80000);
396 }
397
TEST(NgHttp2AdapterTest,ClientRejects100HeadersWithFin)398 TEST(NgHttp2AdapterTest, ClientRejects100HeadersWithFin) {
399 DataSavingVisitor visitor;
400 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
401
402 testing::InSequence s;
403
404 const std::vector<Header> headers1 =
405 ToHeaders({{":method", "GET"},
406 {":scheme", "http"},
407 {":authority", "example.com"},
408 {":path", "/this/is/request/one"}});
409
410 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
411 ASSERT_GT(stream_id1, 0);
412 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
413
414 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
415 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
416
417 int result = adapter->Send();
418 EXPECT_EQ(0, result);
419 visitor.Clear();
420
421 const std::string stream_frames =
422 TestFrameSequence()
423 .ServerPreface()
424 .Headers(1, {{":status", "100"}}, /*fin=*/false)
425 .Headers(1, {{":status", "100"}}, /*fin=*/true)
426 .Serialize();
427
428 // Server preface (empty SETTINGS)
429 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
430 EXPECT_CALL(visitor, OnSettingsStart());
431 EXPECT_CALL(visitor, OnSettingsEnd());
432
433 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
434 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
435 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "100"));
436 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
437
438 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
439 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
440 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "100"));
441 EXPECT_CALL(visitor,
442 OnInvalidFrame(
443 1, Http2VisitorInterface::InvalidFrameError::kHttpMessaging));
444
445 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
446 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
447
448 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
449 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
450 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
451 EXPECT_CALL(visitor, OnFrameSent(RST_STREAM, 1, _, 0x0, 1));
452 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
453
454 EXPECT_TRUE(adapter->want_write());
455 result = adapter->Send();
456 EXPECT_EQ(0, result);
457 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
458 SpdyFrameType::RST_STREAM}));
459 }
460
TEST(NgHttp2AdapterTest,ClientRejects100HeadersWithContent)461 TEST(NgHttp2AdapterTest, ClientRejects100HeadersWithContent) {
462 DataSavingVisitor visitor;
463 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
464
465 testing::InSequence s;
466
467 const std::vector<Header> headers1 =
468 ToHeaders({{":method", "GET"},
469 {":scheme", "http"},
470 {":authority", "example.com"},
471 {":path", "/this/is/request/one"}});
472
473 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
474 ASSERT_GT(stream_id1, 0);
475
476 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
477 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
478
479 int result = adapter->Send();
480 EXPECT_EQ(0, result);
481 visitor.Clear();
482
483 const std::string stream_frames =
484 TestFrameSequence()
485 .ServerPreface()
486 .Headers(1, {{":status", "100"}},
487 /*fin=*/false)
488 .Data(1, "We needed the final headers before data, whoops")
489 .Serialize();
490
491 // Server preface (empty SETTINGS)
492 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
493 EXPECT_CALL(visitor, OnSettingsStart());
494 EXPECT_CALL(visitor, OnSettingsEnd());
495
496 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
497 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
498 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "100"));
499 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
500 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0));
501 EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
502
503 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
504 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
505
506 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
507 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
508 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
509 EXPECT_CALL(visitor,
510 OnFrameSent(RST_STREAM, 1, _, 0x0,
511 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
512 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
513
514 EXPECT_TRUE(adapter->want_write());
515 result = adapter->Send();
516 EXPECT_EQ(0, result);
517 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
518 SpdyFrameType::RST_STREAM}));
519 }
520
TEST(NgHttp2AdapterTest,ClientRejects100HeadersWithContentLength)521 TEST(NgHttp2AdapterTest, ClientRejects100HeadersWithContentLength) {
522 DataSavingVisitor visitor;
523 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
524
525 testing::InSequence s;
526
527 const std::vector<Header> headers1 =
528 ToHeaders({{":method", "GET"},
529 {":scheme", "http"},
530 {":authority", "example.com"},
531 {":path", "/this/is/request/one"}});
532
533 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
534 ASSERT_GT(stream_id1, 0);
535
536 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
537 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
538
539 int result = adapter->Send();
540 EXPECT_EQ(0, result);
541 visitor.Clear();
542
543 const std::string stream_frames =
544 TestFrameSequence()
545 .ServerPreface()
546 .Headers(1, {{":status", "100"}, {"content-length", "42"}},
547 /*fin=*/false)
548 .Headers(1,
549 {{":status", "200"},
550 {"server", "my-fake-server"},
551 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
552 /*fin=*/true)
553 .Serialize();
554
555 // Server preface (empty SETTINGS)
556 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
557 EXPECT_CALL(visitor, OnSettingsStart());
558 EXPECT_CALL(visitor, OnSettingsEnd());
559
560 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
561 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
562 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "100"));
563 EXPECT_CALL(
564 visitor,
565 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
566 "stream: 1, name: [content-length], value: [42]"));
567 EXPECT_CALL(
568 visitor,
569 OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
570 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
571
572 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
573 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
574
575 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
576 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
577 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
578 EXPECT_CALL(visitor,
579 OnFrameSent(RST_STREAM, 1, _, 0x0,
580 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
581 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
582
583 EXPECT_TRUE(adapter->want_write());
584 result = adapter->Send();
585 EXPECT_EQ(0, result);
586 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
587 SpdyFrameType::RST_STREAM}));
588 }
589
TEST(NgHttp2AdapterTest,ClientHandles204WithContent)590 TEST(NgHttp2AdapterTest, ClientHandles204WithContent) {
591 DataSavingVisitor visitor;
592 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
593
594 testing::InSequence s;
595
596 const std::vector<Header> headers1 =
597 ToHeaders({{":method", "GET"},
598 {":scheme", "http"},
599 {":authority", "example.com"},
600 {":path", "/this/is/request/one"}});
601
602 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
603 ASSERT_GT(stream_id1, 0);
604
605 const std::vector<Header> headers2 =
606 ToHeaders({{":method", "GET"},
607 {":scheme", "http"},
608 {":authority", "example.com"},
609 {":path", "/this/is/request/two"}});
610
611 const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
612 ASSERT_GT(stream_id2, stream_id1);
613
614 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
615 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
616 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id2, _, 0x5));
617 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id2, _, 0x5, 0));
618
619 int result = adapter->Send();
620 EXPECT_EQ(0, result);
621 visitor.Clear();
622
623 const std::string stream_frames =
624 TestFrameSequence()
625 .ServerPreface()
626 .Headers(1, {{":status", "204"}, {"content-length", "2"}},
627 /*fin=*/false)
628 .Data(1, "hi")
629 .Headers(3, {{":status", "204"}}, /*fin=*/false)
630 .Data(3, "hi")
631 .Serialize();
632
633 // Server preface (empty SETTINGS)
634 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
635 EXPECT_CALL(visitor, OnSettingsStart());
636 EXPECT_CALL(visitor, OnSettingsEnd());
637
638 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
639 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
640 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "204"));
641 EXPECT_CALL(
642 visitor,
643 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
644 "stream: 1, name: [content-length], value: [2]"));
645 EXPECT_CALL(
646 visitor,
647 OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
648 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 4));
649 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
650 EXPECT_CALL(visitor, OnHeaderForStream(3, ":status", "204"));
651 EXPECT_CALL(visitor, OnEndHeadersForStream(3));
652 EXPECT_CALL(visitor, OnFrameHeader(3, _, DATA, 0));
653 EXPECT_CALL(visitor, OnBeginDataForStream(3, 2));
654
655 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
656 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
657
658 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
659 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
660 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
661 EXPECT_CALL(visitor,
662 OnFrameSent(RST_STREAM, 1, _, 0x0,
663 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
664 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
665 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 3, _, 0x0));
666 EXPECT_CALL(visitor,
667 OnFrameSent(RST_STREAM, 3, _, 0x0,
668 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
669 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::PROTOCOL_ERROR));
670
671 EXPECT_TRUE(adapter->want_write());
672 result = adapter->Send();
673 EXPECT_EQ(0, result);
674 EXPECT_THAT(visitor.data(),
675 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::RST_STREAM,
676 SpdyFrameType::RST_STREAM}));
677 }
678
TEST(NgHttp2AdapterTest,ClientHandles304WithContent)679 TEST(NgHttp2AdapterTest, ClientHandles304WithContent) {
680 DataSavingVisitor visitor;
681 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
682
683 testing::InSequence s;
684
685 const std::vector<Header> headers1 =
686 ToHeaders({{":method", "GET"},
687 {":scheme", "http"},
688 {":authority", "example.com"},
689 {":path", "/this/is/request/one"}});
690
691 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
692 ASSERT_GT(stream_id1, 0);
693
694 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
695 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
696
697 int result = adapter->Send();
698 EXPECT_EQ(0, result);
699 visitor.Clear();
700
701 const std::string stream_frames =
702 TestFrameSequence()
703 .ServerPreface()
704 .Headers(1, {{":status", "304"}, {"content-length", "2"}},
705 /*fin=*/false)
706 .Data(1, "hi")
707 .Serialize();
708
709 // Server preface (empty SETTINGS)
710 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
711 EXPECT_CALL(visitor, OnSettingsStart());
712 EXPECT_CALL(visitor, OnSettingsEnd());
713
714 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
715 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
716 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "304"));
717 EXPECT_CALL(visitor, OnHeaderForStream(1, "content-length", "2"));
718 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
719 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0));
720 EXPECT_CALL(visitor, OnBeginDataForStream(1, 2));
721
722 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
723 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
724
725 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
726 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
727 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
728 EXPECT_CALL(visitor,
729 OnFrameSent(RST_STREAM, 1, _, 0x0,
730 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
731 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
732
733 EXPECT_TRUE(adapter->want_write());
734 result = adapter->Send();
735 EXPECT_EQ(0, result);
736 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
737 SpdyFrameType::RST_STREAM}));
738 }
739
TEST(NgHttp2AdapterTest,ClientHandles304WithContentLength)740 TEST(NgHttp2AdapterTest, ClientHandles304WithContentLength) {
741 DataSavingVisitor visitor;
742 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
743
744 testing::InSequence s;
745
746 const std::vector<Header> headers =
747 ToHeaders({{":method", "GET"},
748 {":scheme", "http"},
749 {":authority", "example.com"},
750 {":path", "/this/is/request/one"}});
751
752 const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
753 ASSERT_GT(stream_id, 0);
754
755 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
756 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
757
758 int result = adapter->Send();
759 EXPECT_EQ(0, result);
760 visitor.Clear();
761
762 const std::string stream_frames =
763 TestFrameSequence()
764 .ServerPreface()
765 .Headers(1, {{":status", "304"}, {"content-length", "2"}},
766 /*fin=*/true)
767 .Serialize();
768
769 // Server preface (empty SETTINGS)
770 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
771 EXPECT_CALL(visitor, OnSettingsStart());
772 EXPECT_CALL(visitor, OnSettingsEnd());
773
774 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
775 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
776 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "304"));
777 EXPECT_CALL(visitor, OnHeaderForStream(1, "content-length", "2"));
778 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
779 EXPECT_CALL(visitor, OnEndStream(1));
780 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
781
782 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
783 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
784
785 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
786 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
787
788 EXPECT_TRUE(adapter->want_write());
789 result = adapter->Send();
790 EXPECT_EQ(0, result);
791 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
792 }
793
TEST(NgHttp2AdapterTest,ClientHandlesTrailers)794 TEST(NgHttp2AdapterTest, ClientHandlesTrailers) {
795 DataSavingVisitor visitor;
796 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
797
798 testing::InSequence s;
799
800 const std::vector<Header> headers1 =
801 ToHeaders({{":method", "GET"},
802 {":scheme", "http"},
803 {":authority", "example.com"},
804 {":path", "/this/is/request/one"}});
805
806 const char* kSentinel1 = "arbitrary pointer 1";
807 const int32_t stream_id1 =
808 adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
809 ASSERT_GT(stream_id1, 0);
810 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
811
812 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
813 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
814
815 int result = adapter->Send();
816 EXPECT_EQ(0, result);
817 absl::string_view data = visitor.data();
818 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
819 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
820 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
821 visitor.Clear();
822
823 const std::string stream_frames =
824 TestFrameSequence()
825 .ServerPreface()
826 .Headers(1,
827 {{":status", "200"},
828 {"server", "my-fake-server"},
829 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
830 /*fin=*/false)
831 .Data(1, "This is the response body.")
832 .Headers(1, {{"final-status", "A-OK"}},
833 /*fin=*/true)
834 .Serialize();
835
836 // Server preface (empty SETTINGS)
837 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
838 EXPECT_CALL(visitor, OnSettingsStart());
839 EXPECT_CALL(visitor, OnSettingsEnd());
840
841 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
842 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
843 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
844 EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
845 EXPECT_CALL(visitor,
846 OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
847 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
848 EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 0));
849 EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
850 EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
851 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
852 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
853 EXPECT_CALL(visitor, OnHeaderForStream(1, "final-status", "A-OK"));
854 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
855 EXPECT_CALL(visitor, OnEndStream(1));
856 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
857
858 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
859 EXPECT_EQ(stream_frames.size(), stream_result);
860
861 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
862 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
863
864 EXPECT_TRUE(adapter->want_write());
865 result = adapter->Send();
866 EXPECT_EQ(0, result);
867 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
868 }
869
TEST(NgHttp2AdapterTest,ClientSendsTrailers)870 TEST(NgHttp2AdapterTest, ClientSendsTrailers) {
871 DataSavingVisitor visitor;
872 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
873
874 testing::InSequence s;
875
876 const std::vector<Header> headers1 =
877 ToHeaders({{":method", "GET"},
878 {":scheme", "http"},
879 {":authority", "example.com"},
880 {":path", "/this/is/request/one"}});
881
882 const std::string kBody = "This is an example request body.";
883 auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
884 body1->AppendPayload(kBody);
885 // nghttp2 does not require that the data source indicate the end of data
886 // before trailers are enqueued.
887
888 const int32_t stream_id1 =
889 adapter->SubmitRequest(headers1, std::move(body1), nullptr);
890 ASSERT_GT(stream_id1, 0);
891
892 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x4));
893 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x4, 0));
894 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id1, _, 0x0, 0));
895
896 int result = adapter->Send();
897 EXPECT_EQ(0, result);
898 absl::string_view data = visitor.data();
899 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
900 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
901 EXPECT_THAT(data,
902 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
903 visitor.Clear();
904
905 const std::vector<Header> trailers1 =
906 ToHeaders({{"extra-info", "Trailers are weird but good?"}});
907 adapter->SubmitTrailer(stream_id1, trailers1);
908
909 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
910 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
911
912 result = adapter->Send();
913 EXPECT_EQ(0, result);
914 data = visitor.data();
915 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
916 }
917
TEST(NgHttp2AdapterTest,ClientHandlesMetadata)918 TEST(NgHttp2AdapterTest, ClientHandlesMetadata) {
919 DataSavingVisitor visitor;
920 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
921
922 testing::InSequence s;
923
924 const std::vector<Header> headers1 =
925 ToHeaders({{":method", "GET"},
926 {":scheme", "http"},
927 {":authority", "example.com"},
928 {":path", "/this/is/request/one"}});
929
930 const char* kSentinel1 = "arbitrary pointer 1";
931 const int32_t stream_id1 =
932 adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
933 ASSERT_GT(stream_id1, 0);
934 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
935
936 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
937 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
938
939 int result = adapter->Send();
940 EXPECT_EQ(0, result);
941 absl::string_view data = visitor.data();
942 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
943 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
944 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
945 visitor.Clear();
946
947 const std::string stream_frames =
948 TestFrameSequence()
949 .ServerPreface()
950 .Metadata(0, "Example connection metadata")
951 .Headers(1,
952 {{":status", "200"},
953 {"server", "my-fake-server"},
954 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
955 /*fin=*/false)
956 .Metadata(1, "Example stream metadata")
957 .Data(1, "This is the response body.", true)
958 .Serialize();
959
960 // Server preface (empty SETTINGS)
961 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
962 EXPECT_CALL(visitor, OnSettingsStart());
963 EXPECT_CALL(visitor, OnSettingsEnd());
964
965 EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
966 EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
967 EXPECT_CALL(visitor, OnMetadataForStream(0, _));
968 EXPECT_CALL(visitor, OnMetadataEndForStream(0));
969 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
970 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
971 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
972 EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
973 EXPECT_CALL(visitor,
974 OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
975 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
976 EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
977 EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
978 EXPECT_CALL(visitor, OnMetadataForStream(1, _));
979 EXPECT_CALL(visitor, OnMetadataEndForStream(1));
980 EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 1));
981 EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
982 EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
983 EXPECT_CALL(visitor, OnEndStream(1));
984 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
985
986 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
987 EXPECT_EQ(stream_frames.size(), stream_result);
988
989 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
990 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
991
992 EXPECT_TRUE(adapter->want_write());
993 result = adapter->Send();
994 EXPECT_EQ(0, result);
995 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
996 }
997
TEST(NgHttp2AdapterTest,ClientHandlesMetadataWithEmptyPayload)998 TEST(NgHttp2AdapterTest, ClientHandlesMetadataWithEmptyPayload) {
999 DataSavingVisitor visitor;
1000 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1001
1002 testing::InSequence s;
1003
1004 const std::vector<Header> headers1 =
1005 ToHeaders({{":method", "GET"},
1006 {":scheme", "http"},
1007 {":authority", "example.com"},
1008 {":path", "/this/is/request/one"}});
1009
1010 const int32_t stream_id = adapter->SubmitRequest(headers1, nullptr, nullptr);
1011 ASSERT_GT(stream_id, 0);
1012
1013 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
1014 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
1015
1016 int result = adapter->Send();
1017 EXPECT_EQ(0, result);
1018 absl::string_view data = visitor.data();
1019 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1020 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1021 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
1022 visitor.Clear();
1023
1024 const std::string stream_frames =
1025 TestFrameSequence()
1026 .ServerPreface()
1027 .Headers(1,
1028 {{":status", "200"},
1029 {"server", "my-fake-server"},
1030 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
1031 /*fin=*/false)
1032 .Metadata(1, "")
1033 .Data(1, "This is the response body.", true)
1034 .Serialize();
1035
1036 // Server preface (empty SETTINGS)
1037 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1038 EXPECT_CALL(visitor, OnSettingsStart());
1039 EXPECT_CALL(visitor, OnSettingsEnd());
1040
1041 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
1042 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
1043 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(3);
1044 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
1045 EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
1046 EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
1047 EXPECT_CALL(visitor, OnMetadataEndForStream(1));
1048 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 1));
1049 EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
1050 EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
1051 EXPECT_CALL(visitor, OnEndStream(1));
1052 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
1053
1054 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1055 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
1056 }
1057
TEST(NgHttp2AdapterTest,ClientHandlesMetadataWithError)1058 TEST(NgHttp2AdapterTest, ClientHandlesMetadataWithError) {
1059 DataSavingVisitor visitor;
1060 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1061
1062 testing::InSequence s;
1063
1064 const std::vector<Header> headers1 =
1065 ToHeaders({{":method", "GET"},
1066 {":scheme", "http"},
1067 {":authority", "example.com"},
1068 {":path", "/this/is/request/one"}});
1069
1070 const char* kSentinel1 = "arbitrary pointer 1";
1071 const int32_t stream_id1 =
1072 adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
1073 ASSERT_GT(stream_id1, 0);
1074 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
1075
1076 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1077 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1078
1079 int result = adapter->Send();
1080 EXPECT_EQ(0, result);
1081 visitor.Clear();
1082
1083 const std::string stream_frames =
1084 TestFrameSequence()
1085 .ServerPreface()
1086 .Metadata(0, "Example connection metadata")
1087 .Headers(1,
1088 {{":status", "200"},
1089 {"server", "my-fake-server"},
1090 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
1091 /*fin=*/false)
1092 .Metadata(1, "Example stream metadata")
1093 .Data(1, "This is the response body.", true)
1094 .Serialize();
1095
1096 // Server preface (empty SETTINGS)
1097 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1098 EXPECT_CALL(visitor, OnSettingsStart());
1099 EXPECT_CALL(visitor, OnSettingsEnd());
1100
1101 EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
1102 EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
1103 EXPECT_CALL(visitor, OnMetadataForStream(0, _));
1104 EXPECT_CALL(visitor, OnMetadataEndForStream(0));
1105 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
1106 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
1107 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
1108 EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
1109 EXPECT_CALL(visitor,
1110 OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
1111 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
1112 EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
1113 EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
1114 EXPECT_CALL(visitor, OnMetadataForStream(1, _))
1115 .WillOnce(testing::Return(false));
1116 // Remaining frames are not processed due to the error.
1117 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
1118
1119 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1120 // The false return from OnMetadataForStream() results in a connection error.
1121 EXPECT_EQ(stream_result, NGHTTP2_ERR_CALLBACK_FAILURE);
1122
1123 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
1124 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
1125
1126 EXPECT_TRUE(adapter->want_write());
1127 EXPECT_TRUE(adapter->want_read()); // Even after an error. Why?
1128 result = adapter->Send();
1129 EXPECT_EQ(0, result);
1130 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
1131 }
1132
TEST(NgHttp2AdapterTest,ClientHandlesHpackHeaderTableSetting)1133 TEST(NgHttp2AdapterTest, ClientHandlesHpackHeaderTableSetting) {
1134 DataSavingVisitor visitor;
1135 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1136
1137 testing::InSequence s;
1138
1139 const std::vector<Header> headers1 = ToHeaders({
1140 {":method", "GET"},
1141 {":scheme", "http"},
1142 {":authority", "example.com"},
1143 {":path", "/this/is/request/one"},
1144 {"x-i-do-not-like", "green eggs and ham"},
1145 {"x-i-will-not-eat-them", "here or there, in a box, with a fox"},
1146 {"x-like-them-in-a-house", "no"},
1147 {"x-like-them-with-a-mouse", "no"},
1148 });
1149
1150 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
1151 ASSERT_GT(stream_id1, 0);
1152
1153 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1154 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1155
1156 int result = adapter->Send();
1157 EXPECT_EQ(0, result);
1158 visitor.Clear();
1159
1160 EXPECT_GT(adapter->GetHpackEncoderDynamicTableSize(), 100);
1161
1162 const std::string stream_frames =
1163 TestFrameSequence().Settings({{HEADER_TABLE_SIZE, 100u}}).Serialize();
1164 // Server preface (SETTINGS)
1165 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
1166 EXPECT_CALL(visitor, OnSettingsStart());
1167 EXPECT_CALL(visitor, OnSetting(Http2Setting{HEADER_TABLE_SIZE, 100u}));
1168
1169 EXPECT_CALL(visitor, OnSettingsEnd());
1170
1171 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1172 EXPECT_EQ(stream_frames.size(), stream_result);
1173
1174 EXPECT_LE(adapter->GetHpackEncoderDynamicTableSize(), 100);
1175 }
1176
TEST(NgHttp2AdapterTest,ClientHandlesInvalidTrailers)1177 TEST(NgHttp2AdapterTest, ClientHandlesInvalidTrailers) {
1178 DataSavingVisitor visitor;
1179 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1180
1181 testing::InSequence s;
1182
1183 const std::vector<Header> headers1 =
1184 ToHeaders({{":method", "GET"},
1185 {":scheme", "http"},
1186 {":authority", "example.com"},
1187 {":path", "/this/is/request/one"}});
1188
1189 const char* kSentinel1 = "arbitrary pointer 1";
1190 const int32_t stream_id1 =
1191 adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
1192 ASSERT_GT(stream_id1, 0);
1193 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
1194
1195 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1196 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1197
1198 int result = adapter->Send();
1199 EXPECT_EQ(0, result);
1200 absl::string_view data = visitor.data();
1201 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1202 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1203 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
1204 visitor.Clear();
1205
1206 const std::string stream_frames =
1207 TestFrameSequence()
1208 .ServerPreface()
1209 .Headers(1,
1210 {{":status", "200"},
1211 {"server", "my-fake-server"},
1212 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
1213 /*fin=*/false)
1214 .Data(1, "This is the response body.")
1215 .Headers(1, {{":bad-status", "9000"}},
1216 /*fin=*/true)
1217 .Serialize();
1218
1219 // Server preface (empty SETTINGS)
1220 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1221 EXPECT_CALL(visitor, OnSettingsStart());
1222 EXPECT_CALL(visitor, OnSettingsEnd());
1223
1224 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
1225 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
1226 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
1227 EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
1228 EXPECT_CALL(visitor,
1229 OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
1230 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
1231 EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 0));
1232 EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
1233 EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
1234 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
1235 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
1236 EXPECT_CALL(
1237 visitor,
1238 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
1239 "stream: 1, name: [:bad-status], value: [9000]"));
1240 EXPECT_CALL(
1241 visitor,
1242 OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
1243
1244 // Bad status trailer will cause a PROTOCOL_ERROR. The header is never
1245 // delivered in an OnHeaderForStream callback.
1246
1247 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1248 EXPECT_EQ(stream_frames.size(), stream_result);
1249
1250 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
1251 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
1252 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, stream_id1, 4, 0x0));
1253 EXPECT_CALL(visitor, OnFrameSent(RST_STREAM, stream_id1, 4, 0x0, 1));
1254 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
1255
1256 EXPECT_TRUE(adapter->want_write());
1257 result = adapter->Send();
1258 EXPECT_EQ(0, result);
1259 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
1260 SpdyFrameType::RST_STREAM}));
1261 }
1262
TEST(NgHttp2AdapterTest,ClientRstStreamWhileHandlingHeaders)1263 TEST(NgHttp2AdapterTest, ClientRstStreamWhileHandlingHeaders) {
1264 DataSavingVisitor visitor;
1265 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1266
1267 testing::InSequence s;
1268
1269 const std::vector<Header> headers1 =
1270 ToHeaders({{":method", "GET"},
1271 {":scheme", "http"},
1272 {":authority", "example.com"},
1273 {":path", "/this/is/request/one"}});
1274
1275 const char* kSentinel1 = "arbitrary pointer 1";
1276 const int32_t stream_id1 =
1277 adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
1278 ASSERT_GT(stream_id1, 0);
1279 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
1280
1281 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1282 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1283
1284 int result = adapter->Send();
1285 EXPECT_EQ(0, result);
1286 absl::string_view data = visitor.data();
1287 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1288 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1289 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
1290 visitor.Clear();
1291
1292 const std::string stream_frames =
1293 TestFrameSequence()
1294 .ServerPreface()
1295 .Headers(1,
1296 {{":status", "200"},
1297 {"server", "my-fake-server"},
1298 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
1299 /*fin=*/false)
1300 .Data(1, "This is the response body.")
1301 .Serialize();
1302
1303 // Server preface (empty SETTINGS)
1304 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1305 EXPECT_CALL(visitor, OnSettingsStart());
1306 EXPECT_CALL(visitor, OnSettingsEnd());
1307
1308 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
1309 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
1310 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
1311 EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
1312 EXPECT_CALL(visitor,
1313 OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"))
1314 .WillOnce(testing::DoAll(
1315 testing::InvokeWithoutArgs([&adapter]() {
1316 adapter->SubmitRst(1, Http2ErrorCode::REFUSED_STREAM);
1317 }),
1318 testing::Return(Http2VisitorInterface::HEADER_RST_STREAM)));
1319
1320 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1321 EXPECT_EQ(stream_frames.size(), stream_result);
1322
1323 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
1324 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
1325 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, stream_id1, 4, 0x0));
1326 EXPECT_CALL(visitor,
1327 OnFrameSent(RST_STREAM, stream_id1, 4, 0x0,
1328 static_cast<int>(Http2ErrorCode::REFUSED_STREAM)));
1329 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::REFUSED_STREAM));
1330
1331 EXPECT_TRUE(adapter->want_write());
1332 result = adapter->Send();
1333 EXPECT_EQ(0, result);
1334 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
1335 SpdyFrameType::RST_STREAM}));
1336 }
1337
TEST(NgHttp2AdapterTest,ClientConnectionErrorWhileHandlingHeaders)1338 TEST(NgHttp2AdapterTest, ClientConnectionErrorWhileHandlingHeaders) {
1339 DataSavingVisitor visitor;
1340 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1341
1342 testing::InSequence s;
1343
1344 const std::vector<Header> headers1 =
1345 ToHeaders({{":method", "GET"},
1346 {":scheme", "http"},
1347 {":authority", "example.com"},
1348 {":path", "/this/is/request/one"}});
1349
1350 const char* kSentinel1 = "arbitrary pointer 1";
1351 const int32_t stream_id1 =
1352 adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
1353 ASSERT_GT(stream_id1, 0);
1354 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
1355
1356 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1357 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1358
1359 int result = adapter->Send();
1360 EXPECT_EQ(0, result);
1361 absl::string_view data = visitor.data();
1362 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1363 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1364 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
1365 visitor.Clear();
1366
1367 const std::string stream_frames =
1368 TestFrameSequence()
1369 .ServerPreface()
1370 .Headers(1,
1371 {{":status", "200"},
1372 {"server", "my-fake-server"},
1373 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
1374 /*fin=*/false)
1375 .Data(1, "This is the response body.")
1376 .Serialize();
1377
1378 // Server preface (empty SETTINGS)
1379 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1380 EXPECT_CALL(visitor, OnSettingsStart());
1381 EXPECT_CALL(visitor, OnSettingsEnd());
1382
1383 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
1384 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
1385 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
1386 EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
1387 EXPECT_CALL(visitor,
1388 OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"))
1389 .WillOnce(
1390 testing::Return(Http2VisitorInterface::HEADER_CONNECTION_ERROR));
1391 // Translation to nghttp2 treats this error as a general parsing error.
1392 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
1393
1394 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1395 EXPECT_EQ(-902 /* NGHTTP2_ERR_CALLBACK_FAILURE */, stream_result);
1396
1397 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
1398 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
1399
1400 EXPECT_TRUE(adapter->want_write());
1401 result = adapter->Send();
1402 EXPECT_EQ(0, result);
1403 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
1404 }
1405
TEST(NgHttp2AdapterTest,ClientConnectionErrorWhileHandlingHeadersOnly)1406 TEST(NgHttp2AdapterTest, ClientConnectionErrorWhileHandlingHeadersOnly) {
1407 DataSavingVisitor visitor;
1408 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1409
1410 testing::InSequence s;
1411
1412 const std::vector<Header> headers1 =
1413 ToHeaders({{":method", "GET"},
1414 {":scheme", "http"},
1415 {":authority", "example.com"},
1416 {":path", "/this/is/request/one"}});
1417
1418 const char* kSentinel1 = "arbitrary pointer 1";
1419 const int32_t stream_id1 =
1420 adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
1421 ASSERT_GT(stream_id1, 0);
1422 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
1423
1424 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1425 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1426
1427 int result = adapter->Send();
1428 EXPECT_EQ(0, result);
1429 absl::string_view data = visitor.data();
1430 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1431 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1432 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
1433 visitor.Clear();
1434
1435 const std::string stream_frames =
1436 TestFrameSequence()
1437 .ServerPreface()
1438 .Headers(1,
1439 {{":status", "200"},
1440 {"server", "my-fake-server"},
1441 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
1442 /*fin=*/true)
1443 .Serialize();
1444
1445 // Server preface (empty SETTINGS)
1446 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1447 EXPECT_CALL(visitor, OnSettingsStart());
1448 EXPECT_CALL(visitor, OnSettingsEnd());
1449
1450 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
1451 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
1452 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
1453 EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
1454 EXPECT_CALL(visitor,
1455 OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"))
1456 .WillOnce(
1457 testing::Return(Http2VisitorInterface::HEADER_CONNECTION_ERROR));
1458 // Translation to nghttp2 treats this error as a general parsing error.
1459 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
1460
1461 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1462 EXPECT_EQ(-902 /* NGHTTP2_ERR_CALLBACK_FAILURE */, stream_result);
1463
1464 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
1465 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
1466
1467 EXPECT_TRUE(adapter->want_write());
1468 result = adapter->Send();
1469 EXPECT_EQ(0, result);
1470 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
1471 }
1472
TEST(NgHttp2AdapterTest,ClientRejectsHeaders)1473 TEST(NgHttp2AdapterTest, ClientRejectsHeaders) {
1474 DataSavingVisitor visitor;
1475 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1476
1477 testing::InSequence s;
1478
1479 const std::vector<Header> headers1 =
1480 ToHeaders({{":method", "GET"},
1481 {":scheme", "http"},
1482 {":authority", "example.com"},
1483 {":path", "/this/is/request/one"}});
1484
1485 const char* kSentinel1 = "arbitrary pointer 1";
1486 const int32_t stream_id1 =
1487 adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
1488 ASSERT_GT(stream_id1, 0);
1489 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
1490
1491 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1492 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1493
1494 int result = adapter->Send();
1495 EXPECT_EQ(0, result);
1496 absl::string_view data = visitor.data();
1497 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1498 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1499 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
1500 visitor.Clear();
1501
1502 const std::string stream_frames =
1503 TestFrameSequence()
1504 .ServerPreface()
1505 .Headers(1,
1506 {{":status", "200"},
1507 {"server", "my-fake-server"},
1508 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
1509 /*fin=*/false)
1510 .Data(1, "This is the response body.")
1511 .Serialize();
1512
1513 // Server preface (empty SETTINGS)
1514 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1515 EXPECT_CALL(visitor, OnSettingsStart());
1516 EXPECT_CALL(visitor, OnSettingsEnd());
1517
1518 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
1519 EXPECT_CALL(visitor, OnBeginHeadersForStream(1))
1520 .WillOnce(testing::Return(false));
1521 // Rejecting headers leads to a connection error.
1522 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
1523
1524 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1525 EXPECT_EQ(NGHTTP2_ERR_CALLBACK_FAILURE, stream_result);
1526
1527 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
1528 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
1529
1530 EXPECT_TRUE(adapter->want_write());
1531 result = adapter->Send();
1532 EXPECT_EQ(0, result);
1533 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
1534 }
1535
TEST(NgHttp2AdapterTest,ClientStartsShutdown)1536 TEST(NgHttp2AdapterTest, ClientStartsShutdown) {
1537 DataSavingVisitor visitor;
1538 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1539
1540 EXPECT_FALSE(adapter->want_write());
1541
1542 // No-op for a client implementation.
1543 adapter->SubmitShutdownNotice();
1544 EXPECT_FALSE(adapter->want_write());
1545
1546 int result = adapter->Send();
1547 EXPECT_EQ(0, result);
1548
1549 EXPECT_EQ(visitor.data(), spdy::kHttp2ConnectionHeaderPrefix);
1550 }
1551
TEST(NgHttp2AdapterTest,ClientReceivesGoAway)1552 TEST(NgHttp2AdapterTest, ClientReceivesGoAway) {
1553 DataSavingVisitor visitor;
1554 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1555
1556 testing::InSequence s;
1557
1558 const std::vector<Header> headers1 =
1559 ToHeaders({{":method", "GET"},
1560 {":scheme", "http"},
1561 {":authority", "example.com"},
1562 {":path", "/this/is/request/one"}});
1563
1564 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
1565 ASSERT_GT(stream_id1, 0);
1566
1567 const std::vector<Header> headers2 =
1568 ToHeaders({{":method", "GET"},
1569 {":scheme", "http"},
1570 {":authority", "example.com"},
1571 {":path", "/this/is/request/two"}});
1572
1573 const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
1574 ASSERT_GT(stream_id2, stream_id1);
1575
1576 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1577 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1578 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id2, _, 0x5));
1579 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id2, _, 0x5, 0));
1580
1581 int result = adapter->Send();
1582 EXPECT_EQ(0, result);
1583 absl::string_view data = visitor.data();
1584 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1585 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1586 EXPECT_THAT(data,
1587 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::HEADERS}));
1588 visitor.Clear();
1589
1590 // Submit a pending WINDOW_UPDATE for a stream that will be closed due to
1591 // GOAWAY. The WINDOW_UPDATE should not be sent.
1592 adapter->SubmitWindowUpdate(3, 42);
1593
1594 const std::string stream_frames =
1595 TestFrameSequence()
1596 .ServerPreface()
1597 .RstStream(1, Http2ErrorCode::ENHANCE_YOUR_CALM)
1598 .GoAway(1, Http2ErrorCode::INTERNAL_ERROR, "indigestion")
1599 .WindowUpdate(0, 42)
1600 .WindowUpdate(1, 42)
1601 .Serialize();
1602
1603 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1604 EXPECT_CALL(visitor, OnSettingsStart());
1605 EXPECT_CALL(visitor, OnSettingsEnd());
1606 EXPECT_CALL(visitor, OnFrameHeader(1, 4, RST_STREAM, 0));
1607 EXPECT_CALL(visitor, OnRstStream(1, Http2ErrorCode::ENHANCE_YOUR_CALM));
1608 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::ENHANCE_YOUR_CALM));
1609 EXPECT_CALL(visitor, OnFrameHeader(0, _, GOAWAY, 0));
1610 EXPECT_CALL(visitor,
1611 OnGoAway(1, Http2ErrorCode::INTERNAL_ERROR, "indigestion"));
1612 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::REFUSED_STREAM));
1613 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
1614 EXPECT_CALL(visitor, OnWindowUpdate(0, 42));
1615 EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
1616
1617 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1618 EXPECT_EQ(stream_frames.size(), stream_result);
1619
1620 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
1621 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
1622
1623 // SETTINGS ack (but only after the enqueue of the seemingly unrelated
1624 // WINDOW_UPDATE). The WINDOW_UPDATE is not written.
1625 EXPECT_TRUE(adapter->want_write());
1626 result = adapter->Send();
1627 EXPECT_EQ(0, result);
1628 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
1629 }
1630
TEST(NgHttp2AdapterTest,ClientReceivesMultipleGoAways)1631 TEST(NgHttp2AdapterTest, ClientReceivesMultipleGoAways) {
1632 DataSavingVisitor visitor;
1633 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1634
1635 testing::InSequence s;
1636
1637 const std::vector<Header> headers1 =
1638 ToHeaders({{":method", "GET"},
1639 {":scheme", "http"},
1640 {":authority", "example.com"},
1641 {":path", "/this/is/request/one"}});
1642
1643 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
1644 ASSERT_GT(stream_id1, 0);
1645
1646 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1647 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1648
1649 int result = adapter->Send();
1650 EXPECT_EQ(0, result);
1651 absl::string_view data = visitor.data();
1652 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1653 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1654 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
1655 visitor.Clear();
1656
1657 const std::string initial_frames =
1658 TestFrameSequence()
1659 .ServerPreface()
1660 .GoAway(kMaxStreamId, Http2ErrorCode::INTERNAL_ERROR, "indigestion")
1661 .Serialize();
1662
1663 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1664 EXPECT_CALL(visitor, OnSettingsStart());
1665 EXPECT_CALL(visitor, OnSettingsEnd());
1666 EXPECT_CALL(visitor, OnFrameHeader(0, _, GOAWAY, 0));
1667 EXPECT_CALL(visitor, OnGoAway(kMaxStreamId, Http2ErrorCode::INTERNAL_ERROR,
1668 "indigestion"));
1669
1670 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
1671 EXPECT_EQ(initial_frames.size(), static_cast<size_t>(initial_result));
1672
1673 // Submit a WINDOW_UPDATE for the open stream. Because the stream is below the
1674 // GOAWAY's last_stream_id, it should be sent.
1675 adapter->SubmitWindowUpdate(1, 42);
1676
1677 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
1678 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
1679 EXPECT_CALL(visitor, OnBeforeFrameSent(WINDOW_UPDATE, 1, 4, 0x0));
1680 EXPECT_CALL(visitor, OnFrameSent(WINDOW_UPDATE, 1, 4, 0x0, 0));
1681
1682 result = adapter->Send();
1683 EXPECT_EQ(0, result);
1684 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
1685 SpdyFrameType::WINDOW_UPDATE}));
1686 visitor.Clear();
1687
1688 const std::string final_frames =
1689 TestFrameSequence()
1690 .GoAway(0, Http2ErrorCode::INTERNAL_ERROR, "indigestion")
1691 .Serialize();
1692
1693 EXPECT_CALL(visitor, OnFrameHeader(0, _, GOAWAY, 0));
1694 EXPECT_CALL(visitor,
1695 OnGoAway(0, Http2ErrorCode::INTERNAL_ERROR, "indigestion"));
1696 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::REFUSED_STREAM));
1697
1698 const int64_t final_result = adapter->ProcessBytes(final_frames);
1699 EXPECT_EQ(final_frames.size(), static_cast<size_t>(final_result));
1700
1701 EXPECT_FALSE(adapter->want_write());
1702 result = adapter->Send();
1703 EXPECT_EQ(0, result);
1704 EXPECT_THAT(visitor.data(), testing::IsEmpty());
1705 }
1706
TEST(NgHttp2AdapterTest,ClientReceivesMultipleGoAwaysWithIncreasingStreamId)1707 TEST(NgHttp2AdapterTest, ClientReceivesMultipleGoAwaysWithIncreasingStreamId) {
1708 DataSavingVisitor visitor;
1709 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1710
1711 testing::InSequence s;
1712
1713 const std::vector<Header> headers1 =
1714 ToHeaders({{":method", "GET"},
1715 {":scheme", "http"},
1716 {":authority", "example.com"},
1717 {":path", "/this/is/request/one"}});
1718
1719 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
1720 ASSERT_GT(stream_id1, 0);
1721
1722 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1723 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1724
1725 int result = adapter->Send();
1726 EXPECT_EQ(0, result);
1727 absl::string_view data = visitor.data();
1728 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1729 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1730 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
1731 visitor.Clear();
1732
1733 auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
1734 {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
1735 adapter->SubmitMetadata(stream_id1, 16384u, std::move(source));
1736
1737 const std::string frames =
1738 TestFrameSequence()
1739 .ServerPreface()
1740 .GoAway(0, Http2ErrorCode::HTTP2_NO_ERROR, "")
1741 .GoAway(0, Http2ErrorCode::ENHANCE_YOUR_CALM, "")
1742 .GoAway(1, Http2ErrorCode::INTERNAL_ERROR, "")
1743 .Serialize();
1744
1745 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1746 EXPECT_CALL(visitor, OnSettingsStart());
1747 EXPECT_CALL(visitor, OnSettingsEnd());
1748 EXPECT_CALL(visitor, OnFrameHeader(0, _, GOAWAY, 0));
1749 EXPECT_CALL(visitor, OnGoAway(0, Http2ErrorCode::HTTP2_NO_ERROR, ""));
1750 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::REFUSED_STREAM));
1751 EXPECT_CALL(visitor, OnFrameHeader(0, _, GOAWAY, 0));
1752 EXPECT_CALL(visitor, OnGoAway(0, Http2ErrorCode::ENHANCE_YOUR_CALM, ""));
1753 EXPECT_CALL(visitor, OnFrameHeader(0, _, GOAWAY, 0));
1754 EXPECT_CALL(
1755 visitor,
1756 OnInvalidFrame(0, Http2VisitorInterface::InvalidFrameError::kProtocol));
1757
1758 const int64_t frames_result = adapter->ProcessBytes(frames);
1759 EXPECT_EQ(frames.size(), static_cast<size_t>(frames_result));
1760
1761 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
1762 EXPECT_CALL(visitor,
1763 OnFrameSent(GOAWAY, 0, _, 0x0,
1764 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
1765
1766 EXPECT_TRUE(adapter->want_write());
1767 result = adapter->Send();
1768 EXPECT_EQ(0, result);
1769 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
1770 }
1771
TEST(NgHttp2AdapterTest,ClientReceivesGoAwayWithPendingStreams)1772 TEST(NgHttp2AdapterTest, ClientReceivesGoAwayWithPendingStreams) {
1773 DataSavingVisitor visitor;
1774 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1775
1776 int result = adapter->Send();
1777 EXPECT_EQ(0, result);
1778 // Client preface does not appear to include the mandatory SETTINGS frame.
1779 EXPECT_THAT(visitor.data(),
1780 testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
1781 visitor.Clear();
1782
1783 testing::InSequence s;
1784
1785 const std::string initial_frames =
1786 TestFrameSequence()
1787 .ServerPreface({{MAX_CONCURRENT_STREAMS, 1}})
1788 .Serialize();
1789
1790 // Server preface (SETTINGS with MAX_CONCURRENT_STREAMS)
1791 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
1792 EXPECT_CALL(visitor, OnSettingsStart());
1793 EXPECT_CALL(visitor, OnSetting);
1794 EXPECT_CALL(visitor, OnSettingsEnd());
1795
1796 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
1797 EXPECT_EQ(initial_frames.size(), initial_result);
1798
1799 const std::vector<Header> headers1 =
1800 ToHeaders({{":method", "GET"},
1801 {":scheme", "http"},
1802 {":authority", "example.com"},
1803 {":path", "/this/is/request/one"}});
1804
1805 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
1806 ASSERT_GT(stream_id1, 0);
1807
1808 const std::vector<Header> headers2 =
1809 ToHeaders({{":method", "GET"},
1810 {":scheme", "http"},
1811 {":authority", "example.com"},
1812 {":path", "/this/is/request/two"}});
1813
1814 const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
1815 ASSERT_GT(stream_id2, stream_id1);
1816
1817 // The second request should be pending because of
1818 // SETTINGS_MAX_CONCURRENT_STREAMS.
1819 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
1820 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
1821 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1822 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1823
1824 result = adapter->Send();
1825 EXPECT_EQ(0, result);
1826 EXPECT_THAT(visitor.data(),
1827 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
1828 visitor.Clear();
1829
1830 // Let the client receive a GOAWAY and raise MAX_CONCURRENT_STREAMS. Even
1831 // though the GOAWAY last_stream_id is higher than the pending request's
1832 // stream ID, pending request should not be sent.
1833 const std::string stream_frames =
1834 TestFrameSequence()
1835 .GoAway(kMaxStreamId, Http2ErrorCode::INTERNAL_ERROR, "indigestion")
1836 .Settings({{MAX_CONCURRENT_STREAMS, 42u}})
1837 .Serialize();
1838
1839 EXPECT_CALL(visitor, OnFrameHeader(0, _, GOAWAY, 0));
1840 EXPECT_CALL(visitor, OnGoAway(kMaxStreamId, Http2ErrorCode::INTERNAL_ERROR,
1841 "indigestion"));
1842 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
1843 EXPECT_CALL(visitor, OnSettingsStart());
1844 EXPECT_CALL(visitor, OnSetting(Http2Setting{MAX_CONCURRENT_STREAMS, 42u}));
1845 EXPECT_CALL(visitor, OnSettingsEnd());
1846
1847 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1848 EXPECT_EQ(stream_frames.size(), stream_result);
1849
1850 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
1851 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
1852
1853 // Nghttp2 closes the pending stream on the next write attempt.
1854 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::REFUSED_STREAM));
1855
1856 EXPECT_TRUE(adapter->want_write());
1857 result = adapter->Send();
1858 EXPECT_EQ(0, result);
1859 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
1860 visitor.Clear();
1861
1862 // Requests submitted after receiving the GOAWAY should not be sent.
1863 const std::vector<Header> headers3 =
1864 ToHeaders({{":method", "GET"},
1865 {":scheme", "http"},
1866 {":authority", "example.com"},
1867 {":path", "/this/is/request/three"}});
1868
1869 const int32_t stream_id3 = adapter->SubmitRequest(headers3, nullptr, nullptr);
1870 ASSERT_GT(stream_id3, stream_id2);
1871
1872 // Nghttp2 closes the pending stream on the next write attempt.
1873 EXPECT_CALL(visitor, OnCloseStream(5, Http2ErrorCode::REFUSED_STREAM));
1874
1875 EXPECT_TRUE(adapter->want_write());
1876 result = adapter->Send();
1877 EXPECT_EQ(0, result);
1878 EXPECT_THAT(visitor.data(), testing::IsEmpty());
1879 EXPECT_FALSE(adapter->want_write());
1880 }
1881
TEST(NgHttp2AdapterTest,ClientFailsOnGoAway)1882 TEST(NgHttp2AdapterTest, ClientFailsOnGoAway) {
1883 DataSavingVisitor visitor;
1884 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1885
1886 testing::InSequence s;
1887
1888 const std::vector<Header> headers1 =
1889 ToHeaders({{":method", "GET"},
1890 {":scheme", "http"},
1891 {":authority", "example.com"},
1892 {":path", "/this/is/request/one"}});
1893
1894 const char* kSentinel1 = "arbitrary pointer 1";
1895 const int32_t stream_id1 =
1896 adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
1897 ASSERT_GT(stream_id1, 0);
1898 QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
1899
1900 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1901 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1902
1903 int result = adapter->Send();
1904 EXPECT_EQ(0, result);
1905 absl::string_view data = visitor.data();
1906 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1907 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1908 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
1909 visitor.Clear();
1910
1911 const std::string stream_frames =
1912 TestFrameSequence()
1913 .ServerPreface()
1914 .Headers(1,
1915 {{":status", "200"},
1916 {"server", "my-fake-server"},
1917 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
1918 /*fin=*/false)
1919 .GoAway(1, Http2ErrorCode::INTERNAL_ERROR, "indigestion")
1920 .Data(1, "This is the response body.")
1921 .Serialize();
1922
1923 // Server preface (empty SETTINGS)
1924 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1925 EXPECT_CALL(visitor, OnSettingsStart());
1926 EXPECT_CALL(visitor, OnSettingsEnd());
1927
1928 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
1929 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
1930 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
1931 EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
1932 EXPECT_CALL(visitor,
1933 OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
1934 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
1935 EXPECT_CALL(visitor, OnFrameHeader(0, _, GOAWAY, 0));
1936 EXPECT_CALL(visitor,
1937 OnGoAway(1, Http2ErrorCode::INTERNAL_ERROR, "indigestion"))
1938 .WillOnce(testing::Return(false));
1939 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
1940
1941 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
1942 EXPECT_EQ(NGHTTP2_ERR_CALLBACK_FAILURE, stream_result);
1943
1944 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
1945 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
1946
1947 EXPECT_TRUE(adapter->want_write());
1948 result = adapter->Send();
1949 EXPECT_EQ(0, result);
1950 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
1951 }
1952
TEST(NgHttp2AdapterTest,ClientRejects101Response)1953 TEST(NgHttp2AdapterTest, ClientRejects101Response) {
1954 DataSavingVisitor visitor;
1955 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
1956
1957 testing::InSequence s;
1958
1959 const std::vector<Header> headers1 =
1960 ToHeaders({{":method", "GET"},
1961 {":scheme", "http"},
1962 {":authority", "example.com"},
1963 {":path", "/this/is/request/one"},
1964 {"upgrade", "new-protocol"}});
1965
1966 const int32_t stream_id1 = adapter->SubmitRequest(headers1, nullptr, nullptr);
1967 ASSERT_GT(stream_id1, 0);
1968
1969 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
1970 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
1971
1972 int result = adapter->Send();
1973 EXPECT_EQ(0, result);
1974 absl::string_view data = visitor.data();
1975 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
1976 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
1977 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
1978 visitor.Clear();
1979
1980 const std::string stream_frames =
1981 TestFrameSequence()
1982 .ServerPreface()
1983 .Headers(1,
1984 {{":status", "101"},
1985 {"server", "my-fake-server"},
1986 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
1987 /*fin=*/false)
1988 .Serialize();
1989
1990 // Server preface (empty SETTINGS)
1991 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1992 EXPECT_CALL(visitor, OnSettingsStart());
1993 EXPECT_CALL(visitor, OnSettingsEnd());
1994
1995 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
1996 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
1997 EXPECT_CALL(
1998 visitor,
1999 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
2000 "stream: 1, name: [:status], value: [101]"));
2001 EXPECT_CALL(
2002 visitor,
2003 OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
2004
2005 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
2006 EXPECT_EQ(static_cast<int64_t>(stream_frames.size()), stream_result);
2007
2008 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
2009 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
2010 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, 4, 0x0));
2011 EXPECT_CALL(
2012 visitor,
2013 OnFrameSent(RST_STREAM, 1, 4, 0x0,
2014 static_cast<uint32_t>(Http2ErrorCode::PROTOCOL_ERROR)));
2015 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
2016
2017 EXPECT_TRUE(adapter->want_write());
2018 result = adapter->Send();
2019 EXPECT_EQ(0, result);
2020 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
2021 SpdyFrameType::RST_STREAM}));
2022 }
2023
TEST(NgHttp2AdapterTest,ClientSubmitRequest)2024 TEST(NgHttp2AdapterTest, ClientSubmitRequest) {
2025 DataSavingVisitor visitor;
2026 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2027 int result = adapter->Send();
2028 EXPECT_EQ(0, result);
2029 // Client preface does not appear to include the mandatory SETTINGS frame.
2030 EXPECT_THAT(visitor.data(),
2031 testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
2032 visitor.Clear();
2033
2034 const std::string initial_frames =
2035 TestFrameSequence().ServerPreface().Serialize();
2036 testing::InSequence s;
2037
2038 // Server preface (empty SETTINGS)
2039 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
2040 EXPECT_CALL(visitor, OnSettingsStart());
2041 EXPECT_CALL(visitor, OnSettingsEnd());
2042
2043 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
2044 EXPECT_EQ(initial_frames.size(), initial_result);
2045
2046 EXPECT_TRUE(adapter->want_write());
2047
2048 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
2049 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
2050
2051 result = adapter->Send();
2052 EXPECT_EQ(0, result);
2053 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
2054 visitor.Clear();
2055
2056 EXPECT_EQ(0, adapter->GetHpackEncoderDynamicTableSize());
2057 EXPECT_FALSE(adapter->want_write());
2058 const char* kSentinel = "";
2059 const absl::string_view kBody = "This is an example request body.";
2060 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
2061 body1->AppendPayload(kBody);
2062 body1->EndData();
2063 int stream_id =
2064 adapter->SubmitRequest(ToHeaders({{":method", "POST"},
2065 {":scheme", "http"},
2066 {":authority", "example.com"},
2067 {":path", "/this/is/request/one"}}),
2068 std::move(body1), const_cast<char*>(kSentinel));
2069 EXPECT_GT(stream_id, 0);
2070 EXPECT_TRUE(adapter->want_write());
2071
2072 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
2073 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
2074 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
2075
2076 result = adapter->Send();
2077 EXPECT_EQ(0, result);
2078
2079 EXPECT_EQ(kInitialFlowControlWindowSize,
2080 adapter->GetStreamReceiveWindowSize(stream_id));
2081 EXPECT_EQ(kInitialFlowControlWindowSize, adapter->GetReceiveWindowSize());
2082 EXPECT_EQ(kInitialFlowControlWindowSize,
2083 adapter->GetStreamReceiveWindowLimit(stream_id));
2084
2085 EXPECT_GT(adapter->GetHpackEncoderDynamicTableSize(), 0);
2086
2087 // Some data was sent, so the remaining send window size should be less than
2088 // the default.
2089 EXPECT_LT(adapter->GetStreamSendWindowSize(stream_id),
2090 kInitialFlowControlWindowSize);
2091 EXPECT_GT(adapter->GetStreamSendWindowSize(stream_id), 0);
2092 // Send window for a nonexistent stream is not available.
2093 EXPECT_EQ(-1, adapter->GetStreamSendWindowSize(stream_id + 2));
2094
2095 EXPECT_THAT(visitor.data(),
2096 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
2097 EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
2098 visitor.Clear();
2099 EXPECT_FALSE(adapter->want_write());
2100
2101 stream_id =
2102 adapter->SubmitRequest(ToHeaders({{":method", "POST"},
2103 {":scheme", "http"},
2104 {":authority", "example.com"},
2105 {":path", "/this/is/request/one"}}),
2106 nullptr, nullptr);
2107 EXPECT_GT(stream_id, 0);
2108 EXPECT_TRUE(adapter->want_write());
2109 const char* kSentinel2 = "arbitrary pointer 2";
2110 EXPECT_EQ(nullptr, adapter->GetStreamUserData(stream_id));
2111 adapter->SetStreamUserData(stream_id, const_cast<char*>(kSentinel2));
2112
2113 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
2114 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
2115
2116 result = adapter->Send();
2117 EXPECT_EQ(0, result);
2118 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
2119
2120 EXPECT_EQ(kSentinel2, adapter->GetStreamUserData(stream_id));
2121
2122 // No data was sent (just HEADERS), so the remaining send window size should
2123 // still be the default.
2124 EXPECT_EQ(adapter->GetStreamSendWindowSize(stream_id),
2125 kInitialFlowControlWindowSize);
2126 }
2127
2128 // This is really a test of the MakeZeroCopyDataFrameSource adapter, but I
2129 // wasn't sure where else to put it.
TEST(NgHttp2AdapterTest,ClientSubmitRequestWithDataProvider)2130 TEST(NgHttp2AdapterTest, ClientSubmitRequestWithDataProvider) {
2131 DataSavingVisitor visitor;
2132 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2133 int result = adapter->Send();
2134 EXPECT_EQ(0, result);
2135 // Client preface does not appear to include the mandatory SETTINGS frame.
2136 EXPECT_THAT(visitor.data(),
2137 testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
2138 visitor.Clear();
2139
2140 const std::string initial_frames =
2141 TestFrameSequence().ServerPreface().Serialize();
2142 testing::InSequence s;
2143
2144 // Server preface (empty SETTINGS)
2145 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
2146 EXPECT_CALL(visitor, OnSettingsStart());
2147 EXPECT_CALL(visitor, OnSettingsEnd());
2148
2149 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
2150 EXPECT_EQ(initial_frames.size(), initial_result);
2151
2152 EXPECT_TRUE(adapter->want_write());
2153
2154 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
2155 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
2156
2157 result = adapter->Send();
2158 EXPECT_EQ(0, result);
2159 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
2160 visitor.Clear();
2161
2162 EXPECT_FALSE(adapter->want_write());
2163 const absl::string_view kBody = "This is an example request body.";
2164 // This test will use TestDataSource as the source of the body payload data.
2165 TestDataSource body1{kBody};
2166 // The TestDataSource is wrapped in the nghttp2_data_provider data type.
2167 nghttp2_data_provider provider = body1.MakeDataProvider();
2168 nghttp2_send_data_callback send_callback = &TestSendCallback;
2169
2170 // This call transforms it back into a DataFrameSource, which is compatible
2171 // with the Http2Adapter API.
2172 std::unique_ptr<DataFrameSource> frame_source =
2173 MakeZeroCopyDataFrameSource(provider, &visitor, std::move(send_callback));
2174 int stream_id =
2175 adapter->SubmitRequest(ToHeaders({{":method", "POST"},
2176 {":scheme", "http"},
2177 {":authority", "example.com"},
2178 {":path", "/this/is/request/one"}}),
2179 std::move(frame_source), nullptr);
2180 EXPECT_GT(stream_id, 0);
2181 EXPECT_TRUE(adapter->want_write());
2182
2183 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
2184 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
2185 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
2186
2187 result = adapter->Send();
2188 EXPECT_EQ(0, result);
2189 EXPECT_THAT(visitor.data(),
2190 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
2191 EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
2192 EXPECT_FALSE(adapter->want_write());
2193 }
2194
2195 // This test verifies how nghttp2 behaves when a data source becomes
2196 // read-blocked.
TEST(NgHttp2AdapterTest,ClientSubmitRequestWithDataProviderAndReadBlock)2197 TEST(NgHttp2AdapterTest, ClientSubmitRequestWithDataProviderAndReadBlock) {
2198 DataSavingVisitor visitor;
2199 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2200
2201 const absl::string_view kBody = "This is an example request body.";
2202 // This test will use TestDataSource as the source of the body payload data.
2203 TestDataSource body1{kBody};
2204 body1.set_is_data_available(false);
2205 // The TestDataSource is wrapped in the nghttp2_data_provider data type.
2206 nghttp2_data_provider provider = body1.MakeDataProvider();
2207 nghttp2_send_data_callback send_callback = &TestSendCallback;
2208
2209 // This call transforms it back into a DataFrameSource, which is compatible
2210 // with the Http2Adapter API.
2211 std::unique_ptr<DataFrameSource> frame_source =
2212 MakeZeroCopyDataFrameSource(provider, &visitor, std::move(send_callback));
2213 int stream_id =
2214 adapter->SubmitRequest(ToHeaders({{":method", "POST"},
2215 {":scheme", "http"},
2216 {":authority", "example.com"},
2217 {":path", "/this/is/request/one"}}),
2218 std::move(frame_source), nullptr);
2219 EXPECT_GT(stream_id, 0);
2220 EXPECT_TRUE(adapter->want_write());
2221
2222 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
2223 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
2224
2225 int result = adapter->Send();
2226 EXPECT_EQ(0, result);
2227 // Client preface does not appear to include the mandatory SETTINGS frame.
2228 absl::string_view serialized = visitor.data();
2229 EXPECT_THAT(serialized,
2230 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
2231 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
2232 EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::HEADERS}));
2233 visitor.Clear();
2234 EXPECT_FALSE(adapter->want_write());
2235
2236 // Resume the deferred stream.
2237 body1.set_is_data_available(true);
2238 EXPECT_TRUE(adapter->ResumeStream(stream_id));
2239 EXPECT_TRUE(adapter->want_write());
2240
2241 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
2242
2243 result = adapter->Send();
2244 EXPECT_EQ(0, result);
2245 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::DATA}));
2246 EXPECT_FALSE(adapter->want_write());
2247
2248 // Stream data is done, so this stream cannot be resumed.
2249 EXPECT_FALSE(adapter->ResumeStream(stream_id));
2250 EXPECT_FALSE(adapter->want_write());
2251 }
2252
2253 // This test verifies how nghttp2 behaves when a data source is read block, then
2254 // ends with an empty DATA frame.
TEST(NgHttp2AdapterTest,ClientSubmitRequestEmptyDataWithFin)2255 TEST(NgHttp2AdapterTest, ClientSubmitRequestEmptyDataWithFin) {
2256 DataSavingVisitor visitor;
2257 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2258
2259 const absl::string_view kEmptyBody = "";
2260 // This test will use TestDataSource as the source of the body payload data.
2261 TestDataSource body1{kEmptyBody};
2262 body1.set_is_data_available(false);
2263 // The TestDataSource is wrapped in the nghttp2_data_provider data type.
2264 nghttp2_data_provider provider = body1.MakeDataProvider();
2265 nghttp2_send_data_callback send_callback = &TestSendCallback;
2266
2267 // This call transforms it back into a DataFrameSource, which is compatible
2268 // with the Http2Adapter API.
2269 std::unique_ptr<DataFrameSource> frame_source =
2270 MakeZeroCopyDataFrameSource(provider, &visitor, std::move(send_callback));
2271 int stream_id =
2272 adapter->SubmitRequest(ToHeaders({{":method", "POST"},
2273 {":scheme", "http"},
2274 {":authority", "example.com"},
2275 {":path", "/this/is/request/one"}}),
2276 std::move(frame_source), nullptr);
2277 EXPECT_GT(stream_id, 0);
2278 EXPECT_TRUE(adapter->want_write());
2279
2280 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
2281 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
2282
2283 int result = adapter->Send();
2284 EXPECT_EQ(0, result);
2285 // Client preface does not appear to include the mandatory SETTINGS frame.
2286 absl::string_view serialized = visitor.data();
2287 EXPECT_THAT(serialized,
2288 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
2289 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
2290 EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::HEADERS}));
2291 visitor.Clear();
2292 EXPECT_FALSE(adapter->want_write());
2293
2294 // Resume the deferred stream.
2295 body1.set_is_data_available(true);
2296 EXPECT_TRUE(adapter->ResumeStream(stream_id));
2297 EXPECT_TRUE(adapter->want_write());
2298
2299 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, 0, 0x1, 0));
2300
2301 result = adapter->Send();
2302 EXPECT_EQ(0, result);
2303 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::DATA}));
2304 EXPECT_FALSE(adapter->want_write());
2305
2306 // Stream data is done, so this stream cannot be resumed.
2307 EXPECT_FALSE(adapter->ResumeStream(stream_id));
2308 EXPECT_FALSE(adapter->want_write());
2309 }
2310
2311 // This test verifies how nghttp2 behaves when a connection becomes
2312 // write-blocked.
TEST(NgHttp2AdapterTest,ClientSubmitRequestWithDataProviderAndWriteBlock)2313 TEST(NgHttp2AdapterTest, ClientSubmitRequestWithDataProviderAndWriteBlock) {
2314 DataSavingVisitor visitor;
2315 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2316
2317 const absl::string_view kBody = "This is an example request body.";
2318 // This test will use TestDataSource as the source of the body payload data.
2319 TestDataSource body1{kBody};
2320 // The TestDataSource is wrapped in the nghttp2_data_provider data type.
2321 nghttp2_data_provider provider = body1.MakeDataProvider();
2322 nghttp2_send_data_callback send_callback = &TestSendCallback;
2323
2324 // This call transforms it back into a DataFrameSource, which is compatible
2325 // with the Http2Adapter API.
2326 std::unique_ptr<DataFrameSource> frame_source =
2327 MakeZeroCopyDataFrameSource(provider, &visitor, std::move(send_callback));
2328 int stream_id =
2329 adapter->SubmitRequest(ToHeaders({{":method", "POST"},
2330 {":scheme", "http"},
2331 {":authority", "example.com"},
2332 {":path", "/this/is/request/one"}}),
2333 std::move(frame_source), nullptr);
2334 EXPECT_GT(stream_id, 0);
2335 EXPECT_TRUE(adapter->want_write());
2336
2337 visitor.set_is_write_blocked(true);
2338 int result = adapter->Send();
2339 EXPECT_EQ(0, result);
2340 EXPECT_THAT(visitor.data(), testing::IsEmpty());
2341 EXPECT_TRUE(adapter->want_write());
2342
2343 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
2344 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
2345 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
2346
2347 visitor.set_is_write_blocked(false);
2348 result = adapter->Send();
2349 EXPECT_EQ(0, result);
2350
2351 // Client preface does not appear to include the mandatory SETTINGS frame.
2352 absl::string_view serialized = visitor.data();
2353 EXPECT_THAT(serialized,
2354 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
2355 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
2356 EXPECT_THAT(serialized,
2357 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
2358 EXPECT_FALSE(adapter->want_write());
2359 }
2360
TEST(NgHttp2AdapterTest,ClientReceivesDataOnClosedStream)2361 TEST(NgHttp2AdapterTest, ClientReceivesDataOnClosedStream) {
2362 DataSavingVisitor visitor;
2363 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2364 int result = adapter->Send();
2365 EXPECT_EQ(0, result);
2366 // Client preface does not appear to include the mandatory SETTINGS frame.
2367 EXPECT_THAT(visitor.data(),
2368 testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
2369 visitor.Clear();
2370
2371 const std::string initial_frames =
2372 TestFrameSequence().ServerPreface().Serialize();
2373 testing::InSequence s;
2374
2375 // Server preface (empty SETTINGS)
2376 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
2377 EXPECT_CALL(visitor, OnSettingsStart());
2378 EXPECT_CALL(visitor, OnSettingsEnd());
2379
2380 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
2381 EXPECT_EQ(initial_frames.size(), initial_result);
2382
2383 // Client SETTINGS ack
2384 EXPECT_TRUE(adapter->want_write());
2385 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
2386 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
2387
2388 result = adapter->Send();
2389 EXPECT_EQ(0, result);
2390 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
2391 visitor.Clear();
2392
2393 // Let the client open a stream with a request.
2394 int stream_id =
2395 adapter->SubmitRequest(ToHeaders({{":method", "GET"},
2396 {":scheme", "http"},
2397 {":authority", "example.com"},
2398 {":path", "/this/is/request/one"}}),
2399 nullptr, nullptr);
2400 EXPECT_GT(stream_id, 0);
2401
2402 EXPECT_TRUE(adapter->want_write());
2403 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
2404 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
2405
2406 result = adapter->Send();
2407 EXPECT_EQ(0, result);
2408 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
2409 visitor.Clear();
2410
2411 // Let the client RST_STREAM the stream it opened.
2412 adapter->SubmitRst(stream_id, Http2ErrorCode::CANCEL);
2413 EXPECT_TRUE(adapter->want_write());
2414 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, stream_id, _, 0x0));
2415 EXPECT_CALL(visitor, OnFrameSent(RST_STREAM, stream_id, _, 0x0,
2416 static_cast<int>(Http2ErrorCode::CANCEL)));
2417 EXPECT_CALL(visitor, OnCloseStream(stream_id, Http2ErrorCode::CANCEL));
2418
2419 result = adapter->Send();
2420 EXPECT_EQ(0, result);
2421 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::RST_STREAM}));
2422 visitor.Clear();
2423
2424 // Let the server send a response on the stream. (It might not have received
2425 // the RST_STREAM yet.)
2426 const std::string response_frames =
2427 TestFrameSequence()
2428 .Headers(stream_id,
2429 {{":status", "200"},
2430 {"server", "my-fake-server"},
2431 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
2432 /*fin=*/false)
2433 .Data(stream_id, "This is the response body.", /*fin=*/true)
2434 .Serialize();
2435
2436 // The visitor gets notified about the HEADERS frame but not the DATA frame on
2437 // the closed stream. No further processing for either frame occurs.
2438 EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 0x4));
2439 EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, DATA, _)).Times(0);
2440
2441 const int64_t response_result = adapter->ProcessBytes(response_frames);
2442 EXPECT_EQ(response_frames.size(), response_result);
2443
2444 EXPECT_FALSE(adapter->want_write());
2445 }
2446
TEST(NgHttp2AdapterTest,ClientQueuesRequests)2447 TEST(NgHttp2AdapterTest, ClientQueuesRequests) {
2448 DataSavingVisitor visitor;
2449 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2450
2451 testing::InSequence s;
2452
2453 adapter->SubmitSettings({});
2454
2455 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
2456 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
2457 adapter->Send();
2458
2459 const std::string initial_frames =
2460 TestFrameSequence()
2461 .ServerPreface({{MAX_CONCURRENT_STREAMS, 2}})
2462 .SettingsAck()
2463 .Serialize();
2464
2465 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0x0));
2466 EXPECT_CALL(visitor, OnSettingsStart());
2467 EXPECT_CALL(visitor, OnSetting(Http2Setting{
2468 Http2KnownSettingsId::MAX_CONCURRENT_STREAMS, 2u}));
2469 EXPECT_CALL(visitor, OnSettingsEnd());
2470 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0x1));
2471 EXPECT_CALL(visitor, OnSettingsAck());
2472
2473 adapter->ProcessBytes(initial_frames);
2474
2475 const std::vector<Header> headers =
2476 ToHeaders({{":method", "GET"},
2477 {":scheme", "http"},
2478 {":authority", "example.com"},
2479 {":path", "/example/request"}});
2480 std::vector<int32_t> stream_ids;
2481 // Start two, which hits the limit.
2482 int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
2483 stream_ids.push_back(stream_id);
2484 stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
2485 stream_ids.push_back(stream_id);
2486 // Start two more, which must be queued.
2487 stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
2488 stream_ids.push_back(stream_id);
2489 stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
2490 stream_ids.push_back(stream_id);
2491
2492 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
2493 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
2494 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_ids[0], _, 0x5));
2495 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_ids[0], _, 0x5, 0));
2496 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_ids[1], _, 0x5));
2497 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_ids[1], _, 0x5, 0));
2498
2499 adapter->Send();
2500
2501 const std::string update_streams =
2502 TestFrameSequence().Settings({{MAX_CONCURRENT_STREAMS, 5}}).Serialize();
2503
2504 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0x0));
2505 EXPECT_CALL(visitor, OnSettingsStart());
2506 EXPECT_CALL(visitor, OnSetting(Http2Setting{
2507 Http2KnownSettingsId::MAX_CONCURRENT_STREAMS, 5u}));
2508 EXPECT_CALL(visitor, OnSettingsEnd());
2509
2510 adapter->ProcessBytes(update_streams);
2511
2512 stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
2513 stream_ids.push_back(stream_id);
2514
2515 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
2516 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
2517 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_ids[2], _, 0x5));
2518 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_ids[2], _, 0x5, 0));
2519 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_ids[3], _, 0x5));
2520 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_ids[3], _, 0x5, 0));
2521 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_ids[4], _, 0x5));
2522 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_ids[4], _, 0x5, 0));
2523 // Header frames should all have been sent in order, regardless of any
2524 // queuing.
2525
2526 adapter->Send();
2527 }
2528
TEST(NgHttp2AdapterTest,ClientAcceptsHeadResponseWithContentLength)2529 TEST(NgHttp2AdapterTest, ClientAcceptsHeadResponseWithContentLength) {
2530 DataSavingVisitor visitor;
2531 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2532
2533 const std::vector<Header> headers = ToHeaders({{":method", "HEAD"},
2534 {":scheme", "http"},
2535 {":authority", "example.com"},
2536 {":path", "/"}});
2537 const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
2538
2539 testing::InSequence s;
2540
2541 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
2542 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
2543
2544 adapter->Send();
2545
2546 const std::string initial_frames =
2547 TestFrameSequence()
2548 .ServerPreface()
2549 .Headers(stream_id, {{":status", "200"}, {"content-length", "101"}},
2550 /*fin=*/true)
2551 .Serialize();
2552
2553 EXPECT_CALL(visitor, OnFrameHeader(0, _, SETTINGS, 0x0));
2554 EXPECT_CALL(visitor, OnSettingsStart());
2555 EXPECT_CALL(visitor, OnSettingsEnd());
2556 EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 5));
2557 EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
2558 EXPECT_CALL(visitor, OnHeaderForStream).Times(2);
2559 EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
2560 EXPECT_CALL(visitor, OnEndStream(stream_id));
2561 EXPECT_CALL(visitor,
2562 OnCloseStream(stream_id, Http2ErrorCode::HTTP2_NO_ERROR));
2563
2564 adapter->ProcessBytes(initial_frames);
2565
2566 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
2567 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
2568
2569 adapter->Send();
2570 }
2571
TEST(NgHttp2AdapterTest,SubmitMetadata)2572 TEST(NgHttp2AdapterTest, SubmitMetadata) {
2573 DataSavingVisitor visitor;
2574 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2575
2576 auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
2577 {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
2578 adapter->SubmitMetadata(1, 16384u, std::move(source));
2579 EXPECT_TRUE(adapter->want_write());
2580
2581 EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
2582 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
2583
2584 int result = adapter->Send();
2585 EXPECT_EQ(0, result);
2586 absl::string_view serialized = visitor.data();
2587 EXPECT_THAT(serialized,
2588 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
2589 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
2590 EXPECT_THAT(serialized,
2591 EqualsFrames({static_cast<SpdyFrameType>(kMetadataFrameType)}));
2592 EXPECT_FALSE(adapter->want_write());
2593 }
2594
TEST(NgHttp2AdapterTest,SubmitMetadataMultipleFrames)2595 TEST(NgHttp2AdapterTest, SubmitMetadataMultipleFrames) {
2596 DataSavingVisitor visitor;
2597 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2598
2599 const auto kLargeValue = std::string(63 * 1024, 'a');
2600 auto source = std::make_unique<TestMetadataSource>(
2601 ToHeaderBlock(ToHeaders({{"large-value", kLargeValue}})));
2602 adapter->SubmitMetadata(1, 16384u, std::move(source));
2603 EXPECT_TRUE(adapter->want_write());
2604
2605 testing::InSequence seq;
2606 EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
2607 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
2608 EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
2609 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
2610 EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
2611 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
2612 EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
2613 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
2614
2615 int result = adapter->Send();
2616 EXPECT_EQ(0, result);
2617 absl::string_view serialized = visitor.data();
2618 EXPECT_THAT(serialized,
2619 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
2620 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
2621 EXPECT_THAT(serialized,
2622 EqualsFrames({static_cast<SpdyFrameType>(kMetadataFrameType),
2623 static_cast<SpdyFrameType>(kMetadataFrameType),
2624 static_cast<SpdyFrameType>(kMetadataFrameType),
2625 static_cast<SpdyFrameType>(kMetadataFrameType)}));
2626 EXPECT_FALSE(adapter->want_write());
2627 }
2628
TEST(NgHttp2AdapterTest,SubmitConnectionMetadata)2629 TEST(NgHttp2AdapterTest, SubmitConnectionMetadata) {
2630 DataSavingVisitor visitor;
2631 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2632
2633 auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
2634 {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
2635 adapter->SubmitMetadata(0, 16384u, std::move(source));
2636 EXPECT_TRUE(adapter->want_write());
2637
2638 EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 0, _, 0x4));
2639 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 0, _, 0x4, 0));
2640
2641 int result = adapter->Send();
2642 EXPECT_EQ(0, result);
2643 absl::string_view serialized = visitor.data();
2644 EXPECT_THAT(serialized,
2645 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
2646 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
2647 EXPECT_THAT(serialized,
2648 EqualsFrames({static_cast<SpdyFrameType>(kMetadataFrameType)}));
2649 EXPECT_FALSE(adapter->want_write());
2650 }
2651
TEST(NgHttp2AdapterTest,ClientSubmitMetadataWithGoaway)2652 TEST(NgHttp2AdapterTest, ClientSubmitMetadataWithGoaway) {
2653 DataSavingVisitor visitor;
2654 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2655
2656 adapter->SubmitSettings({});
2657
2658 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, _, _, 0x0));
2659 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, _, _, 0x0, 0));
2660 adapter->Send();
2661
2662 const std::vector<Header> headers =
2663 ToHeaders({{":method", "GET"},
2664 {":scheme", "http"},
2665 {":authority", "example.com"},
2666 {":path", "/this/is/request/one"}});
2667 const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
2668
2669 auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
2670 {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
2671 adapter->SubmitMetadata(stream_id, 16384u, std::move(source));
2672 EXPECT_TRUE(adapter->want_write());
2673
2674 const std::string initial_frames =
2675 TestFrameSequence()
2676 .ServerPreface()
2677 .GoAway(3, Http2ErrorCode::HTTP2_NO_ERROR, "server shutting down")
2678 .Serialize();
2679 testing::InSequence s;
2680
2681 // Server preface
2682 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
2683 EXPECT_CALL(visitor, OnSettingsStart());
2684 EXPECT_CALL(visitor, OnSettingsEnd());
2685 EXPECT_CALL(visitor, OnFrameHeader(0, _, GOAWAY, 0));
2686 EXPECT_CALL(visitor, OnGoAway(3, Http2ErrorCode::HTTP2_NO_ERROR, _));
2687
2688 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
2689 EXPECT_EQ(initial_frames.size(), initial_result);
2690
2691 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
2692 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
2693 // HEADERS frame is not sent.
2694 EXPECT_CALL(visitor,
2695 OnBeforeFrameSent(kMetadataFrameType, stream_id, _, 0x4));
2696 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, stream_id, _, 0x4, 0));
2697 EXPECT_CALL(visitor,
2698 OnCloseStream(stream_id, Http2ErrorCode::REFUSED_STREAM));
2699
2700 int result = adapter->Send();
2701 EXPECT_EQ(0, result);
2702 absl::string_view serialized = visitor.data();
2703 EXPECT_THAT(serialized,
2704 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
2705 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
2706 EXPECT_THAT(serialized,
2707 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS,
2708 static_cast<SpdyFrameType>(kMetadataFrameType)}));
2709 EXPECT_FALSE(adapter->want_write());
2710 }
2711
TEST(NgHttp2AdapterTest,ClientSubmitMetadataWithFailureBefore)2712 TEST(NgHttp2AdapterTest, ClientSubmitMetadataWithFailureBefore) {
2713 DataSavingVisitor visitor;
2714 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2715
2716 adapter->SubmitSettings({});
2717
2718 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, _, _, 0x0));
2719 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, _, _, 0x0, 0));
2720 adapter->Send();
2721
2722 const std::vector<Header> headers =
2723 ToHeaders({{":method", "GET"},
2724 {":scheme", "http"},
2725 {":authority", "example.com"},
2726 {":path", "/this/is/request/one"}});
2727 const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
2728
2729 auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
2730 {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
2731 adapter->SubmitMetadata(stream_id, 16384u, std::move(source));
2732 EXPECT_TRUE(adapter->want_write());
2733
2734 const std::string initial_frames =
2735 TestFrameSequence().ServerPreface().Serialize();
2736 testing::InSequence s;
2737
2738 // Server preface
2739 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
2740 EXPECT_CALL(visitor, OnSettingsStart());
2741 EXPECT_CALL(visitor, OnSettingsEnd());
2742
2743 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
2744 EXPECT_EQ(initial_frames.size(), initial_result);
2745
2746 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
2747 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
2748 EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, stream_id, _, 0x4))
2749 .WillOnce(testing::Return(NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE));
2750 EXPECT_CALL(visitor, OnConnectionError(
2751 Http2VisitorInterface::ConnectionError::kSendError));
2752
2753 int result = adapter->Send();
2754 EXPECT_EQ(NGHTTP2_ERR_CALLBACK_FAILURE, result);
2755 absl::string_view serialized = visitor.data();
2756 EXPECT_THAT(serialized,
2757 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
2758 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
2759 EXPECT_THAT(serialized,
2760 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
2761 }
2762
TEST(NgHttp2AdapterTest,ClientSubmitMetadataWithFailureDuring)2763 TEST(NgHttp2AdapterTest, ClientSubmitMetadataWithFailureDuring) {
2764 DataSavingVisitor visitor;
2765 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2766
2767 adapter->SubmitSettings({});
2768
2769 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, _, _, 0x0));
2770 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, _, _, 0x0, 0));
2771 adapter->Send();
2772
2773 const std::vector<Header> headers =
2774 ToHeaders({{":method", "GET"},
2775 {":scheme", "http"},
2776 {":authority", "example.com"},
2777 {":path", "/this/is/request/one"}});
2778 const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
2779
2780 auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(
2781 ToHeaders({{"more-than-one-frame", std::string(20000, 'a')}})));
2782 adapter->SubmitMetadata(stream_id, 16384u, std::move(source));
2783 EXPECT_TRUE(adapter->want_write());
2784
2785 const std::string initial_frames =
2786 TestFrameSequence().ServerPreface().Serialize();
2787 testing::InSequence s;
2788
2789 // Server preface
2790 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
2791 EXPECT_CALL(visitor, OnSettingsStart());
2792 EXPECT_CALL(visitor, OnSettingsEnd());
2793
2794 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
2795 EXPECT_EQ(initial_frames.size(), initial_result);
2796
2797 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
2798 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
2799 EXPECT_CALL(visitor,
2800 OnBeforeFrameSent(kMetadataFrameType, stream_id, _, 0x0));
2801 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, stream_id, _, 0x0, 0))
2802 .WillOnce(testing::Return(NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE));
2803 EXPECT_CALL(visitor, OnConnectionError(
2804 Http2VisitorInterface::ConnectionError::kSendError));
2805
2806 int result = adapter->Send();
2807 EXPECT_EQ(NGHTTP2_ERR_CALLBACK_FAILURE, result);
2808 absl::string_view serialized = visitor.data();
2809 EXPECT_THAT(serialized,
2810 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
2811 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
2812 EXPECT_THAT(serialized,
2813 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS,
2814 static_cast<SpdyFrameType>(kMetadataFrameType)}));
2815 }
2816
TEST(NgHttp2AdapterTest,ClientSubmitMetadataWithFailureSending)2817 TEST(NgHttp2AdapterTest, ClientSubmitMetadataWithFailureSending) {
2818 DataSavingVisitor visitor;
2819 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2820
2821 adapter->SubmitSettings({});
2822
2823 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, _, _, 0x0));
2824 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, _, _, 0x0, 0));
2825 adapter->Send();
2826
2827 const std::vector<Header> headers =
2828 ToHeaders({{":method", "GET"},
2829 {":scheme", "http"},
2830 {":authority", "example.com"},
2831 {":path", "/this/is/request/one"}});
2832 const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
2833
2834 auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(
2835 ToHeaders({{"more-than-one-frame", std::string(20000, 'a')}})));
2836 source->InjectFailure();
2837 adapter->SubmitMetadata(stream_id, 16384u, std::move(source));
2838 EXPECT_TRUE(adapter->want_write());
2839
2840 const std::string initial_frames =
2841 TestFrameSequence().ServerPreface().Serialize();
2842 testing::InSequence s;
2843
2844 // Server preface
2845 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
2846 EXPECT_CALL(visitor, OnSettingsStart());
2847 EXPECT_CALL(visitor, OnSettingsEnd());
2848
2849 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
2850 EXPECT_EQ(initial_frames.size(), initial_result);
2851
2852 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
2853 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
2854 EXPECT_CALL(visitor, OnConnectionError(
2855 Http2VisitorInterface::ConnectionError::kSendError));
2856
2857 int result = adapter->Send();
2858 EXPECT_EQ(NGHTTP2_ERR_CALLBACK_FAILURE, result);
2859 absl::string_view serialized = visitor.data();
2860 EXPECT_THAT(serialized,
2861 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
2862 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
2863 EXPECT_THAT(serialized, EqualsFrames({
2864 SpdyFrameType::SETTINGS,
2865 SpdyFrameType::SETTINGS,
2866 }));
2867 }
2868
TEST(NgHttp2AdapterTest,ClientObeysMaxConcurrentStreams)2869 TEST(NgHttp2AdapterTest, ClientObeysMaxConcurrentStreams) {
2870 DataSavingVisitor visitor;
2871 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2872 int result = adapter->Send();
2873 EXPECT_EQ(0, result);
2874 // Client preface does not appear to include the mandatory SETTINGS frame.
2875 EXPECT_THAT(visitor.data(),
2876 testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
2877 visitor.Clear();
2878
2879 const std::string initial_frames =
2880 TestFrameSequence()
2881 .ServerPreface({{MAX_CONCURRENT_STREAMS, 1}})
2882 .Serialize();
2883 testing::InSequence s;
2884
2885 // Server preface (SETTINGS with MAX_CONCURRENT_STREAMS)
2886 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
2887 EXPECT_CALL(visitor, OnSettingsStart());
2888 EXPECT_CALL(visitor, OnSetting);
2889 EXPECT_CALL(visitor, OnSettingsEnd());
2890
2891 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
2892 EXPECT_EQ(initial_frames.size(), initial_result);
2893
2894 EXPECT_TRUE(adapter->want_write());
2895
2896 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
2897 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
2898
2899 result = adapter->Send();
2900 EXPECT_EQ(0, result);
2901 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
2902 visitor.Clear();
2903
2904 EXPECT_FALSE(adapter->want_write());
2905 const absl::string_view kBody = "This is an example request body.";
2906 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
2907 body1->AppendPayload(kBody);
2908 body1->EndData();
2909 const int stream_id =
2910 adapter->SubmitRequest(ToHeaders({{":method", "POST"},
2911 {":scheme", "http"},
2912 {":authority", "example.com"},
2913 {":path", "/this/is/request/one"}}),
2914 std::move(body1), nullptr);
2915 EXPECT_GT(stream_id, 0);
2916 EXPECT_TRUE(adapter->want_write());
2917
2918 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
2919 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
2920 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
2921
2922 result = adapter->Send();
2923 EXPECT_EQ(0, result);
2924
2925 EXPECT_THAT(visitor.data(),
2926 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
2927 EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
2928 visitor.Clear();
2929 EXPECT_FALSE(adapter->want_write());
2930
2931 const int next_stream_id =
2932 adapter->SubmitRequest(ToHeaders({{":method", "POST"},
2933 {":scheme", "http"},
2934 {":authority", "example.com"},
2935 {":path", "/this/is/request/two"}}),
2936 nullptr, nullptr);
2937
2938 // A new pending stream is created, but because of MAX_CONCURRENT_STREAMS, the
2939 // session should not want to write it at the moment.
2940 EXPECT_GT(next_stream_id, stream_id);
2941 EXPECT_FALSE(adapter->want_write());
2942
2943 const std::string stream_frames =
2944 TestFrameSequence()
2945 .Headers(stream_id,
2946 {{":status", "200"},
2947 {"server", "my-fake-server"},
2948 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
2949 /*fin=*/false)
2950 .Data(stream_id, "This is the response body.", /*fin=*/true)
2951 .Serialize();
2952
2953 EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 4));
2954 EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
2955 EXPECT_CALL(visitor, OnHeaderForStream(stream_id, ":status", "200"));
2956 EXPECT_CALL(visitor,
2957 OnHeaderForStream(stream_id, "server", "my-fake-server"));
2958 EXPECT_CALL(visitor, OnHeaderForStream(stream_id, "date",
2959 "Tue, 6 Apr 2021 12:54:01 GMT"));
2960 EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
2961 EXPECT_CALL(visitor, OnFrameHeader(stream_id, 26, DATA, 0x1));
2962 EXPECT_CALL(visitor, OnBeginDataForStream(stream_id, 26));
2963 EXPECT_CALL(visitor,
2964 OnDataForStream(stream_id, "This is the response body."));
2965 EXPECT_CALL(visitor, OnEndStream(stream_id));
2966 EXPECT_CALL(visitor,
2967 OnCloseStream(stream_id, Http2ErrorCode::HTTP2_NO_ERROR));
2968
2969 // The first stream should close, which should make the session want to write
2970 // the next stream.
2971 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
2972 EXPECT_EQ(stream_frames.size(), stream_result);
2973 EXPECT_TRUE(adapter->want_write());
2974
2975 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, next_stream_id, _, 0x5));
2976 EXPECT_CALL(visitor, OnFrameSent(HEADERS, next_stream_id, _, 0x5, 0));
2977
2978 result = adapter->Send();
2979 EXPECT_EQ(0, result);
2980
2981 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
2982 visitor.Clear();
2983 EXPECT_FALSE(adapter->want_write());
2984 }
2985
TEST(NgHttp2AdapterTest,ClientReceivesInitialWindowSetting)2986 TEST(NgHttp2AdapterTest, ClientReceivesInitialWindowSetting) {
2987 DataSavingVisitor visitor;
2988 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
2989
2990 const std::string initial_frames =
2991 TestFrameSequence()
2992 .Settings({{INITIAL_WINDOW_SIZE, 80000u}})
2993 .WindowUpdate(0, 65536)
2994 .Serialize();
2995 // Server preface (SETTINGS with INITIAL_STREAM_WINDOW)
2996 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
2997 EXPECT_CALL(visitor, OnSettingsStart());
2998 EXPECT_CALL(visitor, OnSetting(Http2Setting{INITIAL_WINDOW_SIZE, 80000u}));
2999 EXPECT_CALL(visitor, OnSettingsEnd());
3000 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
3001 EXPECT_CALL(visitor, OnWindowUpdate(0, 65536));
3002
3003 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
3004 EXPECT_EQ(initial_frames.size(), static_cast<size_t>(initial_result));
3005
3006 // Session will want to write a SETTINGS ack.
3007 EXPECT_TRUE(adapter->want_write());
3008
3009 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
3010 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
3011
3012 int64_t result = adapter->Send();
3013 EXPECT_EQ(0, result);
3014 absl::string_view serialized = visitor.data();
3015 EXPECT_THAT(serialized,
3016 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
3017 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
3018 EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::SETTINGS}));
3019 visitor.Clear();
3020
3021 const std::string kLongBody = std::string(81000, 'c');
3022 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
3023 body1->AppendPayload(kLongBody);
3024 body1->EndData();
3025 const int stream_id =
3026 adapter->SubmitRequest(ToHeaders({{":method", "POST"},
3027 {":scheme", "http"},
3028 {":authority", "example.com"},
3029 {":path", "/this/is/request/one"}}),
3030 std::move(body1), nullptr);
3031 EXPECT_GT(stream_id, 0);
3032 EXPECT_TRUE(adapter->want_write());
3033
3034 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
3035 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
3036 // The client can send more than 4 frames (65536 bytes) of data.
3037 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, 16384, 0x0, 0)).Times(4);
3038 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, 14464, 0x0, 0));
3039
3040 result = adapter->Send();
3041 EXPECT_EQ(0, result);
3042 EXPECT_THAT(visitor.data(),
3043 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA,
3044 SpdyFrameType::DATA, SpdyFrameType::DATA,
3045 SpdyFrameType::DATA, SpdyFrameType::DATA}));
3046 }
3047
TEST(NgHttp2AdapterTest,ClientReceivesInitialWindowSettingAfterStreamStart)3048 TEST(NgHttp2AdapterTest, ClientReceivesInitialWindowSettingAfterStreamStart) {
3049 DataSavingVisitor visitor;
3050 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
3051
3052 const std::string initial_frames =
3053 TestFrameSequence().ServerPreface().WindowUpdate(0, 65536).Serialize();
3054 // Server preface (empty SETTINGS)
3055 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3056 EXPECT_CALL(visitor, OnSettingsStart());
3057 EXPECT_CALL(visitor, OnSettingsEnd());
3058 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
3059 EXPECT_CALL(visitor, OnWindowUpdate(0, 65536));
3060
3061 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
3062 EXPECT_EQ(initial_frames.size(), static_cast<size_t>(initial_result));
3063
3064 // Session will want to write a SETTINGS ack.
3065 EXPECT_TRUE(adapter->want_write());
3066
3067 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
3068 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
3069
3070 int64_t result = adapter->Send();
3071 EXPECT_EQ(0, result);
3072 visitor.Clear();
3073
3074 const std::string kLongBody = std::string(81000, 'c');
3075 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
3076 body1->AppendPayload(kLongBody);
3077 body1->EndData();
3078 const int stream_id =
3079 adapter->SubmitRequest(ToHeaders({{":method", "POST"},
3080 {":scheme", "http"},
3081 {":authority", "example.com"},
3082 {":path", "/this/is/request/one"}}),
3083 std::move(body1), nullptr);
3084 EXPECT_GT(stream_id, 0);
3085 EXPECT_TRUE(adapter->want_write());
3086
3087 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
3088 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
3089 // The client can only send 65535 bytes of data, as the stream window has not
3090 // yet been increased.
3091 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, 16384, 0x0, 0)).Times(3);
3092 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, 16383, 0x0, 0));
3093
3094 result = adapter->Send();
3095 EXPECT_EQ(0, result);
3096 EXPECT_THAT(visitor.data(),
3097 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA,
3098 SpdyFrameType::DATA, SpdyFrameType::DATA,
3099 SpdyFrameType::DATA}));
3100 visitor.Clear();
3101
3102 // Can't write any more due to flow control.
3103 EXPECT_FALSE(adapter->want_write());
3104
3105 const std::string settings_frame =
3106 TestFrameSequence().Settings({{INITIAL_WINDOW_SIZE, 80000u}}).Serialize();
3107 // SETTINGS with INITIAL_STREAM_WINDOW
3108 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
3109 EXPECT_CALL(visitor, OnSettingsStart());
3110 EXPECT_CALL(visitor, OnSetting(Http2Setting{INITIAL_WINDOW_SIZE, 80000u}));
3111 EXPECT_CALL(visitor, OnSettingsEnd());
3112
3113 const int64_t settings_result = adapter->ProcessBytes(settings_frame);
3114 EXPECT_EQ(settings_frame.size(), static_cast<size_t>(settings_result));
3115
3116 EXPECT_TRUE(adapter->want_write());
3117
3118 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
3119 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
3120 // The client can write more after receiving the INITIAL_WINDOW_SIZE setting.
3121 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, 14465, 0x0, 0));
3122
3123 result = adapter->Send();
3124 EXPECT_EQ(0, result);
3125 EXPECT_THAT(visitor.data(),
3126 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::DATA}));
3127 }
3128
TEST(NgHttp2AdapterTest,InvalidInitialWindowSetting)3129 TEST(NgHttp2AdapterTest, InvalidInitialWindowSetting) {
3130 DataSavingVisitor visitor;
3131 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
3132
3133 const uint32_t kTooLargeInitialWindow = 1u << 31;
3134 const std::string initial_frames =
3135 TestFrameSequence()
3136 .Settings({{INITIAL_WINDOW_SIZE, kTooLargeInitialWindow}})
3137 .Serialize();
3138 // Server preface (SETTINGS with INITIAL_STREAM_WINDOW)
3139 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
3140 EXPECT_CALL(visitor,
3141 OnInvalidFrame(
3142 0, Http2VisitorInterface::InvalidFrameError::kFlowControl));
3143
3144 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
3145 EXPECT_EQ(initial_frames.size(), static_cast<size_t>(initial_result));
3146
3147 // Session will want to write a GOAWAY.
3148 EXPECT_TRUE(adapter->want_write());
3149
3150 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
3151 EXPECT_CALL(
3152 visitor,
3153 OnFrameSent(GOAWAY, 0, _, 0x0,
3154 static_cast<int>(Http2ErrorCode::FLOW_CONTROL_ERROR)));
3155
3156 int64_t result = adapter->Send();
3157 EXPECT_EQ(0, result);
3158 absl::string_view serialized = visitor.data();
3159 EXPECT_THAT(serialized,
3160 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
3161 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
3162 EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::GOAWAY}));
3163 visitor.Clear();
3164 }
3165
TEST(NgHttp2AdapterTest,InitialWindowSettingCausesOverflow)3166 TEST(NgHttp2AdapterTest, InitialWindowSettingCausesOverflow) {
3167 DataSavingVisitor visitor;
3168 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
3169
3170 testing::InSequence s;
3171
3172 const std::vector<Header> headers =
3173 ToHeaders({{":method", "GET"},
3174 {":scheme", "http"},
3175 {":authority", "example.com"},
3176 {":path", "/this/is/request/one"}});
3177 const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
3178 ASSERT_GT(stream_id, 0);
3179 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
3180 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
3181 int64_t write_result = adapter->Send();
3182 EXPECT_EQ(0, write_result);
3183 absl::string_view data = visitor.data();
3184 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
3185 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
3186 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::HEADERS}));
3187 visitor.Clear();
3188
3189 const uint32_t kLargeInitialWindow = (1u << 31) - 1;
3190 const std::string frames =
3191 TestFrameSequence()
3192 .ServerPreface()
3193 .Headers(stream_id, {{":status", "200"}}, /*fin=*/false)
3194 .WindowUpdate(stream_id, 65536u)
3195 .Settings({{INITIAL_WINDOW_SIZE, kLargeInitialWindow}})
3196 .Serialize();
3197
3198 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3199 EXPECT_CALL(visitor, OnSettingsStart());
3200 EXPECT_CALL(visitor, OnSettingsEnd());
3201
3202 EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 0x4));
3203 EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
3204 EXPECT_CALL(visitor, OnHeaderForStream(stream_id, ":status", "200"));
3205 EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
3206
3207 EXPECT_CALL(visitor, OnFrameHeader(stream_id, 4, WINDOW_UPDATE, 0x0));
3208 EXPECT_CALL(visitor, OnWindowUpdate(stream_id, 65536));
3209
3210 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
3211 EXPECT_CALL(visitor, OnSettingsStart());
3212 EXPECT_CALL(visitor, OnSetting(Http2Setting{INITIAL_WINDOW_SIZE,
3213 kLargeInitialWindow}));
3214 EXPECT_CALL(visitor, OnSettingsEnd());
3215
3216 const int64_t read_result = adapter->ProcessBytes(frames);
3217 EXPECT_EQ(static_cast<size_t>(read_result), frames.size());
3218 EXPECT_TRUE(adapter->want_write());
3219
3220 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
3221 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
3222 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
3223 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
3224
3225 // The stream window update plus the SETTINGS frame with INITIAL_WINDOW_SIZE
3226 // pushes the stream's flow control window outside of the acceptable range.
3227 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, stream_id, 4, 0x0));
3228 EXPECT_CALL(
3229 visitor,
3230 OnFrameSent(RST_STREAM, stream_id, 4, 0x0,
3231 static_cast<int>(Http2ErrorCode::FLOW_CONTROL_ERROR)));
3232 EXPECT_CALL(visitor,
3233 OnCloseStream(stream_id, Http2ErrorCode::FLOW_CONTROL_ERROR));
3234
3235 int result = adapter->Send();
3236 EXPECT_EQ(0, result);
3237 EXPECT_THAT(visitor.data(),
3238 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS,
3239 SpdyFrameType::RST_STREAM}));
3240 }
3241
TEST(NgHttp2AdapterTest,ClientForbidsPushPromise)3242 TEST(NgHttp2AdapterTest, ClientForbidsPushPromise) {
3243 DataSavingVisitor visitor;
3244 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
3245 adapter->SubmitSettings({{ENABLE_PUSH, 0}});
3246
3247 testing::InSequence s;
3248
3249 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
3250 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
3251
3252 int write_result = adapter->Send();
3253 EXPECT_EQ(0, write_result);
3254 absl::string_view data = visitor.data();
3255 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
3256 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
3257 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::SETTINGS}));
3258
3259 visitor.Clear();
3260
3261 const std::vector<Header> headers =
3262 ToHeaders({{":method", "GET"},
3263 {":scheme", "http"},
3264 {":authority", "example.com"},
3265 {":path", "/this/is/request/one"}});
3266 const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
3267 ASSERT_GT(stream_id, 0);
3268 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
3269 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
3270 write_result = adapter->Send();
3271 EXPECT_EQ(0, write_result);
3272 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
3273 visitor.Clear();
3274
3275 const std::vector<Header> push_headers =
3276 ToHeaders({{":method", "GET"},
3277 {":scheme", "http"},
3278 {":authority", "example.com"},
3279 {":path", "/this/is/request/push"}});
3280 const std::string frames = TestFrameSequence()
3281 .ServerPreface()
3282 .SettingsAck()
3283 .PushPromise(stream_id, 2, push_headers)
3284 .Serialize();
3285
3286 // Server preface (empty SETTINGS)
3287 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3288 EXPECT_CALL(visitor, OnSettingsStart());
3289 EXPECT_CALL(visitor, OnSettingsEnd());
3290
3291 // SETTINGS ack (to acknowledge PUSH_ENABLED=0)
3292 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0x1));
3293 EXPECT_CALL(visitor, OnSettingsAck);
3294
3295 // The PUSH_PROMISE is now treated as an invalid frame.
3296 EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, PUSH_PROMISE, _));
3297 EXPECT_CALL(visitor, OnInvalidFrame(stream_id, _));
3298
3299 const int64_t read_result = adapter->ProcessBytes(frames);
3300 EXPECT_EQ(frames.size(), read_result);
3301
3302 EXPECT_TRUE(adapter->want_write());
3303
3304 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
3305 EXPECT_CALL(
3306 visitor,
3307 OnFrameSent(GOAWAY, 0, _, 0x0,
3308 static_cast<int32_t>(Http2ErrorCode::PROTOCOL_ERROR)));
3309
3310 write_result = adapter->Send();
3311 EXPECT_EQ(0, write_result);
3312 }
3313
TEST(NgHttp2AdapterTest,ClientForbidsPushStream)3314 TEST(NgHttp2AdapterTest, ClientForbidsPushStream) {
3315 DataSavingVisitor visitor;
3316 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
3317 adapter->SubmitSettings({{ENABLE_PUSH, 0}});
3318
3319 testing::InSequence s;
3320
3321 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
3322 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
3323
3324 int write_result = adapter->Send();
3325 EXPECT_EQ(0, write_result);
3326 absl::string_view data = visitor.data();
3327 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
3328 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
3329 EXPECT_THAT(data, EqualsFrames({SpdyFrameType::SETTINGS}));
3330
3331 visitor.Clear();
3332
3333 const std::vector<Header> headers =
3334 ToHeaders({{":method", "GET"},
3335 {":scheme", "http"},
3336 {":authority", "example.com"},
3337 {":path", "/this/is/request/one"}});
3338 const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
3339 ASSERT_GT(stream_id, 0);
3340 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
3341 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
3342 write_result = adapter->Send();
3343 EXPECT_EQ(0, write_result);
3344 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
3345 visitor.Clear();
3346
3347 const std::string frames =
3348 TestFrameSequence()
3349 .ServerPreface()
3350 .SettingsAck()
3351 .Headers(2,
3352 {{":status", "200"},
3353 {"server", "my-fake-server"},
3354 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
3355 /*fin=*/true)
3356 .Serialize();
3357
3358 // Server preface (empty SETTINGS)
3359 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3360 EXPECT_CALL(visitor, OnSettingsStart());
3361 EXPECT_CALL(visitor, OnSettingsEnd());
3362
3363 // SETTINGS ack (to acknowledge PUSH_ENABLED=0)
3364 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0x1));
3365 EXPECT_CALL(visitor, OnSettingsAck);
3366
3367 // The push HEADERS are invalid.
3368 EXPECT_CALL(visitor, OnFrameHeader(2, _, HEADERS, _));
3369 EXPECT_CALL(visitor, OnInvalidFrame(2, _));
3370
3371 const int64_t read_result = adapter->ProcessBytes(frames);
3372 EXPECT_EQ(frames.size(), read_result);
3373
3374 EXPECT_TRUE(adapter->want_write());
3375
3376 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
3377 EXPECT_CALL(
3378 visitor,
3379 OnFrameSent(GOAWAY, 0, _, 0x0,
3380 static_cast<int32_t>(Http2ErrorCode::PROTOCOL_ERROR)));
3381
3382 write_result = adapter->Send();
3383 EXPECT_EQ(0, write_result);
3384 }
3385
TEST(NgHttp2AdapterTest,FailureSendingConnectionPreface)3386 TEST(NgHttp2AdapterTest, FailureSendingConnectionPreface) {
3387 DataSavingVisitor visitor;
3388 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
3389
3390 visitor.set_has_write_error();
3391 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kSendError));
3392
3393 int result = adapter->Send();
3394 EXPECT_EQ(result, NGHTTP2_ERR_CALLBACK_FAILURE);
3395 }
3396
TEST(NgHttp2AdapterTest,MaxFrameSizeSettingNotAppliedBeforeAck)3397 TEST(NgHttp2AdapterTest, MaxFrameSizeSettingNotAppliedBeforeAck) {
3398 DataSavingVisitor visitor;
3399 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
3400
3401 const uint32_t large_frame_size = kDefaultFramePayloadSizeLimit + 42;
3402 adapter->SubmitSettings({{MAX_FRAME_SIZE, large_frame_size}});
3403 const int32_t stream_id =
3404 adapter->SubmitRequest(ToHeaders({{":method", "GET"},
3405 {":scheme", "https"},
3406 {":authority", "example.com"},
3407 {":path", "/this/is/request/one"}}),
3408 /*data_source=*/nullptr, /*user_data=*/nullptr);
3409 EXPECT_GT(stream_id, 0);
3410 EXPECT_TRUE(adapter->want_write());
3411
3412 testing::InSequence s;
3413
3414 // Client preface (SETTINGS with MAX_FRAME_SIZE) and request HEADERS
3415 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
3416 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
3417 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
3418 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
3419
3420 int send_result = adapter->Send();
3421 EXPECT_EQ(0, send_result);
3422 absl::string_view data = visitor.data();
3423 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
3424 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
3425 EXPECT_THAT(data,
3426 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
3427 visitor.Clear();
3428
3429 const std::string server_frames =
3430 TestFrameSequence()
3431 .ServerPreface()
3432 .Headers(1, {{":status", "200"}}, /*fin=*/false)
3433 .Data(1, std::string(large_frame_size, 'a'))
3434 .Serialize();
3435
3436 // Server preface (empty SETTINGS)
3437 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3438 EXPECT_CALL(visitor, OnSettingsStart());
3439 EXPECT_CALL(visitor, OnSettingsEnd());
3440
3441 // Response HEADERS. Because the SETTINGS with MAX_FRAME_SIZE was not
3442 // acknowledged, the large DATA is treated as a connection error. Note that
3443 // nghttp2 does not deliver any DATA or connection error events.
3444 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
3445 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
3446 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
3447 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
3448
3449 const int64_t process_result = adapter->ProcessBytes(server_frames);
3450 EXPECT_EQ(server_frames.size(), static_cast<size_t>(process_result));
3451
3452 EXPECT_TRUE(adapter->want_write());
3453
3454 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
3455 EXPECT_CALL(visitor,
3456 OnFrameSent(GOAWAY, 0, _, 0x0,
3457 static_cast<int>(Http2ErrorCode::FRAME_SIZE_ERROR)));
3458
3459 send_result = adapter->Send();
3460 EXPECT_EQ(0, send_result);
3461 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
3462 }
3463
TEST(NgHttp2AdapterTest,MaxFrameSizeSettingAppliedAfterAck)3464 TEST(NgHttp2AdapterTest, MaxFrameSizeSettingAppliedAfterAck) {
3465 DataSavingVisitor visitor;
3466 auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
3467
3468 const uint32_t large_frame_size = kDefaultFramePayloadSizeLimit + 42;
3469 adapter->SubmitSettings({{MAX_FRAME_SIZE, large_frame_size}});
3470 const int32_t stream_id =
3471 adapter->SubmitRequest(ToHeaders({{":method", "GET"},
3472 {":scheme", "https"},
3473 {":authority", "example.com"},
3474 {":path", "/this/is/request/one"}}),
3475 /*data_source=*/nullptr, /*user_data=*/nullptr);
3476 EXPECT_GT(stream_id, 0);
3477 EXPECT_TRUE(adapter->want_write());
3478
3479 testing::InSequence s;
3480
3481 // Client preface (SETTINGS with MAX_FRAME_SIZE) and request HEADERS
3482 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
3483 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
3484 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
3485 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
3486
3487 int send_result = adapter->Send();
3488 EXPECT_EQ(0, send_result);
3489 absl::string_view data = visitor.data();
3490 EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
3491 data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
3492 EXPECT_THAT(data,
3493 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
3494 visitor.Clear();
3495
3496 const std::string server_frames =
3497 TestFrameSequence()
3498 .ServerPreface()
3499 .SettingsAck()
3500 .Headers(1, {{":status", "200"}}, /*fin=*/false)
3501 .Data(1, std::string(large_frame_size, 'a'))
3502 .Serialize();
3503
3504 // Server preface (empty SETTINGS) and ack of SETTINGS.
3505 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3506 EXPECT_CALL(visitor, OnSettingsStart());
3507 EXPECT_CALL(visitor, OnSettingsEnd());
3508 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0x1));
3509 EXPECT_CALL(visitor, OnSettingsAck());
3510
3511 // Response HEADERS and DATA. Because the SETTINGS with MAX_FRAME_SIZE was
3512 // acknowledged, the large DATA is accepted without any error.
3513 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
3514 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
3515 EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
3516 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
3517 EXPECT_CALL(visitor, OnFrameHeader(1, large_frame_size, DATA, 0x0));
3518 EXPECT_CALL(visitor, OnBeginDataForStream(1, large_frame_size));
3519 EXPECT_CALL(visitor, OnDataForStream(1, _));
3520
3521 const int64_t process_result = adapter->ProcessBytes(server_frames);
3522 EXPECT_EQ(server_frames.size(), static_cast<size_t>(process_result));
3523
3524 // Client ack of SETTINGS.
3525 EXPECT_TRUE(adapter->want_write());
3526 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
3527 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
3528
3529 send_result = adapter->Send();
3530 EXPECT_EQ(0, send_result);
3531 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
3532 }
3533
TEST(NgHttp2AdapterTest,WindowUpdateRaisesFlowControlWindowLimit)3534 TEST(NgHttp2AdapterTest, WindowUpdateRaisesFlowControlWindowLimit) {
3535 DataSavingVisitor visitor;
3536 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
3537
3538 const std::string data_chunk(kDefaultFramePayloadSizeLimit, 'a');
3539 const std::string request = TestFrameSequence()
3540 .ClientPreface()
3541 .Headers(1,
3542 {{":method", "GET"},
3543 {":scheme", "https"},
3544 {":authority", "example.com"},
3545 {":path", "/"}},
3546 /*fin=*/false)
3547 .Serialize();
3548
3549 // Client preface (empty SETTINGS)
3550 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3551 EXPECT_CALL(visitor, OnSettingsStart());
3552 EXPECT_CALL(visitor, OnSettingsEnd());
3553 // Stream 1
3554 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
3555 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
3556 EXPECT_CALL(visitor, OnHeaderForStream).Times(4);
3557 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
3558
3559 adapter->ProcessBytes(request);
3560
3561 // Updates the advertised window for the connection and stream 1.
3562 adapter->SubmitWindowUpdate(0, 2 * kDefaultFramePayloadSizeLimit);
3563 adapter->SubmitWindowUpdate(1, 2 * kDefaultFramePayloadSizeLimit);
3564
3565 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
3566 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
3567 EXPECT_CALL(visitor, OnBeforeFrameSent(WINDOW_UPDATE, 0, 4, 0x0));
3568 EXPECT_CALL(visitor, OnFrameSent(WINDOW_UPDATE, 0, 4, 0x0, 0));
3569 EXPECT_CALL(visitor, OnBeforeFrameSent(WINDOW_UPDATE, 1, 4, 0x0));
3570 EXPECT_CALL(visitor, OnFrameSent(WINDOW_UPDATE, 1, 4, 0x0, 0));
3571
3572 int result = adapter->Send();
3573 EXPECT_EQ(0, result);
3574
3575 // Verifies the advertised window.
3576 EXPECT_EQ(kInitialFlowControlWindowSize + 2 * kDefaultFramePayloadSizeLimit,
3577 adapter->GetReceiveWindowSize());
3578 EXPECT_EQ(kInitialFlowControlWindowSize + 2 * kDefaultFramePayloadSizeLimit,
3579 adapter->GetStreamReceiveWindowSize(1));
3580
3581 const std::string request_body = TestFrameSequence()
3582 .Data(1, data_chunk)
3583 .Data(1, data_chunk)
3584 .Data(1, data_chunk)
3585 .Data(1, data_chunk)
3586 .Data(1, data_chunk)
3587 .Serialize();
3588
3589 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0)).Times(5);
3590 EXPECT_CALL(visitor, OnBeginDataForStream(1, _)).Times(5);
3591 EXPECT_CALL(visitor, OnDataForStream(1, _)).Times(5);
3592
3593 // DATA frames on stream 1 consume most of the window.
3594 adapter->ProcessBytes(request_body);
3595 EXPECT_EQ(kInitialFlowControlWindowSize - 3 * kDefaultFramePayloadSizeLimit,
3596 adapter->GetReceiveWindowSize());
3597 EXPECT_EQ(kInitialFlowControlWindowSize - 3 * kDefaultFramePayloadSizeLimit,
3598 adapter->GetStreamReceiveWindowSize(1));
3599
3600 // Marking the data consumed should result in an advertised window larger than
3601 // the initial window.
3602 adapter->MarkDataConsumedForStream(1, 4 * kDefaultFramePayloadSizeLimit);
3603 EXPECT_GT(adapter->GetReceiveWindowSize(), kInitialFlowControlWindowSize);
3604 EXPECT_GT(adapter->GetStreamReceiveWindowSize(1),
3605 kInitialFlowControlWindowSize);
3606 }
3607
TEST(NgHttp2AdapterTest,ConnectionErrorOnControlFrameSent)3608 TEST(NgHttp2AdapterTest, ConnectionErrorOnControlFrameSent) {
3609 DataSavingVisitor visitor;
3610 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
3611
3612 const std::string frames =
3613 TestFrameSequence().ClientPreface().Ping(42).Serialize();
3614 testing::InSequence s;
3615
3616 // Client preface (empty SETTINGS)
3617 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3618 EXPECT_CALL(visitor, OnSettingsStart());
3619 EXPECT_CALL(visitor, OnSettingsEnd());
3620 // PING
3621 EXPECT_CALL(visitor, OnFrameHeader(0, _, PING, 0));
3622 EXPECT_CALL(visitor, OnPing(42, false));
3623
3624 const int64_t read_result = adapter->ProcessBytes(frames);
3625 EXPECT_EQ(static_cast<size_t>(read_result), frames.size());
3626
3627 EXPECT_TRUE(adapter->want_write());
3628
3629 // SETTINGS ack
3630 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
3631 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0))
3632 .WillOnce(testing::Return(-902));
3633 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kSendError));
3634
3635 int send_result = adapter->Send();
3636 EXPECT_LT(send_result, 0);
3637
3638 // Apparently nghttp2 retries sending the frames that had failed before.
3639 EXPECT_TRUE(adapter->want_write());
3640
3641 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
3642 EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, _, 0x1));
3643 EXPECT_CALL(visitor, OnFrameSent(PING, 0, _, 0x1, 0));
3644 send_result = adapter->Send();
3645 EXPECT_EQ(send_result, 0);
3646
3647 EXPECT_FALSE(adapter->want_write());
3648 }
3649
TEST(NgHttp2AdapterTest,ConnectionErrorOnDataFrameSent)3650 TEST(NgHttp2AdapterTest, ConnectionErrorOnDataFrameSent) {
3651 DataSavingVisitor visitor;
3652 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
3653
3654 const std::string frames = TestFrameSequence()
3655 .ClientPreface()
3656 .Headers(1,
3657 {{":method", "GET"},
3658 {":scheme", "https"},
3659 {":authority", "example.com"},
3660 {":path", "/this/is/request/one"}},
3661 /*fin=*/true)
3662 .Serialize();
3663 testing::InSequence s;
3664
3665 // Client preface (empty SETTINGS)
3666 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3667 EXPECT_CALL(visitor, OnSettingsStart());
3668 EXPECT_CALL(visitor, OnSettingsEnd());
3669 // Stream 1
3670 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x5));
3671 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
3672 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
3673 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
3674 EXPECT_CALL(visitor, OnEndStream(1));
3675
3676 const int64_t read_result = adapter->ProcessBytes(frames);
3677 EXPECT_EQ(static_cast<size_t>(read_result), frames.size());
3678
3679 auto body = std::make_unique<TestDataFrameSource>(visitor, true);
3680 body->AppendPayload("Here is some data, which will lead to a fatal error");
3681 TestDataFrameSource* body_ptr = body.get();
3682 int submit_result = adapter->SubmitResponse(
3683 1, ToHeaders({{":status", "200"}}), std::move(body));
3684 ASSERT_EQ(0, submit_result);
3685
3686 EXPECT_TRUE(adapter->want_write());
3687
3688 // SETTINGS ack
3689 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
3690 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
3691 // Stream 1, with doomed DATA
3692 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
3693 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
3694 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0))
3695 .WillOnce(testing::Return(-902));
3696 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kSendError));
3697
3698 int send_result = adapter->Send();
3699 EXPECT_LT(send_result, 0);
3700
3701 // The test data source got a signal that the first chunk of data was sent
3702 // successfully, so discarded that data internally. However, due to the send
3703 // error, the next Send() from nghttp2 will try to send that exact same data
3704 // again. Without this line appending the exact same data back to the data
3705 // source, the test crashes. It is not clear how the data source would know to
3706 // not discard the data, unless told by the session? This is not intuitive.
3707 body_ptr->AppendPayload(
3708 "Here is some data, which will lead to a fatal error");
3709
3710 // Apparently nghttp2 retries sending the frames that had failed before.
3711 EXPECT_TRUE(adapter->want_write());
3712 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
3713
3714 send_result = adapter->Send();
3715 EXPECT_EQ(send_result, 0);
3716
3717 EXPECT_FALSE(adapter->want_write());
3718 }
3719
TEST(NgHttp2AdapterTest,ServerConstruction)3720 TEST(NgHttp2AdapterTest, ServerConstruction) {
3721 testing::StrictMock<MockHttp2Visitor> visitor;
3722 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
3723 ASSERT_NE(nullptr, adapter);
3724 EXPECT_TRUE(adapter->want_read());
3725 EXPECT_FALSE(adapter->want_write());
3726 EXPECT_TRUE(adapter->IsServerSession());
3727 }
3728
TEST(NgHttp2AdapterTest,ServerHandlesFrames)3729 TEST(NgHttp2AdapterTest, ServerHandlesFrames) {
3730 DataSavingVisitor visitor;
3731 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
3732
3733 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
3734 EXPECT_EQ(0, adapter->GetHpackDecoderDynamicTableSize());
3735
3736 const std::string frames = TestFrameSequence()
3737 .ClientPreface()
3738 .Ping(42)
3739 .WindowUpdate(0, 1000)
3740 .Headers(1,
3741 {{":method", "POST"},
3742 {":scheme", "https"},
3743 {":authority", "example.com"},
3744 {":path", "/this/is/request/one"}},
3745 /*fin=*/false)
3746 .WindowUpdate(1, 2000)
3747 .Data(1, "This is the request body.")
3748 .Headers(3,
3749 {{":method", "GET"},
3750 {":scheme", "http"},
3751 {":authority", "example.com"},
3752 {":path", "/this/is/request/two"}},
3753 /*fin=*/true)
3754 .RstStream(3, Http2ErrorCode::CANCEL)
3755 .Ping(47)
3756 .Serialize();
3757 testing::InSequence s;
3758
3759 const char* kSentinel1 = "arbitrary pointer 1";
3760
3761 // Client preface (empty SETTINGS)
3762 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3763 EXPECT_CALL(visitor, OnSettingsStart());
3764 EXPECT_CALL(visitor, OnSettingsEnd());
3765
3766 EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
3767 EXPECT_CALL(visitor, OnPing(42, false));
3768 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
3769 EXPECT_CALL(visitor, OnWindowUpdate(0, 1000));
3770 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
3771 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
3772 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
3773 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
3774 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
3775 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
3776 EXPECT_CALL(visitor, OnEndHeadersForStream(1))
3777 .WillOnce(testing::InvokeWithoutArgs([&adapter, kSentinel1]() {
3778 adapter->SetStreamUserData(1, const_cast<char*>(kSentinel1));
3779 return true;
3780 }));
3781 EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
3782 EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
3783 EXPECT_CALL(visitor, OnFrameHeader(1, 25, DATA, 0));
3784 EXPECT_CALL(visitor, OnBeginDataForStream(1, 25));
3785 EXPECT_CALL(visitor, OnDataForStream(1, "This is the request body."));
3786 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 5));
3787 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
3788 EXPECT_CALL(visitor, OnHeaderForStream(3, ":method", "GET"));
3789 EXPECT_CALL(visitor, OnHeaderForStream(3, ":scheme", "http"));
3790 EXPECT_CALL(visitor, OnHeaderForStream(3, ":authority", "example.com"));
3791 EXPECT_CALL(visitor, OnHeaderForStream(3, ":path", "/this/is/request/two"));
3792 EXPECT_CALL(visitor, OnEndHeadersForStream(3));
3793 EXPECT_CALL(visitor, OnEndStream(3));
3794 EXPECT_CALL(visitor, OnFrameHeader(3, 4, RST_STREAM, 0));
3795 EXPECT_CALL(visitor, OnRstStream(3, Http2ErrorCode::CANCEL));
3796 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::CANCEL));
3797 EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
3798 EXPECT_CALL(visitor, OnPing(47, false));
3799
3800 const int64_t result = adapter->ProcessBytes(frames);
3801 EXPECT_EQ(frames.size(), result);
3802
3803 EXPECT_EQ(kSentinel1, adapter->GetStreamUserData(1));
3804
3805 EXPECT_GT(kInitialFlowControlWindowSize,
3806 adapter->GetStreamReceiveWindowSize(1));
3807 EXPECT_EQ(adapter->GetStreamReceiveWindowSize(1),
3808 adapter->GetReceiveWindowSize());
3809 // Upper bound should still be the original value.
3810 EXPECT_EQ(kInitialFlowControlWindowSize,
3811 adapter->GetStreamReceiveWindowLimit(1));
3812
3813 EXPECT_GT(adapter->GetHpackDecoderDynamicTableSize(), 0);
3814
3815 // Because stream 3 has already been closed, it's not possible to set user
3816 // data.
3817 const char* kSentinel3 = "another arbitrary pointer";
3818 adapter->SetStreamUserData(3, const_cast<char*>(kSentinel3));
3819 EXPECT_EQ(nullptr, adapter->GetStreamUserData(3));
3820
3821 EXPECT_EQ(3, adapter->GetHighestReceivedStreamId());
3822
3823 EXPECT_EQ(adapter->GetSendWindowSize(), kInitialFlowControlWindowSize + 1000);
3824
3825 EXPECT_TRUE(adapter->want_write());
3826
3827 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
3828 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
3829 EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, 8, 0x1));
3830 EXPECT_CALL(visitor, OnFrameSent(PING, 0, 8, 0x1, 0));
3831 EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, 8, 0x1));
3832 EXPECT_CALL(visitor, OnFrameSent(PING, 0, 8, 0x1, 0));
3833
3834 int send_result = adapter->Send();
3835 // Some bytes should have been serialized.
3836 EXPECT_EQ(0, send_result);
3837 // SETTINGS ack, two PING acks.
3838 EXPECT_THAT(visitor.data(),
3839 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::PING,
3840 SpdyFrameType::PING}));
3841 }
3842
TEST(NgHttp2AdapterTest,ServerVisitorRejectsHeaders)3843 TEST(NgHttp2AdapterTest, ServerVisitorRejectsHeaders) {
3844 DataSavingVisitor visitor;
3845 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
3846 EXPECT_FALSE(adapter->want_write());
3847
3848 const std::string frames =
3849 TestFrameSequence()
3850 .ClientPreface()
3851 .Headers(1,
3852 {{":method", "GET"},
3853 {":scheme", "https"},
3854 {":authority", "example.com"},
3855 {":path", "/this/is/request/one"},
3856 {"header1", "ok"},
3857 {"header2", "rejected"},
3858 {"header3", "not processed"}, // CONTINUATION starts here
3859 {"header4", "not processed"},
3860 {"header5", "not processed"},
3861 {"header6", "not processed"},
3862 {"header7", "not processed"},
3863 {"header8", "not processed"}},
3864 /*fin=*/false, /*add_continuation=*/true)
3865 .Serialize();
3866
3867 testing::InSequence s;
3868
3869 // Client preface (empty SETTINGS)
3870 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3871 EXPECT_CALL(visitor, OnSettingsStart());
3872 EXPECT_CALL(visitor, OnSettingsEnd());
3873 // Stream 1
3874 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x0));
3875 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
3876 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(5);
3877 EXPECT_CALL(visitor, OnHeaderForStream(1, "header2", _))
3878 .WillOnce(testing::Return(Http2VisitorInterface::HEADER_RST_STREAM));
3879 // The CONTINUATION frame header and header fields are not processed.
3880
3881 int64_t result = adapter->ProcessBytes(frames);
3882 EXPECT_EQ(static_cast<size_t>(result), frames.size());
3883
3884 EXPECT_TRUE(adapter->want_write());
3885
3886 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
3887 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
3888 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
3889 EXPECT_CALL(visitor,
3890 OnFrameSent(RST_STREAM, 1, _, 0x0,
3891 static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
3892 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::INTERNAL_ERROR));
3893
3894 int send_result = adapter->Send();
3895 // Some bytes should have been serialized.
3896 EXPECT_EQ(0, send_result);
3897 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
3898 SpdyFrameType::RST_STREAM}));
3899 }
3900
TEST(OgHttp2AdapterTest,HeaderValuesWithObsTextAllowed)3901 TEST(OgHttp2AdapterTest, HeaderValuesWithObsTextAllowed) {
3902 DataSavingVisitor visitor;
3903 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
3904
3905 const std::string frames = TestFrameSequence()
3906 .ClientPreface()
3907 .Headers(1,
3908 {{":method", "GET"},
3909 {":scheme", "https"},
3910 {":authority", "example.com"},
3911 {":path", "/"},
3912 {"name", "val\xa1ue"}},
3913 /*fin=*/true)
3914 .Serialize();
3915 testing::InSequence s;
3916
3917 // Client preface (empty SETTINGS)
3918 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3919 EXPECT_CALL(visitor, OnSettingsStart());
3920 EXPECT_CALL(visitor, OnSettingsEnd());
3921 // Stream 1
3922 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
3923 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
3924 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
3925 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
3926 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
3927 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/"));
3928 EXPECT_CALL(visitor, OnHeaderForStream(1, "name", "val\xa1ue"));
3929 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
3930 EXPECT_CALL(visitor, OnEndStream(1));
3931
3932 const int64_t result = adapter->ProcessBytes(frames);
3933 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
3934 }
3935
TEST(NgHttp2AdapterTest,ServerHandlesDataWithPadding)3936 TEST(NgHttp2AdapterTest, ServerHandlesDataWithPadding) {
3937 DataSavingVisitor visitor;
3938 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
3939
3940 const std::string frames = TestFrameSequence()
3941 .ClientPreface()
3942 .Headers(1,
3943 {{":method", "POST"},
3944 {":scheme", "https"},
3945 {":authority", "example.com"},
3946 {":path", "/this/is/request/one"}},
3947 /*fin=*/false)
3948 .Data(1, "This is the request body.",
3949 /*fin=*/true, /*padding_length=*/39)
3950 .Headers(3,
3951 {{":method", "GET"},
3952 {":scheme", "http"},
3953 {":authority", "example.com"},
3954 {":path", "/this/is/request/two"}},
3955 /*fin=*/true)
3956 .Serialize();
3957 testing::InSequence s;
3958
3959 // Client preface (empty SETTINGS)
3960 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
3961 EXPECT_CALL(visitor, OnSettingsStart());
3962 EXPECT_CALL(visitor, OnSettingsEnd());
3963
3964 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
3965 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
3966 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
3967 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
3968 EXPECT_CALL(visitor, OnFrameHeader(1, 25 + 39, DATA, 0x9));
3969 EXPECT_CALL(visitor, OnBeginDataForStream(1, 25 + 39));
3970 EXPECT_CALL(visitor, OnDataForStream(1, "This is the request body."));
3971 // Note: nghttp2 passes padding information after the actual data.
3972 EXPECT_CALL(visitor, OnDataPaddingLength(1, 39));
3973 EXPECT_CALL(visitor, OnEndStream(1));
3974 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 5));
3975 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
3976 EXPECT_CALL(visitor, OnHeaderForStream(3, _, _)).Times(4);
3977 EXPECT_CALL(visitor, OnEndHeadersForStream(3));
3978 EXPECT_CALL(visitor, OnEndStream(3));
3979
3980 const int64_t result = adapter->ProcessBytes(frames);
3981 EXPECT_EQ(frames.size(), result);
3982
3983 EXPECT_TRUE(adapter->want_write());
3984
3985 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
3986 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
3987
3988 int send_result = adapter->Send();
3989 EXPECT_EQ(0, send_result);
3990 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
3991 }
3992
TEST(NgHttp2AdapterTest,ServerHandlesHostHeader)3993 TEST(NgHttp2AdapterTest, ServerHandlesHostHeader) {
3994 DataSavingVisitor visitor;
3995 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
3996
3997 const std::string frames = TestFrameSequence()
3998 .ClientPreface()
3999 .Headers(1,
4000 {{":method", "POST"},
4001 {":scheme", "https"},
4002 {":path", "/this/is/request/one"},
4003 {"host", "example.com"}},
4004 /*fin=*/true)
4005 .Headers(3,
4006 {{":method", "POST"},
4007 {":scheme", "https"},
4008 {":authority", "example.com"},
4009 {":path", "/this/is/request/one"},
4010 {"host", "example.com"}},
4011 /*fin=*/true)
4012 .Headers(5,
4013 {{":method", "POST"},
4014 {":scheme", "https"},
4015 {":authority", "foo.com"},
4016 {":path", "/this/is/request/one"},
4017 {"host", "bar.com"}},
4018 /*fin=*/true)
4019 .Serialize();
4020
4021 testing::InSequence s;
4022
4023 // Client preface (empty SETTINGS)
4024 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4025 EXPECT_CALL(visitor, OnSettingsStart());
4026 EXPECT_CALL(visitor, OnSettingsEnd());
4027
4028 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
4029 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4030 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
4031 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
4032 EXPECT_CALL(visitor, OnEndStream(1));
4033
4034 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 5));
4035 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
4036 EXPECT_CALL(visitor, OnHeaderForStream(3, _, _)).Times(5);
4037 EXPECT_CALL(visitor, OnEndHeadersForStream(3));
4038 EXPECT_CALL(visitor, OnEndStream(3));
4039
4040 EXPECT_CALL(visitor, OnFrameHeader(5, _, HEADERS, 5));
4041 EXPECT_CALL(visitor, OnBeginHeadersForStream(5));
4042 EXPECT_CALL(visitor, OnHeaderForStream(5, _, _)).Times(5);
4043 EXPECT_CALL(visitor, OnEndHeadersForStream(5));
4044 EXPECT_CALL(visitor, OnEndStream(5));
4045
4046 const int64_t result = adapter->ProcessBytes(frames);
4047 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
4048
4049 EXPECT_TRUE(adapter->want_write());
4050
4051 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
4052 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
4053
4054 int send_result = adapter->Send();
4055 EXPECT_EQ(0, send_result);
4056 visitor.Clear();
4057 }
4058
4059 // Tests the case where the response body is in the progress of being sent while
4060 // trailers are queued.
TEST(NgHttp2AdapterTest,ServerSubmitsTrailersWhileDataDeferred)4061 TEST(NgHttp2AdapterTest, ServerSubmitsTrailersWhileDataDeferred) {
4062 DataSavingVisitor visitor;
4063 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4064
4065 const std::string frames = TestFrameSequence()
4066 .ClientPreface()
4067 .Headers(1,
4068 {{":method", "POST"},
4069 {":scheme", "https"},
4070 {":authority", "example.com"},
4071 {":path", "/this/is/request/one"}},
4072 /*fin=*/false)
4073 .WindowUpdate(1, 2000)
4074 .Data(1, "This is the request body.")
4075 .WindowUpdate(0, 2000)
4076 .Serialize();
4077 testing::InSequence s;
4078
4079 // Client preface (empty SETTINGS)
4080 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4081 EXPECT_CALL(visitor, OnSettingsStart());
4082 EXPECT_CALL(visitor, OnSettingsEnd());
4083
4084 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
4085 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4086 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
4087 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
4088 EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
4089 EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
4090 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0));
4091 EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
4092 EXPECT_CALL(visitor, OnDataForStream(1, "This is the request body."));
4093 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
4094 EXPECT_CALL(visitor, OnWindowUpdate(0, 2000));
4095
4096 const int64_t result = adapter->ProcessBytes(frames);
4097 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
4098
4099 EXPECT_TRUE(adapter->want_write());
4100
4101 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
4102 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
4103
4104 int send_result = adapter->Send();
4105 EXPECT_EQ(0, send_result);
4106 visitor.Clear();
4107
4108 const absl::string_view kBody = "This is an example response body.";
4109
4110 // The body source must indicate that the end of the body is not the end of
4111 // the stream.
4112 auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
4113 body1->AppendPayload(kBody);
4114 auto* body1_ptr = body1.get();
4115 int submit_result = adapter->SubmitResponse(
4116 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
4117 std::move(body1));
4118 EXPECT_EQ(submit_result, 0);
4119 EXPECT_TRUE(adapter->want_write());
4120
4121 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
4122 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
4123 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
4124
4125 send_result = adapter->Send();
4126 // Some bytes should have been serialized.
4127 EXPECT_EQ(0, send_result);
4128 visitor.Clear();
4129 EXPECT_FALSE(adapter->want_write());
4130
4131 int trailer_result =
4132 adapter->SubmitTrailer(1, ToHeaders({{"final-status", "a-ok"}}));
4133 ASSERT_EQ(trailer_result, 0);
4134
4135 // Even though the data source has not finished sending data, nghttp2 will
4136 // write the trailers anyway.
4137 EXPECT_TRUE(adapter->want_write());
4138
4139 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
4140 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
4141
4142 send_result = adapter->Send();
4143 EXPECT_EQ(0, send_result);
4144 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
4145 visitor.Clear();
4146
4147 // Resuming the stream results in the library wanting to write again.
4148 body1_ptr->AppendPayload(kBody);
4149 body1_ptr->EndData();
4150 adapter->ResumeStream(1);
4151 EXPECT_TRUE(adapter->want_write());
4152
4153 send_result = adapter->Send();
4154 EXPECT_EQ(0, send_result);
4155
4156 // But no data is written for the stream.
4157 EXPECT_THAT(visitor.data(), testing::IsEmpty());
4158 EXPECT_FALSE(adapter->want_write());
4159 }
4160
TEST(NgHttp2AdapterTest,ServerSubmitsTrailersWithDataEndStream)4161 TEST(NgHttp2AdapterTest, ServerSubmitsTrailersWithDataEndStream) {
4162 DataSavingVisitor visitor;
4163 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4164
4165 const std::string frames =
4166 TestFrameSequence()
4167 .ClientPreface()
4168 .Headers(1, {{":method", "GET"},
4169 {":scheme", "https"},
4170 {":authority", "example.com"},
4171 {":path", "/this/is/request/one"}})
4172 .Data(1, "Example data, woohoo.")
4173 .Serialize();
4174
4175 testing::InSequence s;
4176
4177 // Client preface (empty SETTINGS)
4178 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4179 EXPECT_CALL(visitor, OnSettingsStart());
4180 EXPECT_CALL(visitor, OnSettingsEnd());
4181 // Stream 1
4182 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, END_HEADERS_FLAG));
4183 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4184 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
4185 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
4186 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
4187 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
4188 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
4189 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0));
4190 EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
4191 EXPECT_CALL(visitor, OnDataForStream(1, _));
4192
4193 const int64_t result = adapter->ProcessBytes(frames);
4194 EXPECT_EQ(static_cast<size_t>(result), frames.size());
4195
4196 // Send a body that will end with the END_STREAM flag.
4197 const absl::string_view kBody = "This is an example response body.";
4198 auto body = std::make_unique<TestDataFrameSource>(visitor, /*has_fin=*/true);
4199 body->AppendPayload(kBody);
4200 body->EndData();
4201
4202 int submit_result = adapter->SubmitResponse(
4203 1, ToHeaders({{":status", "200"}}), std::move(body));
4204 ASSERT_EQ(submit_result, 0);
4205
4206 const std::vector<Header> trailers =
4207 ToHeaders({{"extra-info", "Trailers are weird but good?"}});
4208 submit_result = adapter->SubmitTrailer(1, trailers);
4209 ASSERT_EQ(submit_result, 0);
4210
4211 // It looks like nghttp2 drops the response body altogether and goes straight
4212 // to writing the trailers.
4213 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, ACK_FLAG));
4214 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, ACK_FLAG, 0));
4215 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, END_HEADERS_FLAG));
4216 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, END_HEADERS_FLAG, 0));
4217 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _,
4218 END_HEADERS_FLAG | END_STREAM_FLAG));
4219 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _,
4220 END_HEADERS_FLAG | END_STREAM_FLAG, 0));
4221
4222 const int send_result = adapter->Send();
4223 EXPECT_EQ(send_result, 0);
4224 EXPECT_THAT(visitor.data(),
4225 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS,
4226 SpdyFrameType::HEADERS}));
4227 }
4228
TEST(NgHttp2AdapterTest,ServerSubmitsTrailersWithDataEndStreamAndDeferral)4229 TEST(NgHttp2AdapterTest, ServerSubmitsTrailersWithDataEndStreamAndDeferral) {
4230 DataSavingVisitor visitor;
4231 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4232
4233 const std::string frames =
4234 TestFrameSequence()
4235 .ClientPreface()
4236 .Headers(1, {{":method", "GET"},
4237 {":scheme", "https"},
4238 {":authority", "example.com"},
4239 {":path", "/this/is/request/one"}})
4240 .Data(1, "Example data, woohoo.")
4241 .Serialize();
4242
4243 testing::InSequence s;
4244
4245 // Client preface (empty SETTINGS)
4246 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4247 EXPECT_CALL(visitor, OnSettingsStart());
4248 EXPECT_CALL(visitor, OnSettingsEnd());
4249 // Stream 1
4250 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, END_HEADERS_FLAG));
4251 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4252 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
4253 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
4254 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
4255 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
4256 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
4257 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0));
4258 EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
4259 EXPECT_CALL(visitor, OnDataForStream(1, _));
4260
4261 const int64_t result = adapter->ProcessBytes(frames);
4262 EXPECT_EQ(static_cast<size_t>(result), frames.size());
4263
4264 // Send a body that will end with the END_STREAM flag. Don't end the body here
4265 // so that more body can be added later.
4266 const absl::string_view kBody = "This is an example response body.";
4267 auto body = std::make_unique<TestDataFrameSource>(visitor, /*has_fin=*/true);
4268 body->AppendPayload(kBody);
4269 TestDataFrameSource& body_ref = *body;
4270
4271 int submit_result = adapter->SubmitResponse(
4272 1, ToHeaders({{":status", "200"}}), std::move(body));
4273 ASSERT_EQ(submit_result, 0);
4274
4275 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, ACK_FLAG));
4276 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, ACK_FLAG, 0));
4277 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, END_HEADERS_FLAG));
4278 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, END_HEADERS_FLAG, 0));
4279 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
4280
4281 int send_result = adapter->Send();
4282 EXPECT_EQ(0, send_result);
4283 EXPECT_THAT(visitor.data(),
4284 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS,
4285 SpdyFrameType::DATA}));
4286 visitor.Clear();
4287
4288 const std::vector<Header> trailers =
4289 ToHeaders({{"extra-info", "Trailers are weird but good?"}});
4290 submit_result = adapter->SubmitTrailer(1, trailers);
4291 ASSERT_EQ(submit_result, 0);
4292
4293 // Add more body and signal the end of data. Resuming the stream should allow
4294 // the new body to be sent, though nghttp2 does not send the body.
4295 body_ref.AppendPayload(kBody);
4296 body_ref.EndData();
4297 adapter->ResumeStream(1);
4298
4299 // For some reason, nghttp2 drops the new body and goes straight to writing
4300 // the trailers.
4301 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _,
4302 END_HEADERS_FLAG | END_STREAM_FLAG));
4303 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _,
4304 END_HEADERS_FLAG | END_STREAM_FLAG, 0));
4305
4306 send_result = adapter->Send();
4307 EXPECT_EQ(send_result, 0);
4308 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
4309 }
4310
TEST(NgHttp2AdapterTest,ClientDisobeysConnectionFlowControl)4311 TEST(NgHttp2AdapterTest, ClientDisobeysConnectionFlowControl) {
4312 DataSavingVisitor visitor;
4313 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4314
4315 const std::string frames = TestFrameSequence()
4316 .ClientPreface()
4317 .Headers(1,
4318 {{":method", "POST"},
4319 {":scheme", "https"},
4320 {":authority", "example.com"},
4321 {":path", "/this/is/request/one"},
4322 {"accept", "some bogus value!"}},
4323 /*fin=*/false)
4324 // 70000 bytes of data
4325 .Data(1, std::string(16384, 'a'))
4326 .Data(1, std::string(16384, 'a'))
4327 .Data(1, std::string(16384, 'a'))
4328 .Data(1, std::string(16384, 'a'))
4329 .Data(1, std::string(4464, 'a'))
4330 .Serialize();
4331
4332 testing::InSequence s;
4333 // Client preface (empty SETTINGS)
4334 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4335 EXPECT_CALL(visitor, OnSettingsStart());
4336 EXPECT_CALL(visitor, OnSettingsEnd());
4337
4338 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
4339 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4340 EXPECT_CALL(visitor, OnHeaderForStream).Times(5);
4341 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
4342 EXPECT_CALL(visitor, OnFrameHeader(1, 16384, DATA, 0x0));
4343 EXPECT_CALL(visitor, OnBeginDataForStream(1, 16384));
4344 EXPECT_CALL(visitor, OnDataForStream(1, _));
4345 EXPECT_CALL(visitor, OnFrameHeader(1, 16384, DATA, 0x0));
4346 EXPECT_CALL(visitor, OnBeginDataForStream(1, 16384));
4347 EXPECT_CALL(visitor, OnDataForStream(1, _));
4348 EXPECT_CALL(visitor, OnFrameHeader(1, 16384, DATA, 0x0));
4349 EXPECT_CALL(visitor, OnBeginDataForStream(1, 16384));
4350 EXPECT_CALL(visitor, OnDataForStream(1, _));
4351 EXPECT_CALL(visitor, OnFrameHeader(1, 16384, DATA, 0x0));
4352 EXPECT_CALL(visitor, OnBeginDataForStream(1, 16384));
4353 // No further frame data or headers are delivered.
4354
4355 const int64_t result = adapter->ProcessBytes(frames);
4356 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
4357
4358 EXPECT_TRUE(adapter->want_write());
4359
4360 // No SETTINGS ack is written.
4361 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
4362 EXPECT_CALL(
4363 visitor,
4364 OnFrameSent(GOAWAY, 0, _, 0x0,
4365 static_cast<int>(Http2ErrorCode::FLOW_CONTROL_ERROR)));
4366
4367 int send_result = adapter->Send();
4368 EXPECT_EQ(0, send_result);
4369 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
4370 }
4371
TEST(NgHttp2AdapterTest,ClientDisobeysConnectionFlowControlWithOneDataFrame)4372 TEST(NgHttp2AdapterTest, ClientDisobeysConnectionFlowControlWithOneDataFrame) {
4373 DataSavingVisitor visitor;
4374 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4375
4376 // Allow the client to send a DATA frame that exceeds the connection flow
4377 // control window.
4378 const uint32_t window_overflow_bytes = kInitialFlowControlWindowSize + 1;
4379 adapter->SubmitSettings({{MAX_FRAME_SIZE, window_overflow_bytes}});
4380
4381 const std::string initial_frames =
4382 TestFrameSequence()
4383 .ClientPreface()
4384 .Headers(1,
4385 {{":method", "POST"},
4386 {":scheme", "https"},
4387 {":authority", "example.com"},
4388 {":path", "/this/is/request/one"}},
4389 /*fin=*/false)
4390 .Serialize();
4391
4392 testing::InSequence s;
4393
4394 // Client preface (empty SETTINGS)
4395 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4396 EXPECT_CALL(visitor, OnSettingsStart());
4397 EXPECT_CALL(visitor, OnSettingsEnd());
4398
4399 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
4400 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4401 EXPECT_CALL(visitor, OnHeaderForStream).Times(4);
4402 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
4403
4404 int64_t process_result = adapter->ProcessBytes(initial_frames);
4405 EXPECT_EQ(initial_frames.size(), static_cast<size_t>(process_result));
4406
4407 EXPECT_TRUE(adapter->want_write());
4408
4409 // Outbound SETTINGS containing MAX_FRAME_SIZE.
4410 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
4411 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
4412
4413 // Ack of client's initial settings.
4414 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
4415 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
4416
4417 int send_result = adapter->Send();
4418 EXPECT_EQ(0, send_result);
4419 EXPECT_THAT(visitor.data(),
4420 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
4421 visitor.Clear();
4422
4423 // Now let the client ack the MAX_FRAME_SIZE SETTINGS and send a DATA frame to
4424 // overflow the connection-level window. The result should be a GOAWAY.
4425 const std::string overflow_frames =
4426 TestFrameSequence()
4427 .SettingsAck()
4428 .Data(1, std::string(window_overflow_bytes, 'a'))
4429 .Serialize();
4430
4431 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0x1));
4432 EXPECT_CALL(visitor, OnSettingsAck());
4433 EXPECT_CALL(visitor, OnFrameHeader(1, window_overflow_bytes, DATA, 0x0));
4434 EXPECT_CALL(visitor, OnBeginDataForStream(1, window_overflow_bytes));
4435 // No further frame data is delivered.
4436
4437 process_result = adapter->ProcessBytes(overflow_frames);
4438 EXPECT_EQ(overflow_frames.size(), static_cast<size_t>(process_result));
4439
4440 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
4441 EXPECT_CALL(
4442 visitor,
4443 OnFrameSent(GOAWAY, 0, _, 0x0,
4444 static_cast<int>(Http2ErrorCode::FLOW_CONTROL_ERROR)));
4445
4446 send_result = adapter->Send();
4447 EXPECT_EQ(0, send_result);
4448 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
4449 }
4450
TEST(NgHttp2AdapterTest,ClientDisobeysConnectionFlowControlAcrossReads)4451 TEST(NgHttp2AdapterTest, ClientDisobeysConnectionFlowControlAcrossReads) {
4452 DataSavingVisitor visitor;
4453 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4454
4455 // Allow the client to send a DATA frame that exceeds the connection flow
4456 // control window.
4457 const uint32_t window_overflow_bytes = kInitialFlowControlWindowSize + 1;
4458 adapter->SubmitSettings({{MAX_FRAME_SIZE, window_overflow_bytes}});
4459
4460 const std::string initial_frames =
4461 TestFrameSequence()
4462 .ClientPreface()
4463 .Headers(1,
4464 {{":method", "POST"},
4465 {":scheme", "https"},
4466 {":authority", "example.com"},
4467 {":path", "/this/is/request/one"}},
4468 /*fin=*/false)
4469 .Serialize();
4470
4471 testing::InSequence s;
4472
4473 // Client preface (empty SETTINGS)
4474 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4475 EXPECT_CALL(visitor, OnSettingsStart());
4476 EXPECT_CALL(visitor, OnSettingsEnd());
4477
4478 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
4479 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4480 EXPECT_CALL(visitor, OnHeaderForStream).Times(4);
4481 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
4482
4483 int64_t process_result = adapter->ProcessBytes(initial_frames);
4484 EXPECT_EQ(initial_frames.size(), static_cast<size_t>(process_result));
4485
4486 EXPECT_TRUE(adapter->want_write());
4487
4488 // Outbound SETTINGS containing MAX_FRAME_SIZE.
4489 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
4490 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
4491
4492 // Ack of client's initial settings.
4493 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
4494 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
4495
4496 int send_result = adapter->Send();
4497 EXPECT_EQ(0, send_result);
4498 EXPECT_THAT(visitor.data(),
4499 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
4500 visitor.Clear();
4501
4502 // Now let the client ack the MAX_FRAME_SIZE SETTINGS and send a DATA frame to
4503 // overflow the connection-level window. The result should be a GOAWAY, but
4504 // because the processing is split across several calls, nghttp2 instead
4505 // delivers the data payloads (which the visitor then consumes). This is a bug
4506 // in nghttp2, which should recognize the flow control error.
4507 const std::string overflow_frames =
4508 TestFrameSequence()
4509 .SettingsAck()
4510 .Data(1, std::string(window_overflow_bytes, 'a'))
4511 .Serialize();
4512
4513 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0x1));
4514 EXPECT_CALL(visitor, OnSettingsAck());
4515 EXPECT_CALL(visitor, OnFrameHeader(1, window_overflow_bytes, DATA, 0x0));
4516 EXPECT_CALL(visitor, OnBeginDataForStream(1, window_overflow_bytes));
4517 // BUG: The visitor should not have received the data.
4518 EXPECT_CALL(visitor, OnDataForStream(1, _))
4519 .WillRepeatedly(
4520 [&adapter](Http2StreamId stream_id, absl::string_view data) {
4521 adapter->MarkDataConsumedForStream(stream_id, data.size());
4522 return true;
4523 });
4524
4525 const size_t chunk_length = 16384;
4526 ASSERT_GE(overflow_frames.size(), chunk_length);
4527 absl::string_view remaining = overflow_frames;
4528 while (!remaining.empty()) {
4529 absl::string_view chunk = remaining.substr(0, chunk_length);
4530 process_result = adapter->ProcessBytes(chunk);
4531 EXPECT_EQ(chunk.length(), static_cast<size_t>(process_result));
4532
4533 remaining.remove_prefix(chunk.length());
4534 }
4535
4536 EXPECT_CALL(visitor, OnBeforeFrameSent(WINDOW_UPDATE, 0, 4, 0x0));
4537 EXPECT_CALL(visitor, OnFrameSent(WINDOW_UPDATE, 0, 4, 0x0, 0));
4538 EXPECT_CALL(visitor, OnBeforeFrameSent(WINDOW_UPDATE, 1, 4, 0x0));
4539 EXPECT_CALL(visitor, OnFrameSent(WINDOW_UPDATE, 1, 4, 0x0, 0));
4540
4541 send_result = adapter->Send();
4542 EXPECT_EQ(0, send_result);
4543 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::WINDOW_UPDATE,
4544 SpdyFrameType::WINDOW_UPDATE}));
4545 }
4546
TEST(NgHttp2AdapterTest,ClientDisobeysStreamFlowControl)4547 TEST(NgHttp2AdapterTest, ClientDisobeysStreamFlowControl) {
4548 DataSavingVisitor visitor;
4549 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4550
4551 const std::string frames = TestFrameSequence()
4552 .ClientPreface()
4553 .Headers(1,
4554 {{":method", "POST"},
4555 {":scheme", "https"},
4556 {":authority", "example.com"},
4557 {":path", "/this/is/request/one"},
4558 {"accept", "some bogus value!"}},
4559 /*fin=*/false)
4560 .Serialize();
4561 const std::string more_frames = TestFrameSequence()
4562 // 70000 bytes of data
4563 .Data(1, std::string(16384, 'a'))
4564 .Data(1, std::string(16384, 'a'))
4565 .Data(1, std::string(16384, 'a'))
4566 .Data(1, std::string(16384, 'a'))
4567 .Data(1, std::string(4464, 'a'))
4568 .Serialize();
4569
4570 testing::InSequence s;
4571 // Client preface (empty SETTINGS)
4572 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4573 EXPECT_CALL(visitor, OnSettingsStart());
4574 EXPECT_CALL(visitor, OnSettingsEnd());
4575
4576 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
4577 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4578 EXPECT_CALL(visitor, OnHeaderForStream).Times(5);
4579 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
4580
4581 int64_t result = adapter->ProcessBytes(frames);
4582 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
4583
4584 adapter->SubmitWindowUpdate(0, 20000);
4585
4586 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
4587 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
4588 EXPECT_CALL(visitor, OnBeforeFrameSent(WINDOW_UPDATE, 0, 4, 0x0));
4589 EXPECT_CALL(visitor, OnFrameSent(WINDOW_UPDATE, 0, 4, 0x0, 0));
4590
4591 int send_result = adapter->Send();
4592 EXPECT_EQ(0, send_result);
4593 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
4594 SpdyFrameType::WINDOW_UPDATE}));
4595 visitor.Clear();
4596
4597 EXPECT_CALL(visitor, OnFrameHeader(1, 16384, DATA, 0x0));
4598 EXPECT_CALL(visitor, OnBeginDataForStream(1, 16384));
4599 EXPECT_CALL(visitor, OnDataForStream(1, _));
4600 EXPECT_CALL(visitor, OnFrameHeader(1, 16384, DATA, 0x0));
4601 EXPECT_CALL(visitor, OnBeginDataForStream(1, 16384));
4602 EXPECT_CALL(visitor, OnDataForStream(1, _));
4603 EXPECT_CALL(visitor, OnFrameHeader(1, 16384, DATA, 0x0));
4604 EXPECT_CALL(visitor, OnBeginDataForStream(1, 16384));
4605 EXPECT_CALL(visitor, OnDataForStream(1, _));
4606 EXPECT_CALL(visitor, OnFrameHeader(1, 16384, DATA, 0x0));
4607 EXPECT_CALL(visitor, OnBeginDataForStream(1, 16384));
4608 EXPECT_CALL(visitor, OnDataForStream(1, _));
4609 // No further frame data or headers for stream 1 are delivered.
4610
4611 result = adapter->ProcessBytes(more_frames);
4612 EXPECT_EQ(more_frames.size(), static_cast<size_t>(result));
4613
4614 EXPECT_TRUE(adapter->want_write());
4615 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, 4, 0x0));
4616 EXPECT_CALL(
4617 visitor,
4618 OnFrameSent(RST_STREAM, 1, 4, 0x0,
4619 static_cast<int>(Http2ErrorCode::FLOW_CONTROL_ERROR)));
4620 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::FLOW_CONTROL_ERROR));
4621
4622 send_result = adapter->Send();
4623 EXPECT_EQ(0, send_result);
4624 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::RST_STREAM}));
4625 }
4626
TEST(NgHttp2AdapterTest,ServerErrorWhileHandlingHeaders)4627 TEST(NgHttp2AdapterTest, ServerErrorWhileHandlingHeaders) {
4628 DataSavingVisitor visitor;
4629 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4630
4631 const std::string frames = TestFrameSequence()
4632 .ClientPreface()
4633 .Headers(1,
4634 {{":method", "POST"},
4635 {":scheme", "https"},
4636 {":authority", "example.com"},
4637 {":path", "/this/is/request/one"},
4638 {"accept", "some bogus value!"}},
4639 /*fin=*/false)
4640 .WindowUpdate(1, 2000)
4641 .Data(1, "This is the request body.")
4642 .WindowUpdate(0, 2000)
4643 .Serialize();
4644 testing::InSequence s;
4645
4646 // Client preface (empty SETTINGS)
4647 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4648 EXPECT_CALL(visitor, OnSettingsStart());
4649 EXPECT_CALL(visitor, OnSettingsEnd());
4650
4651 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
4652 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4653 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
4654 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
4655 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
4656 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
4657 EXPECT_CALL(visitor, OnHeaderForStream(1, "accept", "some bogus value!"))
4658 .WillOnce(testing::Return(Http2VisitorInterface::HEADER_RST_STREAM));
4659 EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
4660 EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
4661 // DATA frame is not delivered to the visitor.
4662 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
4663 EXPECT_CALL(visitor, OnWindowUpdate(0, 2000));
4664
4665 const int64_t result = adapter->ProcessBytes(frames);
4666 EXPECT_EQ(frames.size(), result);
4667
4668 EXPECT_TRUE(adapter->want_write());
4669
4670 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
4671 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
4672 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, 4, 0x0));
4673 EXPECT_CALL(visitor,
4674 OnFrameSent(RST_STREAM, 1, 4, 0x0,
4675 static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
4676 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::INTERNAL_ERROR));
4677
4678 int send_result = adapter->Send();
4679 // Some bytes should have been serialized.
4680 EXPECT_EQ(0, send_result);
4681 // SETTINGS ack
4682 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
4683 SpdyFrameType::RST_STREAM}));
4684 }
4685
TEST(NgHttp2AdapterTest,ServerErrorWhileHandlingHeadersDropsFrames)4686 TEST(NgHttp2AdapterTest, ServerErrorWhileHandlingHeadersDropsFrames) {
4687 DataSavingVisitor visitor;
4688 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4689
4690 const std::string frames = TestFrameSequence()
4691 .ClientPreface()
4692 .Headers(1,
4693 {{":method", "POST"},
4694 {":scheme", "https"},
4695 {":authority", "example.com"},
4696 {":path", "/this/is/request/one"},
4697 {"accept", "some bogus value!"}},
4698 /*fin=*/false)
4699 .WindowUpdate(1, 2000)
4700 .Data(1, "This is the request body.")
4701 .Metadata(1, "This is the request metadata.")
4702 .RstStream(1, Http2ErrorCode::CANCEL)
4703 .WindowUpdate(0, 2000)
4704 .Headers(3,
4705 {{":method", "GET"},
4706 {":scheme", "https"},
4707 {":authority", "example.com"},
4708 {":path", "/this/is/request/two"}},
4709 /*fin=*/false)
4710 .Metadata(3, "This is the request metadata.",
4711 /*multiple_frames=*/true)
4712 .Serialize();
4713 testing::InSequence s;
4714
4715 // Client preface (empty SETTINGS)
4716 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4717 EXPECT_CALL(visitor, OnSettingsStart());
4718 EXPECT_CALL(visitor, OnSettingsEnd());
4719
4720 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
4721 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4722 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
4723 EXPECT_CALL(visitor, OnHeaderForStream(1, "accept", "some bogus value!"))
4724 .WillOnce(testing::Return(Http2VisitorInterface::HEADER_RST_STREAM));
4725 // For the RST_STREAM-marked stream, the control frames and METADATA frame but
4726 // not the DATA frame are delivered to the visitor.
4727 EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
4728 EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
4729 EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
4730 EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
4731 EXPECT_CALL(visitor, OnMetadataForStream(1, _));
4732 EXPECT_CALL(visitor, OnMetadataEndForStream(1));
4733 EXPECT_CALL(visitor, OnFrameHeader(1, 4, RST_STREAM, 0));
4734 EXPECT_CALL(visitor, OnRstStream(1, Http2ErrorCode::CANCEL));
4735 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::CANCEL));
4736 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
4737 EXPECT_CALL(visitor, OnWindowUpdate(0, 2000));
4738 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 4));
4739 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
4740 EXPECT_CALL(visitor, OnHeaderForStream(3, _, _)).Times(4);
4741 EXPECT_CALL(visitor, OnEndHeadersForStream(3));
4742 EXPECT_CALL(visitor, OnFrameHeader(3, _, kMetadataFrameType, 0));
4743 EXPECT_CALL(visitor, OnBeginMetadataForStream(3, _));
4744 EXPECT_CALL(visitor, OnMetadataForStream(3, "This is the re"))
4745 .WillOnce(testing::DoAll(testing::InvokeWithoutArgs([&adapter]() {
4746 adapter->SubmitRst(
4747 3, Http2ErrorCode::REFUSED_STREAM);
4748 }),
4749 testing::Return(true)));
4750 // The rest of the metadata is still delivered to the visitor.
4751 EXPECT_CALL(visitor, OnFrameHeader(3, _, kMetadataFrameType, 4));
4752 EXPECT_CALL(visitor, OnBeginMetadataForStream(3, _));
4753 EXPECT_CALL(visitor, OnMetadataForStream(3, "quest metadata."));
4754 EXPECT_CALL(visitor, OnMetadataEndForStream(3));
4755
4756 const int64_t result = adapter->ProcessBytes(frames);
4757 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
4758
4759 EXPECT_TRUE(adapter->want_write());
4760
4761 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
4762 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
4763 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, 4, 0x0));
4764 EXPECT_CALL(visitor,
4765 OnFrameSent(RST_STREAM, 1, 4, 0x0,
4766 static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
4767 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 3, 4, 0x0));
4768 EXPECT_CALL(visitor,
4769 OnFrameSent(RST_STREAM, 3, 4, 0x0,
4770 static_cast<int>(Http2ErrorCode::REFUSED_STREAM)));
4771 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::REFUSED_STREAM));
4772
4773 int send_result = adapter->Send();
4774 // Some bytes should have been serialized.
4775 EXPECT_EQ(0, send_result);
4776 EXPECT_THAT(visitor.data(),
4777 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::RST_STREAM,
4778 SpdyFrameType::RST_STREAM}));
4779 }
4780
TEST(NgHttp2AdapterTest,ServerConnectionErrorWhileHandlingHeaders)4781 TEST(NgHttp2AdapterTest, ServerConnectionErrorWhileHandlingHeaders) {
4782 DataSavingVisitor visitor;
4783 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4784
4785 const std::string frames = TestFrameSequence()
4786 .ClientPreface()
4787 .Headers(1,
4788 {{":method", "POST"},
4789 {":scheme", "https"},
4790 {":authority", "example.com"},
4791 {":path", "/this/is/request/one"},
4792 {"Accept", "uppercase, oh boy!"}},
4793 /*fin=*/false)
4794 .WindowUpdate(1, 2000)
4795 .Data(1, "This is the request body.")
4796 .WindowUpdate(0, 2000)
4797 .Serialize();
4798 testing::InSequence s;
4799
4800 // Client preface (empty SETTINGS)
4801 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4802 EXPECT_CALL(visitor, OnSettingsStart());
4803 EXPECT_CALL(visitor, OnSettingsEnd());
4804
4805 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
4806 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4807 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
4808 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
4809 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
4810 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
4811 EXPECT_CALL(visitor, OnErrorDebug);
4812 EXPECT_CALL(
4813 visitor,
4814 OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader))
4815 .WillOnce(testing::Return(false));
4816 // Translation to nghttp2 treats this error as a general parsing error.
4817 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
4818
4819 const int64_t result = adapter->ProcessBytes(frames);
4820 EXPECT_EQ(result, NGHTTP2_ERR_CALLBACK_FAILURE);
4821
4822 EXPECT_TRUE(adapter->want_write());
4823
4824 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
4825 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
4826 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, 4, 0x0));
4827 EXPECT_CALL(visitor,
4828 OnFrameSent(RST_STREAM, 1, 4, 0x0,
4829 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
4830 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
4831
4832 int send_result = adapter->Send();
4833 // Some bytes should have been serialized.
4834 EXPECT_EQ(0, send_result);
4835 // SETTINGS ack and RST_STREAM
4836 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
4837 SpdyFrameType::RST_STREAM}));
4838 }
4839
TEST(NgHttp2AdapterTest,ServerErrorAfterHandlingHeaders)4840 TEST(NgHttp2AdapterTest, ServerErrorAfterHandlingHeaders) {
4841 DataSavingVisitor visitor;
4842 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4843
4844 const std::string frames = TestFrameSequence()
4845 .ClientPreface()
4846 .Headers(1,
4847 {{":method", "POST"},
4848 {":scheme", "https"},
4849 {":authority", "example.com"},
4850 {":path", "/this/is/request/one"}},
4851 /*fin=*/false)
4852 .WindowUpdate(1, 2000)
4853 .Data(1, "This is the request body.")
4854 .WindowUpdate(0, 2000)
4855 .Serialize();
4856 testing::InSequence s;
4857
4858 // Client preface (empty SETTINGS)
4859 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4860 EXPECT_CALL(visitor, OnSettingsStart());
4861 EXPECT_CALL(visitor, OnSettingsEnd());
4862
4863 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
4864 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4865 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
4866 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
4867 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
4868 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
4869 EXPECT_CALL(visitor, OnEndHeadersForStream(1))
4870 .WillOnce(testing::Return(false));
4871 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
4872
4873 const int64_t result = adapter->ProcessBytes(frames);
4874 EXPECT_EQ(-902, result);
4875
4876 EXPECT_TRUE(adapter->want_write());
4877
4878 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
4879 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
4880
4881 int send_result = adapter->Send();
4882 // Some bytes should have been serialized.
4883 EXPECT_EQ(0, send_result);
4884 // SETTINGS ack
4885 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
4886 }
4887
4888 // Exercises the case when a visitor chooses to reject a frame based solely on
4889 // the frame header, which is a fatal error for the connection.
TEST(NgHttp2AdapterTest,ServerRejectsFrameHeader)4890 TEST(NgHttp2AdapterTest, ServerRejectsFrameHeader) {
4891 DataSavingVisitor visitor;
4892 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4893
4894 const std::string frames = TestFrameSequence()
4895 .ClientPreface()
4896 .Ping(64)
4897 .Headers(1,
4898 {{":method", "POST"},
4899 {":scheme", "https"},
4900 {":authority", "example.com"},
4901 {":path", "/this/is/request/one"}},
4902 /*fin=*/false)
4903 .WindowUpdate(1, 2000)
4904 .Data(1, "This is the request body.")
4905 .WindowUpdate(0, 2000)
4906 .Serialize();
4907 testing::InSequence s;
4908
4909 // Client preface (empty SETTINGS)
4910 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4911 EXPECT_CALL(visitor, OnSettingsStart());
4912 EXPECT_CALL(visitor, OnSettingsEnd());
4913
4914 EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0))
4915 .WillOnce(testing::Return(false));
4916 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
4917
4918 const int64_t result = adapter->ProcessBytes(frames);
4919 EXPECT_EQ(-902, result);
4920
4921 EXPECT_TRUE(adapter->want_write());
4922
4923 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
4924 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
4925
4926 int send_result = adapter->Send();
4927 // Some bytes should have been serialized.
4928 EXPECT_EQ(0, send_result);
4929 // SETTINGS ack
4930 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
4931 }
4932
TEST(NgHttp2AdapterTest,ServerRejectsBeginningOfData)4933 TEST(NgHttp2AdapterTest, ServerRejectsBeginningOfData) {
4934 DataSavingVisitor visitor;
4935 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4936
4937 const std::string frames = TestFrameSequence()
4938 .ClientPreface()
4939 .Headers(1,
4940 {{":method", "POST"},
4941 {":scheme", "https"},
4942 {":authority", "example.com"},
4943 {":path", "/this/is/request/one"}},
4944 /*fin=*/false)
4945 .Data(1, "This is the request body.")
4946 .Headers(3,
4947 {{":method", "GET"},
4948 {":scheme", "http"},
4949 {":authority", "example.com"},
4950 {":path", "/this/is/request/two"}},
4951 /*fin=*/true)
4952 .RstStream(3, Http2ErrorCode::CANCEL)
4953 .Ping(47)
4954 .Serialize();
4955 testing::InSequence s;
4956
4957 // Client preface (empty SETTINGS)
4958 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
4959 EXPECT_CALL(visitor, OnSettingsStart());
4960 EXPECT_CALL(visitor, OnSettingsEnd());
4961
4962 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
4963 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
4964 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
4965 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
4966 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
4967 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
4968 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
4969 EXPECT_CALL(visitor, OnFrameHeader(1, 25, DATA, 0));
4970 EXPECT_CALL(visitor, OnBeginDataForStream(1, 25))
4971 .WillOnce(testing::Return(false));
4972 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
4973
4974 const int64_t result = adapter->ProcessBytes(frames);
4975 EXPECT_EQ(NGHTTP2_ERR_CALLBACK_FAILURE, result);
4976
4977 EXPECT_TRUE(adapter->want_write());
4978
4979 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
4980 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
4981
4982 int send_result = adapter->Send();
4983 // Some bytes should have been serialized.
4984 EXPECT_EQ(0, send_result);
4985 // SETTINGS ack.
4986 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
4987 }
4988
TEST(NgHttp2AdapterTest,ServerRejectsStreamData)4989 TEST(NgHttp2AdapterTest, ServerRejectsStreamData) {
4990 DataSavingVisitor visitor;
4991 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
4992
4993 const std::string frames = TestFrameSequence()
4994 .ClientPreface()
4995 .Headers(1,
4996 {{":method", "POST"},
4997 {":scheme", "https"},
4998 {":authority", "example.com"},
4999 {":path", "/this/is/request/one"}},
5000 /*fin=*/false)
5001 .Data(1, "This is the request body.")
5002 .Headers(3,
5003 {{":method", "GET"},
5004 {":scheme", "http"},
5005 {":authority", "example.com"},
5006 {":path", "/this/is/request/two"}},
5007 /*fin=*/true)
5008 .RstStream(3, Http2ErrorCode::CANCEL)
5009 .Ping(47)
5010 .Serialize();
5011 testing::InSequence s;
5012
5013 // Client preface (empty SETTINGS)
5014 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5015 EXPECT_CALL(visitor, OnSettingsStart());
5016 EXPECT_CALL(visitor, OnSettingsEnd());
5017
5018 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
5019 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5020 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
5021 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5022 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5023 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
5024 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5025 EXPECT_CALL(visitor, OnFrameHeader(1, 25, DATA, 0));
5026 EXPECT_CALL(visitor, OnBeginDataForStream(1, 25));
5027 EXPECT_CALL(visitor, OnDataForStream(1, _)).WillOnce(testing::Return(false));
5028 EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
5029
5030 const int64_t result = adapter->ProcessBytes(frames);
5031 EXPECT_EQ(NGHTTP2_ERR_CALLBACK_FAILURE, result);
5032
5033 EXPECT_TRUE(adapter->want_write());
5034
5035 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
5036 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
5037
5038 int send_result = adapter->Send();
5039 // Some bytes should have been serialized.
5040 EXPECT_EQ(0, send_result);
5041 // SETTINGS ack.
5042 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
5043 }
5044
TEST(NgHttp2AdapterTest,ServerReceivesTooLargeHeader)5045 TEST(NgHttp2AdapterTest, ServerReceivesTooLargeHeader) {
5046 DataSavingVisitor visitor;
5047 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5048
5049 // nghttp2 will accept a maximum of 64kB of huffman encoded data per header
5050 // field.
5051 const std::string too_large_value = std::string(80 * 1024, 'q');
5052 const std::string frames = TestFrameSequence()
5053 .ClientPreface()
5054 .Headers(1,
5055 {{":method", "POST"},
5056 {":scheme", "https"},
5057 {":authority", "example.com"},
5058 {":path", "/this/is/request/one"},
5059 {"x-toobig", too_large_value}},
5060 /*fin=*/false)
5061 .Serialize();
5062 testing::InSequence s;
5063
5064 // Client preface (empty SETTINGS)
5065 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5066 EXPECT_CALL(visitor, OnSettingsStart());
5067 EXPECT_CALL(visitor, OnSettingsEnd());
5068
5069 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0));
5070 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5071 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
5072 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5073 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5074 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
5075 // Further header processing is skipped, as the header field is too large.
5076
5077 const int64_t result = adapter->ProcessBytes(frames);
5078 EXPECT_EQ(frames.size(), result);
5079
5080 EXPECT_TRUE(adapter->want_write());
5081
5082 // Since nghttp2 opted not to process the header, it generates a GOAWAY with
5083 // error code COMPRESSION_ERROR.
5084 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, 8, 0x0));
5085 EXPECT_CALL(visitor,
5086 OnFrameSent(GOAWAY, 0, 8, 0x0,
5087 static_cast<int>(Http2ErrorCode::COMPRESSION_ERROR)));
5088
5089 int send_result = adapter->Send();
5090 // Some bytes should have been serialized.
5091 EXPECT_EQ(0, send_result);
5092 // GOAWAY.
5093 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
5094 }
5095
TEST(NgHttp2AdapterTest,ServerReceivesInvalidAuthority)5096 TEST(NgHttp2AdapterTest, ServerReceivesInvalidAuthority) {
5097 DataSavingVisitor visitor;
5098 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5099
5100 const std::string frames = TestFrameSequence()
5101 .ClientPreface()
5102 .Headers(1,
5103 {{":method", "POST"},
5104 {":scheme", "https"},
5105 {":authority", "ex|ample.com"},
5106 {":path", "/this/is/request/one"}},
5107 /*fin=*/false)
5108 .Serialize();
5109 testing::InSequence s;
5110
5111 // Client preface (empty SETTINGS)
5112 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5113 EXPECT_CALL(visitor, OnSettingsStart());
5114 EXPECT_CALL(visitor, OnSettingsEnd());
5115
5116 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
5117 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5118 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
5119 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5120 EXPECT_CALL(
5121 visitor,
5122 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
5123 "stream: 1, name: [:authority], value: [ex|ample.com]"));
5124 EXPECT_CALL(
5125 visitor,
5126 OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
5127
5128 const int64_t result = adapter->ProcessBytes(frames);
5129 EXPECT_EQ(frames.size(), result);
5130
5131 EXPECT_TRUE(adapter->want_write());
5132
5133 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
5134 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0x0));
5135 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, 4, 0x0));
5136 EXPECT_CALL(visitor,
5137 OnFrameSent(RST_STREAM, 1, 4, 0x0,
5138 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
5139 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
5140
5141 int send_result = adapter->Send();
5142 EXPECT_EQ(0, send_result);
5143 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
5144 SpdyFrameType::RST_STREAM}));
5145 }
5146
TEST(NgHttpAdapterTest,ServerReceivesGoAway)5147 TEST(NgHttpAdapterTest, ServerReceivesGoAway) {
5148 DataSavingVisitor visitor;
5149 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5150
5151 const std::string frames = TestFrameSequence()
5152 .ClientPreface()
5153 .Headers(1,
5154 {{":method", "GET"},
5155 {":scheme", "https"},
5156 {":authority", "example.com"},
5157 {":path", "/this/is/request/one"}},
5158 /*fin=*/true)
5159 .GoAway(0, Http2ErrorCode::HTTP2_NO_ERROR, "")
5160 .Serialize();
5161 testing::InSequence s;
5162
5163 // Client preface (empty SETTINGS)
5164 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5165 EXPECT_CALL(visitor, OnSettingsStart());
5166 EXPECT_CALL(visitor, OnSettingsEnd());
5167
5168 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x5));
5169 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5170 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
5171 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5172 EXPECT_CALL(visitor, OnEndStream(1));
5173 EXPECT_CALL(visitor, OnFrameHeader(0, _, GOAWAY, 0x0));
5174 EXPECT_CALL(visitor, OnGoAway(0, Http2ErrorCode::HTTP2_NO_ERROR, ""));
5175
5176 const int64_t result = adapter->ProcessBytes(frames);
5177 EXPECT_EQ(static_cast<int64_t>(frames.size()), result);
5178
5179 // The server should still be able to send a response after receiving a GOAWAY
5180 // with a lower last-stream-ID field, as the stream was client-initiated.
5181 const int submit_result =
5182 adapter->SubmitResponse(1, ToHeaders({{":status", "200"}}),
5183 /*data_source=*/nullptr);
5184 ASSERT_EQ(0, submit_result);
5185
5186 EXPECT_TRUE(adapter->want_write());
5187
5188 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
5189 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0x0));
5190 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
5191 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
5192 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
5193
5194 int send_result = adapter->Send();
5195 EXPECT_EQ(0, send_result);
5196 EXPECT_THAT(visitor.data(),
5197 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
5198 }
5199
TEST(NgHttp2AdapterTest,ServerSubmitResponse)5200 TEST(NgHttp2AdapterTest, ServerSubmitResponse) {
5201 DataSavingVisitor visitor;
5202 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5203 EXPECT_FALSE(adapter->want_write());
5204
5205 const std::string frames = TestFrameSequence()
5206 .ClientPreface()
5207 .Headers(1,
5208 {{":method", "GET"},
5209 {":scheme", "https"},
5210 {":authority", "example.com"},
5211 {":path", "/this/is/request/one"}},
5212 /*fin=*/true)
5213 .Serialize();
5214 testing::InSequence s;
5215
5216 const char* kSentinel1 = "arbitrary pointer 1";
5217
5218 // Client preface (empty SETTINGS)
5219 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5220 EXPECT_CALL(visitor, OnSettingsStart());
5221 EXPECT_CALL(visitor, OnSettingsEnd());
5222 // Stream 1
5223 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
5224 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5225 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
5226 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5227 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5228 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
5229 EXPECT_CALL(visitor, OnEndHeadersForStream(1))
5230 .WillOnce(testing::InvokeWithoutArgs([&adapter, kSentinel1]() {
5231 adapter->SetStreamUserData(1, const_cast<char*>(kSentinel1));
5232 return true;
5233 }));
5234 EXPECT_CALL(visitor, OnEndStream(1));
5235
5236 const int64_t result = adapter->ProcessBytes(frames);
5237 EXPECT_EQ(frames.size(), result);
5238
5239 EXPECT_EQ(1, adapter->GetHighestReceivedStreamId());
5240
5241 // Server will want to send a SETTINGS ack.
5242 EXPECT_TRUE(adapter->want_write());
5243
5244 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
5245 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
5246
5247 int send_result = adapter->Send();
5248 EXPECT_EQ(0, send_result);
5249 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
5250 visitor.Clear();
5251
5252 EXPECT_EQ(0, adapter->GetHpackEncoderDynamicTableSize());
5253
5254 EXPECT_FALSE(adapter->want_write());
5255 const absl::string_view kBody = "This is an example response body.";
5256 // A data fin is not sent so that the stream remains open, and the flow
5257 // control state can be verified.
5258 auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
5259 body1->AppendPayload(kBody);
5260 int submit_result = adapter->SubmitResponse(
5261 1,
5262 ToHeaders({{":status", "404"},
5263 {"x-comment", "I have no idea what you're talking about."}}),
5264 std::move(body1));
5265 EXPECT_EQ(submit_result, 0);
5266 EXPECT_TRUE(adapter->want_write());
5267
5268 // Stream user data should have been set successfully after receiving headers.
5269 EXPECT_EQ(kSentinel1, adapter->GetStreamUserData(1));
5270 adapter->SetStreamUserData(1, nullptr);
5271 EXPECT_EQ(nullptr, adapter->GetStreamUserData(1));
5272
5273 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
5274 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
5275 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
5276
5277 send_result = adapter->Send();
5278 EXPECT_EQ(0, send_result);
5279
5280 EXPECT_THAT(visitor.data(),
5281 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
5282 EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
5283 EXPECT_FALSE(adapter->want_write());
5284
5285 // Some data was sent, so the remaining send window size should be less than
5286 // the default.
5287 EXPECT_LT(adapter->GetStreamSendWindowSize(1), kInitialFlowControlWindowSize);
5288 EXPECT_GT(adapter->GetStreamSendWindowSize(1), 0);
5289 // Send window for a nonexistent stream is not available.
5290 EXPECT_EQ(adapter->GetStreamSendWindowSize(3), -1);
5291
5292 EXPECT_GT(adapter->GetHpackEncoderDynamicTableSize(), 0);
5293 }
5294
TEST(NgHttp2AdapterTest,ServerSubmitResponseWithResetFromClient)5295 TEST(NgHttp2AdapterTest, ServerSubmitResponseWithResetFromClient) {
5296 DataSavingVisitor visitor;
5297 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5298 EXPECT_FALSE(adapter->want_write());
5299
5300 const std::string frames = TestFrameSequence()
5301 .ClientPreface()
5302 .Headers(1,
5303 {{":method", "GET"},
5304 {":scheme", "https"},
5305 {":authority", "example.com"},
5306 {":path", "/this/is/request/one"}},
5307 /*fin=*/true)
5308 .Serialize();
5309 testing::InSequence s;
5310
5311 // Client preface (empty SETTINGS)
5312 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5313 EXPECT_CALL(visitor, OnSettingsStart());
5314 EXPECT_CALL(visitor, OnSettingsEnd());
5315 // Stream 1
5316 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
5317 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5318 EXPECT_CALL(visitor, OnHeaderForStream).Times(4);
5319 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5320 EXPECT_CALL(visitor, OnEndStream(1));
5321
5322 const int64_t result = adapter->ProcessBytes(frames);
5323 EXPECT_EQ(frames.size(), result);
5324
5325 EXPECT_EQ(1, adapter->GetHighestReceivedStreamId());
5326
5327 // Server will want to send a SETTINGS ack.
5328 EXPECT_TRUE(adapter->want_write());
5329
5330 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
5331 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
5332
5333 int send_result = adapter->Send();
5334 EXPECT_EQ(0, send_result);
5335 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
5336 visitor.Clear();
5337
5338 EXPECT_FALSE(adapter->want_write());
5339 const absl::string_view kBody = "This is an example response body.";
5340 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
5341 body1->AppendPayload(kBody);
5342 int submit_result = adapter->SubmitResponse(
5343 1,
5344 ToHeaders({{":status", "404"},
5345 {"x-comment", "I have no idea what you're talking about."}}),
5346 std::move(body1));
5347 EXPECT_EQ(submit_result, 0);
5348 EXPECT_TRUE(adapter->want_write());
5349
5350 // Client resets the stream before the server can send the response.
5351 const std::string reset =
5352 TestFrameSequence().RstStream(1, Http2ErrorCode::CANCEL).Serialize();
5353 EXPECT_CALL(visitor, OnFrameHeader(1, 4, RST_STREAM, 0));
5354 EXPECT_CALL(visitor, OnRstStream(1, Http2ErrorCode::CANCEL));
5355 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::CANCEL));
5356 const int64_t reset_result = adapter->ProcessBytes(reset);
5357 EXPECT_EQ(reset.size(), static_cast<size_t>(reset_result));
5358
5359 // Outbound HEADERS and DATA are dropped.
5360 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, _)).Times(0);
5361 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, _, _)).Times(0);
5362 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, _, _)).Times(0);
5363
5364 send_result = adapter->Send();
5365 EXPECT_EQ(0, send_result);
5366
5367 EXPECT_THAT(visitor.data(), testing::IsEmpty());
5368 }
5369
5370 // Should also test: client attempts shutdown, server attempts shutdown after an
5371 // explicit GOAWAY.
TEST(NgHttp2AdapterTest,ServerSendsShutdown)5372 TEST(NgHttp2AdapterTest, ServerSendsShutdown) {
5373 DataSavingVisitor visitor;
5374 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5375
5376 const std::string frames = TestFrameSequence()
5377 .ClientPreface()
5378 .Headers(1,
5379 {{":method", "POST"},
5380 {":scheme", "https"},
5381 {":authority", "example.com"},
5382 {":path", "/this/is/request/one"}},
5383 /*fin=*/false)
5384 .Serialize();
5385 testing::InSequence s;
5386
5387 // Client preface (empty SETTINGS)
5388 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5389 EXPECT_CALL(visitor, OnSettingsStart());
5390 EXPECT_CALL(visitor, OnSettingsEnd());
5391
5392 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
5393 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5394 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
5395 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5396 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5397 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
5398 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5399
5400 const int64_t result = adapter->ProcessBytes(frames);
5401 EXPECT_EQ(frames.size(), result);
5402
5403 adapter->SubmitShutdownNotice();
5404
5405 EXPECT_TRUE(adapter->want_write());
5406
5407 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
5408 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
5409 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
5410 EXPECT_CALL(visitor, OnFrameSent(GOAWAY, 0, _, 0x0, 0));
5411
5412 int send_result = adapter->Send();
5413 EXPECT_EQ(0, send_result);
5414 EXPECT_THAT(visitor.data(),
5415 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::GOAWAY}));
5416 }
5417
TEST(NgHttp2AdapterTest,ServerSendsTrailers)5418 TEST(NgHttp2AdapterTest, ServerSendsTrailers) {
5419 DataSavingVisitor visitor;
5420 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5421 EXPECT_FALSE(adapter->want_write());
5422
5423 const std::string frames = TestFrameSequence()
5424 .ClientPreface()
5425 .Headers(1,
5426 {{":method", "GET"},
5427 {":scheme", "https"},
5428 {":authority", "example.com"},
5429 {":path", "/this/is/request/one"}},
5430 /*fin=*/true)
5431 .Serialize();
5432 testing::InSequence s;
5433
5434 // Client preface (empty SETTINGS)
5435 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5436 EXPECT_CALL(visitor, OnSettingsStart());
5437 EXPECT_CALL(visitor, OnSettingsEnd());
5438 // Stream 1
5439 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
5440 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5441 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
5442 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5443 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5444 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
5445 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5446 EXPECT_CALL(visitor, OnEndStream(1));
5447
5448 const int64_t result = adapter->ProcessBytes(frames);
5449 EXPECT_EQ(frames.size(), result);
5450
5451 // Server will want to send a SETTINGS ack.
5452 EXPECT_TRUE(adapter->want_write());
5453
5454 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
5455 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
5456
5457 int send_result = adapter->Send();
5458 EXPECT_EQ(0, send_result);
5459 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
5460 visitor.Clear();
5461
5462 EXPECT_FALSE(adapter->want_write());
5463 const absl::string_view kBody = "This is an example response body.";
5464
5465 // The body source must indicate that the end of the body is not the end of
5466 // the stream.
5467 auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
5468 body1->AppendPayload(kBody);
5469 body1->EndData();
5470 int submit_result = adapter->SubmitResponse(
5471 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
5472 std::move(body1));
5473 EXPECT_EQ(submit_result, 0);
5474 EXPECT_TRUE(adapter->want_write());
5475
5476 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
5477 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
5478 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
5479
5480 send_result = adapter->Send();
5481 EXPECT_EQ(0, send_result);
5482 EXPECT_THAT(visitor.data(),
5483 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
5484 EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
5485 visitor.Clear();
5486 EXPECT_FALSE(adapter->want_write());
5487
5488 // The body source has been exhausted by the call to Send() above.
5489 int trailer_result = adapter->SubmitTrailer(
5490 1, ToHeaders({{"final-status", "a-ok"},
5491 {"x-comment", "trailers sure are cool"}}));
5492 ASSERT_EQ(trailer_result, 0);
5493 EXPECT_TRUE(adapter->want_write());
5494
5495 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
5496 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
5497 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
5498
5499 send_result = adapter->Send();
5500 EXPECT_EQ(0, send_result);
5501 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
5502 }
5503
TEST(NgHttp2AdapterTest,ClientSendsContinuation)5504 TEST(NgHttp2AdapterTest, ClientSendsContinuation) {
5505 DataSavingVisitor visitor;
5506 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5507 EXPECT_FALSE(adapter->want_write());
5508
5509 const std::string frames = TestFrameSequence()
5510 .ClientPreface()
5511 .Headers(1,
5512 {{":method", "GET"},
5513 {":scheme", "https"},
5514 {":authority", "example.com"},
5515 {":path", "/this/is/request/one"}},
5516 /*fin=*/true,
5517 /*add_continuation=*/true)
5518 .Serialize();
5519 testing::InSequence s;
5520
5521 // Client preface (empty SETTINGS)
5522 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5523 EXPECT_CALL(visitor, OnSettingsStart());
5524 EXPECT_CALL(visitor, OnSettingsEnd());
5525 // Stream 1
5526 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 1));
5527 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5528 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
5529 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5530 EXPECT_CALL(visitor, OnFrameHeader(1, _, CONTINUATION, 4));
5531 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5532 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
5533 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5534 EXPECT_CALL(visitor, OnEndStream(1));
5535
5536 const int64_t result = adapter->ProcessBytes(frames);
5537 EXPECT_EQ(frames.size(), result);
5538 }
5539
TEST(NgHttp2AdapterTest,ClientSendsMetadataWithContinuation)5540 TEST(NgHttp2AdapterTest, ClientSendsMetadataWithContinuation) {
5541 DataSavingVisitor visitor;
5542 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5543 EXPECT_FALSE(adapter->want_write());
5544
5545 const std::string frames =
5546 TestFrameSequence()
5547 .ClientPreface()
5548 .Metadata(0, "Example connection metadata in multiple frames", true)
5549 .Headers(1,
5550 {{":method", "GET"},
5551 {":scheme", "https"},
5552 {":authority", "example.com"},
5553 {":path", "/this/is/request/one"}},
5554 /*fin=*/false,
5555 /*add_continuation=*/true)
5556 .Metadata(1,
5557 "Some stream metadata that's also sent in multiple frames",
5558 true)
5559 .Serialize();
5560 testing::InSequence s;
5561
5562 // Client preface (empty SETTINGS)
5563 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5564 EXPECT_CALL(visitor, OnSettingsStart());
5565 EXPECT_CALL(visitor, OnSettingsEnd());
5566 // Metadata on stream 0
5567 EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 0));
5568 EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
5569 EXPECT_CALL(visitor, OnMetadataForStream(0, _));
5570 EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
5571 EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
5572 EXPECT_CALL(visitor, OnMetadataForStream(0, _));
5573 EXPECT_CALL(visitor, OnMetadataEndForStream(0));
5574
5575 // Stream 1
5576 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0));
5577 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5578 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
5579 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5580 EXPECT_CALL(visitor, OnFrameHeader(1, _, CONTINUATION, 4));
5581 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5582 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
5583 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5584 // Metadata on stream 1
5585 EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 0));
5586 EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
5587 EXPECT_CALL(visitor, OnMetadataForStream(1, _));
5588 EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
5589 EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
5590 EXPECT_CALL(visitor, OnMetadataForStream(1, _));
5591 EXPECT_CALL(visitor, OnMetadataEndForStream(1));
5592
5593 const int64_t result = adapter->ProcessBytes(frames);
5594 EXPECT_EQ(frames.size(), result);
5595 EXPECT_EQ("Example connection metadata in multiple frames",
5596 absl::StrJoin(visitor.GetMetadata(0), ""));
5597 EXPECT_EQ("Some stream metadata that's also sent in multiple frames",
5598 absl::StrJoin(visitor.GetMetadata(1), ""));
5599 }
5600
TEST(NgHttp2AdapterTest,RepeatedHeaderNames)5601 TEST(NgHttp2AdapterTest, RepeatedHeaderNames) {
5602 DataSavingVisitor visitor;
5603 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5604 EXPECT_FALSE(adapter->want_write());
5605
5606 const std::string frames = TestFrameSequence()
5607 .ClientPreface()
5608 .Headers(1,
5609 {{":method", "GET"},
5610 {":scheme", "https"},
5611 {":authority", "example.com"},
5612 {":path", "/this/is/request/one"},
5613 {"accept", "text/plain"},
5614 {"accept", "text/html"}},
5615 /*fin=*/true)
5616 .Serialize();
5617
5618 testing::InSequence s;
5619
5620 // Client preface (empty SETTINGS)
5621 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5622 EXPECT_CALL(visitor, OnSettingsStart());
5623 EXPECT_CALL(visitor, OnSettingsEnd());
5624 // Stream 1
5625 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
5626 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5627 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
5628 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5629 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5630 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
5631 EXPECT_CALL(visitor, OnHeaderForStream(1, "accept", "text/plain"));
5632 EXPECT_CALL(visitor, OnHeaderForStream(1, "accept", "text/html"));
5633 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5634 EXPECT_CALL(visitor, OnEndStream(1));
5635
5636 int64_t result = adapter->ProcessBytes(frames);
5637 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
5638
5639 const std::vector<Header> headers1 = ToHeaders(
5640 {{":status", "200"}, {"content-length", "10"}, {"content-length", "10"}});
5641 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
5642 body1->AppendPayload("perfection");
5643 body1->EndData();
5644
5645 int submit_result = adapter->SubmitResponse(1, headers1, std::move(body1));
5646 ASSERT_EQ(0, submit_result);
5647
5648 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
5649 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
5650 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
5651 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
5652 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, 10, 0x1, 0));
5653 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
5654
5655 int send_result = adapter->Send();
5656 EXPECT_EQ(0, send_result);
5657 EXPECT_THAT(visitor.data(),
5658 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS,
5659 SpdyFrameType::DATA}));
5660 }
5661
TEST(NgHttp2AdapterTest,ServerRespondsToRequestWithTrailers)5662 TEST(NgHttp2AdapterTest, ServerRespondsToRequestWithTrailers) {
5663 DataSavingVisitor visitor;
5664 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5665 EXPECT_FALSE(adapter->want_write());
5666
5667 const std::string frames =
5668 TestFrameSequence()
5669 .ClientPreface()
5670 .Headers(1, {{":method", "GET"},
5671 {":scheme", "https"},
5672 {":authority", "example.com"},
5673 {":path", "/this/is/request/one"}})
5674 .Data(1, "Example data, woohoo.")
5675 .Serialize();
5676
5677 testing::InSequence s;
5678
5679 // Client preface (empty SETTINGS)
5680 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5681 EXPECT_CALL(visitor, OnSettingsStart());
5682 EXPECT_CALL(visitor, OnSettingsEnd());
5683 // Stream 1
5684 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
5685 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5686 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
5687 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5688 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5689 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
5690 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5691 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0));
5692 EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
5693 EXPECT_CALL(visitor, OnDataForStream(1, _));
5694
5695 int64_t result = adapter->ProcessBytes(frames);
5696 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
5697
5698 const std::vector<Header> headers1 = ToHeaders({{":status", "200"}});
5699 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
5700 TestDataFrameSource* body1_ptr = body1.get();
5701
5702 int submit_result = adapter->SubmitResponse(1, headers1, std::move(body1));
5703 ASSERT_EQ(0, submit_result);
5704
5705 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
5706 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
5707 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
5708 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
5709
5710 int send_result = adapter->Send();
5711 EXPECT_EQ(0, send_result);
5712 EXPECT_THAT(visitor.data(),
5713 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
5714 visitor.Clear();
5715
5716 const std::string more_frames =
5717 TestFrameSequence()
5718 .Headers(1, {{"extra-info", "Trailers are weird but good?"}},
5719 /*fin=*/true)
5720 .Serialize();
5721
5722 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
5723 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5724 EXPECT_CALL(visitor, OnHeaderForStream(1, "extra-info",
5725 "Trailers are weird but good?"));
5726 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5727 EXPECT_CALL(visitor, OnEndStream(1));
5728
5729 result = adapter->ProcessBytes(more_frames);
5730 EXPECT_EQ(more_frames.size(), static_cast<size_t>(result));
5731
5732 body1_ptr->EndData();
5733 EXPECT_EQ(true, adapter->ResumeStream(1));
5734
5735 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, 0, 0x1, 0));
5736 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
5737
5738 send_result = adapter->Send();
5739 EXPECT_EQ(0, send_result);
5740 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::DATA}));
5741 }
5742
TEST(NgHttp2AdapterTest,ServerSubmitsResponseWithDataSourceError)5743 TEST(NgHttp2AdapterTest, ServerSubmitsResponseWithDataSourceError) {
5744 DataSavingVisitor visitor;
5745 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5746 EXPECT_FALSE(adapter->want_write());
5747
5748 const std::string frames = TestFrameSequence()
5749 .ClientPreface()
5750 .Headers(1,
5751 {{":method", "GET"},
5752 {":scheme", "https"},
5753 {":authority", "example.com"},
5754 {":path", "/this/is/request/one"}},
5755 /*fin=*/true)
5756 .Serialize();
5757 testing::InSequence s;
5758
5759 // Client preface (empty SETTINGS)
5760 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5761 EXPECT_CALL(visitor, OnSettingsStart());
5762 EXPECT_CALL(visitor, OnSettingsEnd());
5763 // Stream 1
5764 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
5765 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5766 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
5767 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5768 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5769 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
5770 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5771 EXPECT_CALL(visitor, OnEndStream(1));
5772
5773 const int64_t result = adapter->ProcessBytes(frames);
5774 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
5775
5776 auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
5777 body1->SimulateError();
5778 int submit_result = adapter->SubmitResponse(
5779 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
5780 std::move(body1));
5781 EXPECT_EQ(submit_result, 0);
5782 EXPECT_TRUE(adapter->want_write());
5783
5784 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
5785 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
5786 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
5787 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
5788 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
5789 EXPECT_CALL(visitor, OnFrameSent(RST_STREAM, 1, _, 0x0, 2));
5790 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::INTERNAL_ERROR));
5791
5792 int send_result = adapter->Send();
5793 EXPECT_EQ(0, send_result);
5794 EXPECT_THAT(visitor.data(),
5795 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS,
5796 SpdyFrameType::RST_STREAM}));
5797 visitor.Clear();
5798 EXPECT_FALSE(adapter->want_write());
5799
5800 int trailer_result =
5801 adapter->SubmitTrailer(1, ToHeaders({{":final-status", "a-ok"}}));
5802 // The library does not object to the user queuing trailers, even through the
5803 // stream has already been closed.
5804 EXPECT_EQ(trailer_result, 0);
5805 }
5806
TEST(NgHttp2AdapterTest,CompleteRequestWithServerResponse)5807 TEST(NgHttp2AdapterTest, CompleteRequestWithServerResponse) {
5808 DataSavingVisitor visitor;
5809 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5810 EXPECT_FALSE(adapter->want_write());
5811
5812 const std::string frames =
5813 TestFrameSequence()
5814 .ClientPreface()
5815 .Headers(1,
5816 {{":method", "GET"},
5817 {":scheme", "https"},
5818 {":authority", "example.com"},
5819 {":path", "/this/is/request/one"}},
5820 /*fin=*/false)
5821 .Data(1, "This is the response body.", /*fin=*/true)
5822 .Serialize();
5823 testing::InSequence s;
5824
5825 // Client preface (empty SETTINGS)
5826 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5827 EXPECT_CALL(visitor, OnSettingsStart());
5828 EXPECT_CALL(visitor, OnSettingsEnd());
5829 // Stream 1
5830 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
5831 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5832 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
5833 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5834 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 1));
5835 EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
5836 EXPECT_CALL(visitor, OnDataForStream(1, _));
5837 EXPECT_CALL(visitor, OnEndStream(1));
5838
5839 const int64_t result = adapter->ProcessBytes(frames);
5840 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
5841
5842 int submit_result =
5843 adapter->SubmitResponse(1, ToHeaders({{":status", "200"}}), nullptr);
5844 EXPECT_EQ(submit_result, 0);
5845 EXPECT_TRUE(adapter->want_write());
5846
5847 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
5848 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
5849 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
5850 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
5851 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
5852
5853 int send_result = adapter->Send();
5854 EXPECT_EQ(0, send_result);
5855 EXPECT_THAT(visitor.data(),
5856 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
5857 EXPECT_FALSE(adapter->want_write());
5858 }
5859
TEST(NgHttp2AdapterTest,IncompleteRequestWithServerResponse)5860 TEST(NgHttp2AdapterTest, IncompleteRequestWithServerResponse) {
5861 DataSavingVisitor visitor;
5862 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5863 EXPECT_FALSE(adapter->want_write());
5864
5865 const std::string frames = TestFrameSequence()
5866 .ClientPreface()
5867 .Headers(1,
5868 {{":method", "GET"},
5869 {":scheme", "https"},
5870 {":authority", "example.com"},
5871 {":path", "/this/is/request/one"}},
5872 /*fin=*/false)
5873 .Serialize();
5874 testing::InSequence s;
5875
5876 // Client preface (empty SETTINGS)
5877 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5878 EXPECT_CALL(visitor, OnSettingsStart());
5879 EXPECT_CALL(visitor, OnSettingsEnd());
5880 // Stream 1
5881 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
5882 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5883 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
5884 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
5885
5886 const int64_t result = adapter->ProcessBytes(frames);
5887 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
5888
5889 int submit_result =
5890 adapter->SubmitResponse(1, ToHeaders({{":status", "200"}}), nullptr);
5891 EXPECT_EQ(submit_result, 0);
5892 EXPECT_TRUE(adapter->want_write());
5893
5894 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
5895 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
5896 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
5897 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
5898 // BUG: Should send RST_STREAM NO_ERROR as well, but nghttp2 does not.
5899
5900 int send_result = adapter->Send();
5901 EXPECT_EQ(0, send_result);
5902 EXPECT_THAT(visitor.data(),
5903 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
5904 EXPECT_FALSE(adapter->want_write());
5905 }
5906
TEST(NgHttp2AdapterTest,ServerHandlesMultipleContentLength)5907 TEST(NgHttp2AdapterTest, ServerHandlesMultipleContentLength) {
5908 DataSavingVisitor visitor;
5909 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5910 EXPECT_FALSE(adapter->want_write());
5911
5912 const std::string frames = TestFrameSequence()
5913 .ClientPreface()
5914 .Headers(1,
5915 {{":method", "POST"},
5916 {":scheme", "https"},
5917 {":authority", "example.com"},
5918 {":path", "/1"},
5919 {"content-length", "7"},
5920 {"content-length", "7"}},
5921 /*fin=*/false)
5922 .Headers(3,
5923 {{":method", "POST"},
5924 {":scheme", "https"},
5925 {":authority", "example.com"},
5926 {":path", "/3"},
5927 {"content-length", "11"},
5928 {"content-length", "13"}},
5929 /*fin=*/false)
5930 .Serialize();
5931 testing::InSequence s;
5932
5933 // Client preface (empty SETTINGS)
5934 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5935 EXPECT_CALL(visitor, OnSettingsStart());
5936 EXPECT_CALL(visitor, OnSettingsEnd());
5937 // Stream 1
5938 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
5939 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5940 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
5941 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5942 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5943 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/1"));
5944 EXPECT_CALL(visitor, OnHeaderForStream(1, "content-length", "7"));
5945 // nghttp2 does not like duplicate Content-Length headers.
5946 EXPECT_CALL(
5947 visitor,
5948 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
5949 "stream: 1, name: [content-length], value: [7]"));
5950 EXPECT_CALL(
5951 visitor,
5952 OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
5953 // Stream 3
5954 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 4));
5955 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
5956 EXPECT_CALL(visitor, OnHeaderForStream(3, ":method", "POST"));
5957 EXPECT_CALL(visitor, OnHeaderForStream(3, ":scheme", "https"));
5958 EXPECT_CALL(visitor, OnHeaderForStream(3, ":authority", "example.com"));
5959 EXPECT_CALL(visitor, OnHeaderForStream(3, ":path", "/3"));
5960 EXPECT_CALL(visitor, OnHeaderForStream(3, "content-length", "11"));
5961 EXPECT_CALL(
5962 visitor,
5963 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
5964 "stream: 3, name: [content-length], value: [13]"));
5965 EXPECT_CALL(
5966 visitor,
5967 OnInvalidFrame(3, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
5968
5969 const int64_t result = adapter->ProcessBytes(frames);
5970 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
5971 }
5972
TEST(NgHttp2AdapterTest,ServerSendsInvalidTrailers)5973 TEST(NgHttp2AdapterTest, ServerSendsInvalidTrailers) {
5974 DataSavingVisitor visitor;
5975 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
5976 EXPECT_FALSE(adapter->want_write());
5977
5978 const std::string frames = TestFrameSequence()
5979 .ClientPreface()
5980 .Headers(1,
5981 {{":method", "GET"},
5982 {":scheme", "https"},
5983 {":authority", "example.com"},
5984 {":path", "/this/is/request/one"}},
5985 /*fin=*/true)
5986 .Serialize();
5987 testing::InSequence s;
5988
5989 // Client preface (empty SETTINGS)
5990 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
5991 EXPECT_CALL(visitor, OnSettingsStart());
5992 EXPECT_CALL(visitor, OnSettingsEnd());
5993 // Stream 1
5994 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
5995 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
5996 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
5997 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
5998 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
5999 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
6000 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
6001 EXPECT_CALL(visitor, OnEndStream(1));
6002
6003 const int64_t result = adapter->ProcessBytes(frames);
6004 EXPECT_EQ(frames.size(), result);
6005
6006 const absl::string_view kBody = "This is an example response body.";
6007
6008 // The body source must indicate that the end of the body is not the end of
6009 // the stream.
6010 auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
6011 body1->AppendPayload(kBody);
6012 body1->EndData();
6013 int submit_result = adapter->SubmitResponse(
6014 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
6015 std::move(body1));
6016 EXPECT_EQ(submit_result, 0);
6017 EXPECT_TRUE(adapter->want_write());
6018
6019 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
6020 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
6021 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
6022 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
6023 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
6024
6025 int send_result = adapter->Send();
6026 EXPECT_EQ(0, send_result);
6027 EXPECT_THAT(visitor.data(),
6028 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS,
6029 SpdyFrameType::DATA}));
6030 EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
6031 visitor.Clear();
6032 EXPECT_FALSE(adapter->want_write());
6033
6034 // The body source has been exhausted by the call to Send() above.
6035 int trailer_result =
6036 adapter->SubmitTrailer(1, ToHeaders({{":final-status", "a-ok"}}));
6037 ASSERT_EQ(trailer_result, 0);
6038 EXPECT_TRUE(adapter->want_write());
6039
6040 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
6041 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
6042 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
6043
6044 send_result = adapter->Send();
6045 EXPECT_EQ(0, send_result);
6046 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
6047 }
6048
TEST(NgHttp2AdapterTest,ServerDropsNewStreamBelowWatermark)6049 TEST(NgHttp2AdapterTest, ServerDropsNewStreamBelowWatermark) {
6050 DataSavingVisitor visitor;
6051 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6052
6053 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
6054
6055 const std::string frames = TestFrameSequence()
6056 .ClientPreface()
6057 .Headers(3,
6058 {{":method", "POST"},
6059 {":scheme", "https"},
6060 {":authority", "example.com"},
6061 {":path", "/this/is/request/one"}},
6062 /*fin=*/false)
6063 .Data(3, "This is the request body.")
6064 .Headers(1,
6065 {{":method", "GET"},
6066 {":scheme", "http"},
6067 {":authority", "example.com"},
6068 {":path", "/this/is/request/two"}},
6069 /*fin=*/true)
6070 .Serialize();
6071 testing::InSequence s;
6072
6073 // Client preface (empty SETTINGS)
6074 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6075 EXPECT_CALL(visitor, OnSettingsStart());
6076 EXPECT_CALL(visitor, OnSettingsEnd());
6077
6078 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 4));
6079 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
6080 EXPECT_CALL(visitor, OnHeaderForStream(3, ":method", "POST"));
6081 EXPECT_CALL(visitor, OnHeaderForStream(3, ":scheme", "https"));
6082 EXPECT_CALL(visitor, OnHeaderForStream(3, ":authority", "example.com"));
6083 EXPECT_CALL(visitor, OnHeaderForStream(3, ":path", "/this/is/request/one"));
6084 EXPECT_CALL(visitor, OnEndHeadersForStream(3));
6085 EXPECT_CALL(visitor, OnFrameHeader(3, 25, DATA, 0));
6086 EXPECT_CALL(visitor, OnBeginDataForStream(3, 25));
6087 EXPECT_CALL(visitor, OnDataForStream(3, "This is the request body."));
6088
6089 // It looks like nghttp2 delivers the under-watermark frame header but
6090 // otherwise silently drops the rest of the frame without error.
6091 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
6092 EXPECT_CALL(visitor, OnInvalidFrame).Times(0);
6093 EXPECT_CALL(visitor, OnConnectionError).Times(0);
6094
6095 const int64_t result = adapter->ProcessBytes(frames);
6096 EXPECT_EQ(frames.size(), result);
6097
6098 EXPECT_EQ(3, adapter->GetHighestReceivedStreamId());
6099
6100 EXPECT_TRUE(adapter->want_write());
6101
6102 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
6103 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
6104
6105 int send_result = adapter->Send();
6106 // Some bytes should have been serialized.
6107 EXPECT_EQ(0, send_result);
6108 // SETTINGS ack
6109 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
6110 }
6111
TEST(NgHttp2AdapterInteractionTest,ClientServerInteractionRepeatedHeaderNames)6112 TEST(NgHttp2AdapterInteractionTest,
6113 ClientServerInteractionRepeatedHeaderNames) {
6114 DataSavingVisitor client_visitor;
6115 auto client_adapter = NgHttp2Adapter::CreateClientAdapter(client_visitor);
6116
6117 client_adapter->SubmitSettings({});
6118
6119 const std::vector<Header> headers1 =
6120 ToHeaders({{":method", "GET"},
6121 {":scheme", "http"},
6122 {":authority", "example.com"},
6123 {":path", "/this/is/request/one"},
6124 {"accept", "text/plain"},
6125 {"accept", "text/html"}});
6126
6127 const int32_t stream_id1 =
6128 client_adapter->SubmitRequest(headers1, nullptr, nullptr);
6129 ASSERT_GT(stream_id1, 0);
6130
6131 EXPECT_CALL(client_visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
6132 EXPECT_CALL(client_visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
6133 EXPECT_CALL(client_visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
6134 EXPECT_CALL(client_visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
6135 int send_result = client_adapter->Send();
6136 EXPECT_EQ(0, send_result);
6137
6138 DataSavingVisitor server_visitor;
6139 auto server_adapter = NgHttp2Adapter::CreateServerAdapter(server_visitor);
6140
6141 testing::InSequence s;
6142
6143 // Client preface (empty SETTINGS)
6144 EXPECT_CALL(server_visitor, OnFrameHeader(0, _, SETTINGS, 0));
6145 EXPECT_CALL(server_visitor, OnSettingsStart());
6146 EXPECT_CALL(server_visitor, OnSetting(_)).Times(testing::AnyNumber());
6147 EXPECT_CALL(server_visitor, OnSettingsEnd());
6148 // Stream 1
6149 EXPECT_CALL(server_visitor, OnFrameHeader(1, _, HEADERS, 5));
6150 EXPECT_CALL(server_visitor, OnBeginHeadersForStream(1));
6151 EXPECT_CALL(server_visitor, OnHeaderForStream(1, ":method", "GET"));
6152 EXPECT_CALL(server_visitor, OnHeaderForStream(1, ":scheme", "http"));
6153 EXPECT_CALL(server_visitor,
6154 OnHeaderForStream(1, ":authority", "example.com"));
6155 EXPECT_CALL(server_visitor,
6156 OnHeaderForStream(1, ":path", "/this/is/request/one"));
6157 EXPECT_CALL(server_visitor, OnHeaderForStream(1, "accept", "text/plain"));
6158 EXPECT_CALL(server_visitor, OnHeaderForStream(1, "accept", "text/html"));
6159 EXPECT_CALL(server_visitor, OnEndHeadersForStream(1));
6160 EXPECT_CALL(server_visitor, OnEndStream(1));
6161
6162 int64_t result = server_adapter->ProcessBytes(client_visitor.data());
6163 EXPECT_EQ(client_visitor.data().size(), static_cast<size_t>(result));
6164 }
6165
TEST(NgHttp2AdapterInteractionTest,ClientServerInteractionWithCookies)6166 TEST(NgHttp2AdapterInteractionTest, ClientServerInteractionWithCookies) {
6167 DataSavingVisitor client_visitor;
6168 auto client_adapter = NgHttp2Adapter::CreateClientAdapter(client_visitor);
6169
6170 client_adapter->SubmitSettings({});
6171
6172 const std::vector<Header> headers1 =
6173 ToHeaders({{":method", "GET"},
6174 {":scheme", "http"},
6175 {":authority", "example.com"},
6176 {":path", "/this/is/request/one"},
6177 {"cookie", "a; b=2; c"},
6178 {"cookie", "d=e, f, g; h"}});
6179
6180 const int32_t stream_id1 =
6181 client_adapter->SubmitRequest(headers1, nullptr, nullptr);
6182 ASSERT_GT(stream_id1, 0);
6183
6184 EXPECT_CALL(client_visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
6185 EXPECT_CALL(client_visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
6186 EXPECT_CALL(client_visitor,
6187 OnBeforeFrameSent(HEADERS, stream_id1, _,
6188 END_STREAM_FLAG | END_HEADERS_FLAG));
6189 EXPECT_CALL(client_visitor,
6190 OnFrameSent(HEADERS, stream_id1, _,
6191 END_STREAM_FLAG | END_HEADERS_FLAG, 0));
6192 int send_result = client_adapter->Send();
6193 EXPECT_EQ(0, send_result);
6194
6195 DataSavingVisitor server_visitor;
6196 auto server_adapter = NgHttp2Adapter::CreateServerAdapter(server_visitor);
6197
6198 testing::InSequence s;
6199
6200 // Client preface (empty SETTINGS)
6201 EXPECT_CALL(server_visitor, OnFrameHeader(0, _, SETTINGS, 0));
6202 EXPECT_CALL(server_visitor, OnSettingsStart());
6203 EXPECT_CALL(server_visitor, OnSetting).Times(testing::AnyNumber());
6204 EXPECT_CALL(server_visitor, OnSettingsEnd());
6205 // Stream 1
6206 EXPECT_CALL(server_visitor, OnFrameHeader(1, _, HEADERS, 5));
6207 EXPECT_CALL(server_visitor, OnBeginHeadersForStream(1));
6208 EXPECT_CALL(server_visitor, OnHeaderForStream(1, ":method", "GET"));
6209 EXPECT_CALL(server_visitor, OnHeaderForStream(1, ":scheme", "http"));
6210 EXPECT_CALL(server_visitor,
6211 OnHeaderForStream(1, ":authority", "example.com"));
6212 EXPECT_CALL(server_visitor,
6213 OnHeaderForStream(1, ":path", "/this/is/request/one"));
6214 // Cookie values are preserved verbatim.
6215 EXPECT_CALL(server_visitor, OnHeaderForStream(1, "cookie", "a; b=2; c"));
6216 EXPECT_CALL(server_visitor, OnHeaderForStream(1, "cookie", "d=e, f, g; h"));
6217 EXPECT_CALL(server_visitor, OnEndHeadersForStream(1));
6218 EXPECT_CALL(server_visitor, OnEndStream(1));
6219
6220 int64_t result = server_adapter->ProcessBytes(client_visitor.data());
6221 EXPECT_EQ(client_visitor.data().size(), static_cast<size_t>(result));
6222 }
6223
TEST(NgHttp2AdapterTest,ServerForbidsWindowUpdateOnIdleStream)6224 TEST(NgHttp2AdapterTest, ServerForbidsWindowUpdateOnIdleStream) {
6225 DataSavingVisitor visitor;
6226 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6227
6228 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
6229
6230 const std::string frames =
6231 TestFrameSequence().ClientPreface().WindowUpdate(1, 42).Serialize();
6232
6233 testing::InSequence s;
6234
6235 // Client preface (empty SETTINGS)
6236 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6237 EXPECT_CALL(visitor, OnSettingsStart());
6238 EXPECT_CALL(visitor, OnSettingsEnd());
6239
6240 EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
6241 EXPECT_CALL(visitor, OnInvalidFrame(1, _));
6242
6243 const int64_t result = adapter->ProcessBytes(frames);
6244 EXPECT_EQ(frames.size(), result);
6245
6246 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
6247
6248 EXPECT_TRUE(adapter->want_write());
6249
6250 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
6251 EXPECT_CALL(visitor,
6252 OnFrameSent(GOAWAY, 0, _, 0x0,
6253 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
6254
6255 int send_result = adapter->Send();
6256 // Some bytes should have been serialized.
6257 EXPECT_EQ(0, send_result);
6258 // The GOAWAY apparently causes the SETTINGS ack to be dropped.
6259 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
6260 }
6261
TEST(NgHttp2AdapterTest,ServerForbidsDataOnIdleStream)6262 TEST(NgHttp2AdapterTest, ServerForbidsDataOnIdleStream) {
6263 DataSavingVisitor visitor;
6264 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6265
6266 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
6267
6268 const std::string frames = TestFrameSequence()
6269 .ClientPreface()
6270 .Data(1, "Sorry, out of order")
6271 .Serialize();
6272
6273 testing::InSequence s;
6274
6275 // Client preface (empty SETTINGS)
6276 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6277 EXPECT_CALL(visitor, OnSettingsStart());
6278 EXPECT_CALL(visitor, OnSettingsEnd());
6279
6280 const int64_t result = adapter->ProcessBytes(frames);
6281 EXPECT_EQ(frames.size(), result);
6282
6283 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
6284
6285 EXPECT_TRUE(adapter->want_write());
6286
6287 // In this case, nghttp2 goes straight to GOAWAY and does not invoke the
6288 // invalid frame callback.
6289 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
6290 EXPECT_CALL(visitor,
6291 OnFrameSent(GOAWAY, 0, _, 0x0,
6292 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
6293
6294 int send_result = adapter->Send();
6295 // Some bytes should have been serialized.
6296 EXPECT_EQ(0, send_result);
6297 // The GOAWAY apparently causes the SETTINGS ack to be dropped.
6298 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
6299 }
6300
TEST(NgHttp2AdapterTest,ServerForbidsRstStreamOnIdleStream)6301 TEST(NgHttp2AdapterTest, ServerForbidsRstStreamOnIdleStream) {
6302 DataSavingVisitor visitor;
6303 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6304
6305 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
6306
6307 const std::string frames =
6308 TestFrameSequence()
6309 .ClientPreface()
6310 .RstStream(1, Http2ErrorCode::ENHANCE_YOUR_CALM)
6311 .Serialize();
6312
6313 testing::InSequence s;
6314
6315 // Client preface (empty SETTINGS)
6316 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6317 EXPECT_CALL(visitor, OnSettingsStart());
6318 EXPECT_CALL(visitor, OnSettingsEnd());
6319
6320 EXPECT_CALL(visitor, OnFrameHeader(1, _, RST_STREAM, 0));
6321 EXPECT_CALL(visitor, OnInvalidFrame(1, _));
6322
6323 const int64_t result = adapter->ProcessBytes(frames);
6324 EXPECT_EQ(frames.size(), result);
6325
6326 EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
6327
6328 EXPECT_TRUE(adapter->want_write());
6329
6330 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
6331 EXPECT_CALL(visitor,
6332 OnFrameSent(GOAWAY, 0, _, 0x0,
6333 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
6334
6335 int send_result = adapter->Send();
6336 // Some bytes should have been serialized.
6337 EXPECT_EQ(0, send_result);
6338 // The GOAWAY apparently causes the SETTINGS ack to be dropped.
6339 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
6340 }
6341
TEST(NgHttp2AdapterTest,ServerForbidsNewStreamAboveStreamLimit)6342 TEST(NgHttp2AdapterTest, ServerForbidsNewStreamAboveStreamLimit) {
6343 DataSavingVisitor visitor;
6344 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6345 adapter->SubmitSettings({{MAX_CONCURRENT_STREAMS, 1}});
6346
6347 const std::string initial_frames =
6348 TestFrameSequence().ClientPreface().Serialize();
6349
6350 testing::InSequence s;
6351
6352 // Client preface (empty SETTINGS)
6353 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6354 EXPECT_CALL(visitor, OnSettingsStart());
6355 EXPECT_CALL(visitor, OnSettingsEnd());
6356
6357 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
6358 EXPECT_EQ(initial_frames.size(), initial_result);
6359
6360 EXPECT_TRUE(adapter->want_write());
6361
6362 // Server initial SETTINGS (with MAX_CONCURRENT_STREAMS) and SETTINGS ack.
6363 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
6364 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
6365 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
6366 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
6367
6368 int send_result = adapter->Send();
6369 EXPECT_EQ(0, send_result);
6370 EXPECT_THAT(visitor.data(),
6371 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
6372 visitor.Clear();
6373
6374 // Let the client send a SETTINGS ack and then attempt to open more than the
6375 // advertised number of streams. The overflow stream should be rejected.
6376 const std::string stream_frames =
6377 TestFrameSequence()
6378 .SettingsAck()
6379 .Headers(1,
6380 {{":method", "GET"},
6381 {":scheme", "https"},
6382 {":authority", "example.com"},
6383 {":path", "/this/is/request/one"}},
6384 /*fin=*/true)
6385 .Headers(3,
6386 {{":method", "GET"},
6387 {":scheme", "http"},
6388 {":authority", "example.com"},
6389 {":path", "/this/is/request/two"}},
6390 /*fin=*/true)
6391 .Serialize();
6392
6393 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0x1));
6394 EXPECT_CALL(visitor, OnSettingsAck());
6395 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x5));
6396 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
6397 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
6398 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
6399 EXPECT_CALL(visitor, OnEndStream(1));
6400 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 0x5));
6401 EXPECT_CALL(
6402 visitor,
6403 OnInvalidFrame(3, Http2VisitorInterface::InvalidFrameError::kProtocol));
6404
6405 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
6406 EXPECT_EQ(stream_frames.size(), stream_result);
6407
6408 // The server should send a GOAWAY for this error, even though
6409 // OnInvalidFrame() returns true.
6410 EXPECT_TRUE(adapter->want_write());
6411 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
6412 EXPECT_CALL(visitor,
6413 OnFrameSent(GOAWAY, 0, _, 0x0,
6414 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
6415
6416 send_result = adapter->Send();
6417 EXPECT_EQ(0, send_result);
6418 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
6419 }
6420
TEST(NgHttp2AdapterTest,ServerRstStreamsNewStreamAboveStreamLimitBeforeAck)6421 TEST(NgHttp2AdapterTest, ServerRstStreamsNewStreamAboveStreamLimitBeforeAck) {
6422 DataSavingVisitor visitor;
6423 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6424 adapter->SubmitSettings({{MAX_CONCURRENT_STREAMS, 1}});
6425
6426 const std::string initial_frames =
6427 TestFrameSequence().ClientPreface().Serialize();
6428
6429 testing::InSequence s;
6430
6431 // Client preface (empty SETTINGS)
6432 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6433 EXPECT_CALL(visitor, OnSettingsStart());
6434 EXPECT_CALL(visitor, OnSettingsEnd());
6435
6436 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
6437 EXPECT_EQ(initial_frames.size(), initial_result);
6438
6439 EXPECT_TRUE(adapter->want_write());
6440
6441 // Server initial SETTINGS (with MAX_CONCURRENT_STREAMS) and SETTINGS ack.
6442 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
6443 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
6444 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
6445 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
6446
6447 int send_result = adapter->Send();
6448 EXPECT_EQ(0, send_result);
6449 EXPECT_THAT(visitor.data(),
6450 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
6451 visitor.Clear();
6452
6453 // Let the client avoid sending a SETTINGS ack and attempt to open more than
6454 // the advertised number of streams. The server should still reject the
6455 // overflow stream, albeit with RST_STREAM REFUSED_STREAM instead of GOAWAY.
6456 const std::string stream_frames =
6457 TestFrameSequence()
6458 .Headers(1,
6459 {{":method", "GET"},
6460 {":scheme", "https"},
6461 {":authority", "example.com"},
6462 {":path", "/this/is/request/one"}},
6463 /*fin=*/true)
6464 .Headers(3,
6465 {{":method", "GET"},
6466 {":scheme", "http"},
6467 {":authority", "example.com"},
6468 {":path", "/this/is/request/two"}},
6469 /*fin=*/true)
6470 .Serialize();
6471
6472 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x5));
6473 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
6474 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
6475 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
6476 EXPECT_CALL(visitor, OnEndStream(1));
6477 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 0x5));
6478 EXPECT_CALL(visitor,
6479 OnInvalidFrame(
6480 3, Http2VisitorInterface::InvalidFrameError::kRefusedStream));
6481
6482 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
6483 EXPECT_EQ(stream_result, stream_frames.size());
6484
6485 // The server sends a RST_STREAM for the offending stream.
6486 EXPECT_TRUE(adapter->want_write());
6487 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 3, _, 0x0));
6488 EXPECT_CALL(visitor,
6489 OnFrameSent(RST_STREAM, 3, _, 0x0,
6490 static_cast<int>(Http2ErrorCode::REFUSED_STREAM)));
6491
6492 send_result = adapter->Send();
6493 EXPECT_EQ(0, send_result);
6494 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::RST_STREAM}));
6495 }
6496
TEST(NgHttp2AdapterTest,AutomaticSettingsAndPingAcks)6497 TEST(NgHttp2AdapterTest, AutomaticSettingsAndPingAcks) {
6498 DataSavingVisitor visitor;
6499 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6500 const std::string frames =
6501 TestFrameSequence().ClientPreface().Ping(42).Serialize();
6502 testing::InSequence s;
6503
6504 // Client preface (empty SETTINGS)
6505 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6506 EXPECT_CALL(visitor, OnSettingsStart());
6507 EXPECT_CALL(visitor, OnSettingsEnd());
6508 // PING
6509 EXPECT_CALL(visitor, OnFrameHeader(0, _, PING, 0));
6510 EXPECT_CALL(visitor, OnPing(42, false));
6511
6512 const int64_t read_result = adapter->ProcessBytes(frames);
6513 EXPECT_EQ(static_cast<size_t>(read_result), frames.size());
6514
6515 EXPECT_TRUE(adapter->want_write());
6516
6517 // Server preface does not appear to include the mandatory SETTINGS frame.
6518 // SETTINGS ack
6519 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
6520 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
6521 // PING ack
6522 EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, _, 0x1));
6523 EXPECT_CALL(visitor, OnFrameSent(PING, 0, _, 0x1, 0));
6524
6525 int send_result = adapter->Send();
6526 EXPECT_EQ(0, send_result);
6527 EXPECT_THAT(visitor.data(),
6528 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::PING}));
6529 }
6530
TEST(NgHttp2AdapterTest,AutomaticPingAcksDisabled)6531 TEST(NgHttp2AdapterTest, AutomaticPingAcksDisabled) {
6532 DataSavingVisitor visitor;
6533 nghttp2_option* options;
6534 nghttp2_option_new(&options);
6535 nghttp2_option_set_no_auto_ping_ack(options, 1);
6536 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor, options);
6537 nghttp2_option_del(options);
6538
6539 const std::string frames =
6540 TestFrameSequence().ClientPreface().Ping(42).Serialize();
6541 testing::InSequence s;
6542
6543 // Client preface (empty SETTINGS)
6544 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6545 EXPECT_CALL(visitor, OnSettingsStart());
6546 EXPECT_CALL(visitor, OnSettingsEnd());
6547 // PING
6548 EXPECT_CALL(visitor, OnFrameHeader(0, _, PING, 0));
6549 EXPECT_CALL(visitor, OnPing(42, false));
6550
6551 const int64_t read_result = adapter->ProcessBytes(frames);
6552 EXPECT_EQ(static_cast<size_t>(read_result), frames.size());
6553
6554 EXPECT_TRUE(adapter->want_write());
6555
6556 // Server preface does not appear to include the mandatory SETTINGS frame.
6557 // SETTINGS ack
6558 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
6559 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
6560 // No PING ack expected because automatic PING acks are disabled.
6561
6562 int send_result = adapter->Send();
6563 EXPECT_EQ(0, send_result);
6564 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
6565 }
6566
TEST(NgHttp2AdapterTest,InvalidMaxFrameSizeSetting)6567 TEST(NgHttp2AdapterTest, InvalidMaxFrameSizeSetting) {
6568 DataSavingVisitor visitor;
6569 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6570
6571 const std::string frames =
6572 TestFrameSequence().ClientPreface({{MAX_FRAME_SIZE, 3u}}).Serialize();
6573 testing::InSequence s;
6574
6575 // Client preface
6576 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
6577 EXPECT_CALL(
6578 visitor,
6579 OnInvalidFrame(0, Http2VisitorInterface::InvalidFrameError::kProtocol));
6580
6581 const int64_t read_result = adapter->ProcessBytes(frames);
6582 EXPECT_EQ(static_cast<size_t>(read_result), frames.size());
6583
6584 EXPECT_TRUE(adapter->want_write());
6585
6586 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
6587 EXPECT_CALL(visitor,
6588 OnFrameSent(GOAWAY, 0, _, 0x0,
6589 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
6590
6591 int send_result = adapter->Send();
6592 EXPECT_EQ(0, send_result);
6593 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
6594 }
6595
TEST(OgHttp2AdapterTest,InvalidPushSetting)6596 TEST(OgHttp2AdapterTest, InvalidPushSetting) {
6597 DataSavingVisitor visitor;
6598 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6599
6600 const std::string frames =
6601 TestFrameSequence().ClientPreface({{ENABLE_PUSH, 3u}}).Serialize();
6602 testing::InSequence s;
6603
6604 // Client preface
6605 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
6606 EXPECT_CALL(visitor, OnInvalidFrame(0, _));
6607
6608 const int64_t read_result = adapter->ProcessBytes(frames);
6609 EXPECT_EQ(static_cast<size_t>(read_result), frames.size());
6610
6611 EXPECT_TRUE(adapter->want_write());
6612
6613 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
6614 EXPECT_CALL(visitor,
6615 OnFrameSent(GOAWAY, 0, _, 0x0,
6616 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
6617
6618 int send_result = adapter->Send();
6619 EXPECT_EQ(0, send_result);
6620 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
6621 }
6622
TEST(NgHttp2AdapterTest,InvalidConnectProtocolSetting)6623 TEST(NgHttp2AdapterTest, InvalidConnectProtocolSetting) {
6624 DataSavingVisitor visitor;
6625 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6626
6627 const std::string frames = TestFrameSequence()
6628 .ClientPreface({{ENABLE_CONNECT_PROTOCOL, 3u}})
6629 .Serialize();
6630 testing::InSequence s;
6631
6632 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
6633 EXPECT_CALL(
6634 visitor,
6635 OnInvalidFrame(0, Http2VisitorInterface::InvalidFrameError::kProtocol));
6636
6637 int64_t read_result = adapter->ProcessBytes(frames);
6638 EXPECT_EQ(static_cast<size_t>(read_result), frames.size());
6639
6640 EXPECT_TRUE(adapter->want_write());
6641
6642 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
6643 EXPECT_CALL(visitor,
6644 OnFrameSent(GOAWAY, 0, _, 0x0,
6645 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
6646
6647 int send_result = adapter->Send();
6648 EXPECT_EQ(0, send_result);
6649 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
6650
6651 auto adapter2 = NgHttp2Adapter::CreateServerAdapter(visitor);
6652 const std::string frames2 = TestFrameSequence()
6653 .ClientPreface({{ENABLE_CONNECT_PROTOCOL, 1}})
6654 .Settings({{ENABLE_CONNECT_PROTOCOL, 0}})
6655 .Serialize();
6656
6657 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
6658 EXPECT_CALL(visitor, OnSettingsStart());
6659 EXPECT_CALL(visitor, OnSetting(Http2Setting{ENABLE_CONNECT_PROTOCOL, 1u}));
6660 EXPECT_CALL(visitor, OnSettingsEnd());
6661 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
6662 EXPECT_CALL(visitor, OnSettingsStart());
6663 // Surprisingly, nghttp2 allows this behavior, which is prohibited in RFC
6664 // 8441.
6665 EXPECT_CALL(visitor, OnSetting(Http2Setting{ENABLE_CONNECT_PROTOCOL, 0u}));
6666 EXPECT_CALL(visitor, OnSettingsEnd());
6667
6668 read_result = adapter2->ProcessBytes(frames2);
6669 EXPECT_EQ(static_cast<size_t>(read_result), frames2.size());
6670
6671 EXPECT_TRUE(adapter2->want_write());
6672
6673 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
6674 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
6675 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
6676 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
6677 adapter2->Send();
6678 }
6679
TEST(NgHttp2AdapterTest,ServerForbidsProtocolPseudoheaderBeforeAck)6680 TEST(NgHttp2AdapterTest, ServerForbidsProtocolPseudoheaderBeforeAck) {
6681 DataSavingVisitor visitor;
6682 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6683
6684 const std::string initial_frames =
6685 TestFrameSequence().ClientPreface().Serialize();
6686
6687 testing::InSequence s;
6688
6689 // Client preface (empty SETTINGS)
6690 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6691 EXPECT_CALL(visitor, OnSettingsStart());
6692 EXPECT_CALL(visitor, OnSettingsEnd());
6693
6694 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
6695 EXPECT_EQ(static_cast<size_t>(initial_result), initial_frames.size());
6696
6697 // The client attempts to send a CONNECT request with the `:protocol`
6698 // pseudoheader before receiving the server's SETTINGS frame.
6699 const std::string stream1_frames =
6700 TestFrameSequence()
6701 .Headers(1,
6702 {{":method", "CONNECT"},
6703 {":scheme", "https"},
6704 {":authority", "example.com"},
6705 {":path", "/this/is/request/one"},
6706 {":protocol", "websocket"}},
6707 /*fin=*/true)
6708 .Serialize();
6709
6710 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x5));
6711 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
6712 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
6713 EXPECT_CALL(
6714 visitor,
6715 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
6716 "stream: 1, name: [:protocol], value: [websocket]"));
6717 EXPECT_CALL(
6718 visitor,
6719 OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
6720
6721 int64_t stream_result = adapter->ProcessBytes(stream1_frames);
6722 EXPECT_EQ(static_cast<size_t>(stream_result), stream1_frames.size());
6723
6724 // Server sends a SETTINGS ack and initial SETTINGS (with
6725 // ENABLE_CONNECT_PROTOCOL).
6726 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
6727 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
6728 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
6729 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
6730
6731 // The server sends a RST_STREAM for the offending stream.
6732 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
6733 EXPECT_CALL(visitor,
6734 OnFrameSent(RST_STREAM, 1, _, 0x0,
6735 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
6736 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
6737
6738 adapter->SubmitSettings({{ENABLE_CONNECT_PROTOCOL, 1}});
6739 int send_result = adapter->Send();
6740 EXPECT_EQ(0, send_result);
6741 EXPECT_THAT(visitor.data(),
6742 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS,
6743 SpdyFrameType::RST_STREAM}));
6744 visitor.Clear();
6745
6746 // The client attempts to send a CONNECT request with the `:protocol`
6747 // pseudoheader before acking the server's SETTINGS frame.
6748 const std::string stream3_frames =
6749 TestFrameSequence()
6750 .Headers(3,
6751 {{":method", "CONNECT"},
6752 {":scheme", "https"},
6753 {":authority", "example.com"},
6754 {":path", "/this/is/request/two"},
6755 {":protocol", "websocket"}},
6756 /*fin=*/true)
6757 .Serialize();
6758
6759 // Surprisingly, nghttp2 is okay with this.
6760 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 0x5));
6761 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
6762 EXPECT_CALL(visitor, OnHeaderForStream(3, _, _)).Times(5);
6763 EXPECT_CALL(visitor, OnEndHeadersForStream(3));
6764 EXPECT_CALL(visitor, OnEndStream(3));
6765
6766 stream_result = adapter->ProcessBytes(stream3_frames);
6767 EXPECT_EQ(static_cast<size_t>(stream_result), stream3_frames.size());
6768
6769 EXPECT_FALSE(adapter->want_write());
6770 }
6771
TEST(NgHttp2AdapterTest,ServerAllowsProtocolPseudoheaderAfterAck)6772 TEST(NgHttp2AdapterTest, ServerAllowsProtocolPseudoheaderAfterAck) {
6773 DataSavingVisitor visitor;
6774 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6775 adapter->SubmitSettings({{ENABLE_CONNECT_PROTOCOL, 1}});
6776
6777 const std::string initial_frames =
6778 TestFrameSequence().ClientPreface().Serialize();
6779
6780 testing::InSequence s;
6781
6782 // Client preface (empty SETTINGS)
6783 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6784 EXPECT_CALL(visitor, OnSettingsStart());
6785 EXPECT_CALL(visitor, OnSettingsEnd());
6786
6787 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
6788 EXPECT_EQ(static_cast<size_t>(initial_result), initial_frames.size());
6789
6790 // Server initial SETTINGS (with ENABLE_CONNECT_PROTOCOL) and SETTINGS ack.
6791 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
6792 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
6793 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
6794 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
6795
6796 int send_result = adapter->Send();
6797 EXPECT_EQ(0, send_result);
6798 visitor.Clear();
6799
6800 // The client attempts to send a CONNECT request with the `:protocol`
6801 // pseudoheader after acking the server's SETTINGS frame.
6802 const std::string stream_frames =
6803 TestFrameSequence()
6804 .SettingsAck()
6805 .Headers(1,
6806 {{":method", "CONNECT"},
6807 {":scheme", "https"},
6808 {":authority", "example.com"},
6809 {":path", "/this/is/request/one"},
6810 {":protocol", "websocket"}},
6811 /*fin=*/true)
6812 .Serialize();
6813
6814 EXPECT_CALL(visitor, OnFrameHeader(0, _, SETTINGS, 0x1));
6815 EXPECT_CALL(visitor, OnSettingsAck());
6816 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x5));
6817 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
6818 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(5);
6819 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
6820 EXPECT_CALL(visitor, OnEndStream(1));
6821
6822 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
6823 EXPECT_EQ(static_cast<size_t>(stream_result), stream_frames.size());
6824
6825 EXPECT_FALSE(adapter->want_write());
6826 }
6827
TEST(NgHttp2AdapterTest,SkipsSendingFramesForRejectedStream)6828 TEST(NgHttp2AdapterTest, SkipsSendingFramesForRejectedStream) {
6829 DataSavingVisitor visitor;
6830 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6831
6832 const std::string initial_frames =
6833 TestFrameSequence()
6834 .ClientPreface()
6835 .Headers(1,
6836 {{":method", "GET"},
6837 {":scheme", "http"},
6838 {":authority", "example.com"},
6839 {":path", "/this/is/request/one"}},
6840 /*fin=*/true)
6841 .Serialize();
6842
6843 testing::InSequence s;
6844
6845 // Client preface (empty SETTINGS)
6846 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6847 EXPECT_CALL(visitor, OnSettingsStart());
6848 EXPECT_CALL(visitor, OnSettingsEnd());
6849 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x5));
6850 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
6851 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
6852 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
6853 EXPECT_CALL(visitor, OnEndStream(1));
6854
6855 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
6856 EXPECT_EQ(static_cast<size_t>(initial_result), initial_frames.size());
6857
6858 auto body = std::make_unique<TestDataFrameSource>(visitor, true);
6859 body->AppendPayload("Here is some data, which will be completely ignored!");
6860
6861 int submit_result = adapter->SubmitResponse(
6862 1, ToHeaders({{":status", "200"}}), std::move(body));
6863 ASSERT_EQ(0, submit_result);
6864
6865 auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
6866 {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
6867 adapter->SubmitMetadata(1, 16384u, std::move(source));
6868
6869 adapter->SubmitWindowUpdate(1, 1024);
6870 adapter->SubmitRst(1, Http2ErrorCode::INTERNAL_ERROR);
6871
6872 // Server initial SETTINGS and SETTINGS ack.
6873 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
6874 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
6875
6876 // nghttp2 apparently allows extension frames to be sent on reset streams.
6877 EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
6878 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
6879
6880 // The server sends a RST_STREAM for the offending stream.
6881 // The response HEADERS, DATA and WINDOW_UPDATE are all ignored.
6882 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
6883 EXPECT_CALL(visitor,
6884 OnFrameSent(RST_STREAM, 1, _, 0x0,
6885 static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
6886 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::INTERNAL_ERROR));
6887
6888 int send_result = adapter->Send();
6889 EXPECT_EQ(0, send_result);
6890 EXPECT_THAT(visitor.data(),
6891 EqualsFrames({SpdyFrameType::SETTINGS,
6892 static_cast<SpdyFrameType>(kMetadataFrameType),
6893 SpdyFrameType::RST_STREAM}));
6894 }
6895
TEST(NgHttp2AdapterTest,ServerQueuesMetadataWithStreamReset)6896 TEST(NgHttp2AdapterTest, ServerQueuesMetadataWithStreamReset) {
6897 DataSavingVisitor visitor;
6898 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6899
6900 const std::string initial_frames =
6901 TestFrameSequence()
6902 .ClientPreface()
6903 .Headers(1,
6904 {{":method", "GET"},
6905 {":scheme", "http"},
6906 {":authority", "example.com"},
6907 {":path", "/this/is/request/one"}},
6908 /*fin=*/false)
6909 .Serialize();
6910
6911 testing::InSequence s;
6912
6913 // Client preface (empty SETTINGS)
6914 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
6915 EXPECT_CALL(visitor, OnSettingsStart());
6916 EXPECT_CALL(visitor, OnSettingsEnd());
6917 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x4));
6918 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
6919 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
6920 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
6921
6922 const int64_t initial_result = adapter->ProcessBytes(initial_frames);
6923 EXPECT_EQ(static_cast<size_t>(initial_result), initial_frames.size());
6924
6925 auto body = std::make_unique<TestDataFrameSource>(visitor, true);
6926 body->AppendPayload("Here is some data, which will be completely ignored!");
6927
6928 int submit_result = adapter->SubmitResponse(
6929 1, ToHeaders({{":status", "200"}}), std::move(body));
6930 ASSERT_EQ(0, submit_result);
6931
6932 auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
6933 {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
6934 adapter->SubmitMetadata(1, 16384u, std::move(source));
6935 adapter->SubmitWindowUpdate(1, 1024);
6936
6937 const std::string reset_frame =
6938 TestFrameSequence().RstStream(1, Http2ErrorCode::CANCEL).Serialize();
6939
6940 EXPECT_CALL(visitor, OnFrameHeader(1, _, RST_STREAM, 0x0));
6941 EXPECT_CALL(visitor, OnRstStream(1, Http2ErrorCode::CANCEL));
6942 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::CANCEL));
6943 adapter->ProcessBytes(reset_frame);
6944
6945 source = std::make_unique<TestMetadataSource>(
6946 ToHeaderBlock(ToHeaders({{"really-important", "information!"}})));
6947 adapter->SubmitMetadata(1, 16384u, std::move(source));
6948
6949 EXPECT_EQ(1, adapter->stream_metadata_size());
6950 EXPECT_EQ(2, adapter->pending_metadata_count(1));
6951
6952 // Server initial SETTINGS and SETTINGS ack.
6953 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
6954 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
6955
6956 // nghttp2 apparently allows extension frames to be sent on reset streams.
6957 // The response HEADERS, DATA and WINDOW_UPDATE are all discarded.
6958 EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
6959 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
6960 EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
6961 EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
6962
6963 int send_result = adapter->Send();
6964 EXPECT_EQ(0, send_result);
6965 EXPECT_THAT(visitor.data(),
6966 EqualsFrames({SpdyFrameType::SETTINGS,
6967 static_cast<SpdyFrameType>(kMetadataFrameType),
6968 static_cast<SpdyFrameType>(kMetadataFrameType)}));
6969
6970 EXPECT_EQ(0, adapter->stream_metadata_size());
6971 EXPECT_EQ(0, adapter->pending_metadata_count(1));
6972 }
6973
TEST(NgHttp2AdapterTest,ServerStartsShutdown)6974 TEST(NgHttp2AdapterTest, ServerStartsShutdown) {
6975 DataSavingVisitor visitor;
6976 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6977
6978 EXPECT_FALSE(adapter->want_write());
6979
6980 adapter->SubmitShutdownNotice();
6981 EXPECT_TRUE(adapter->want_write());
6982
6983 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
6984 EXPECT_CALL(visitor, OnFrameSent(GOAWAY, 0, _, 0x0, 0));
6985
6986 int result = adapter->Send();
6987 EXPECT_EQ(0, result);
6988 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
6989 }
6990
TEST(NgHttp2AdapterTest,ServerStartsShutdownAfterGoaway)6991 TEST(NgHttp2AdapterTest, ServerStartsShutdownAfterGoaway) {
6992 DataSavingVisitor visitor;
6993 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
6994
6995 EXPECT_FALSE(adapter->want_write());
6996
6997 adapter->SubmitGoAway(1, Http2ErrorCode::HTTP2_NO_ERROR,
6998 "and don't come back!");
6999 EXPECT_TRUE(adapter->want_write());
7000
7001 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
7002 EXPECT_CALL(visitor, OnFrameSent(GOAWAY, 0, _, 0x0, 0));
7003
7004 int result = adapter->Send();
7005 EXPECT_EQ(0, result);
7006 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
7007
7008 // No-op, since a GOAWAY has previously been enqueued.
7009 adapter->SubmitShutdownNotice();
7010 EXPECT_FALSE(adapter->want_write());
7011 }
7012
7013 // Verifies that a connection-level processing error results in repeatedly
7014 // returning a positive value for ProcessBytes() to mark all data as consumed.
TEST(NgHttp2AdapterTest,ConnectionErrorWithBlackholeSinkingData)7015 TEST(NgHttp2AdapterTest, ConnectionErrorWithBlackholeSinkingData) {
7016 DataSavingVisitor visitor;
7017 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
7018
7019 const std::string frames =
7020 TestFrameSequence().ClientPreface().WindowUpdate(1, 42).Serialize();
7021
7022 testing::InSequence s;
7023
7024 // Client preface (empty SETTINGS)
7025 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
7026 EXPECT_CALL(visitor, OnSettingsStart());
7027 EXPECT_CALL(visitor, OnSettingsEnd());
7028
7029 EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
7030 EXPECT_CALL(visitor, OnInvalidFrame(1, _));
7031
7032 const int64_t result = adapter->ProcessBytes(frames);
7033 EXPECT_EQ(static_cast<size_t>(result), frames.size());
7034
7035 // Ask the connection to process more bytes. Because the option is enabled,
7036 // the data should be marked as consumed.
7037 const std::string next_frame = TestFrameSequence().Ping(42).Serialize();
7038 const int64_t next_result = adapter->ProcessBytes(next_frame);
7039 EXPECT_EQ(static_cast<size_t>(next_result), next_frame.size());
7040 }
7041
TEST(NgHttp2AdapterTest,ServerDoesNotSendFramesAfterImmediateGoAway)7042 TEST(NgHttp2AdapterTest, ServerDoesNotSendFramesAfterImmediateGoAway) {
7043 DataSavingVisitor visitor;
7044 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
7045
7046 // Submit a custom initial SETTINGS frame with one setting.
7047 adapter->SubmitSettings({{HEADER_TABLE_SIZE, 100u}});
7048
7049 const std::string frames = TestFrameSequence()
7050 .ClientPreface()
7051 .Headers(1,
7052 {{":method", "GET"},
7053 {":scheme", "https"},
7054 {":authority", "example.com"},
7055 {":path", "/this/is/request/one"}},
7056 /*fin=*/true)
7057 .Serialize();
7058 testing::InSequence s;
7059
7060 // Client preface (empty SETTINGS)
7061 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
7062 EXPECT_CALL(visitor, OnSettingsStart());
7063 EXPECT_CALL(visitor, OnSettingsEnd());
7064 // Stream 1
7065 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x5));
7066 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
7067 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
7068 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
7069 EXPECT_CALL(visitor, OnEndStream(1));
7070
7071 const int64_t read_result = adapter->ProcessBytes(frames);
7072 EXPECT_EQ(static_cast<size_t>(read_result), frames.size());
7073
7074 // Submit a response for the stream.
7075 auto body = std::make_unique<TestDataFrameSource>(visitor, true);
7076 body->AppendPayload("This data is doomed to never be written.");
7077 int submit_result = adapter->SubmitResponse(
7078 1, ToHeaders({{":status", "200"}}), std::move(body));
7079 ASSERT_EQ(0, submit_result);
7080
7081 // Submit a WINDOW_UPDATE frame.
7082 adapter->SubmitWindowUpdate(kConnectionStreamId, 42);
7083
7084 // Submit another SETTINGS frame.
7085 adapter->SubmitSettings({});
7086
7087 // Submit some metadata.
7088 auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
7089 {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
7090 adapter->SubmitMetadata(1, 16384u, std::move(source));
7091
7092 EXPECT_TRUE(adapter->want_write());
7093
7094 // Trigger a connection error. Only the response headers will be written.
7095 const std::string connection_error_frames =
7096 TestFrameSequence().WindowUpdate(3, 42).Serialize();
7097
7098 EXPECT_CALL(visitor, OnFrameHeader(3, 4, WINDOW_UPDATE, 0));
7099 EXPECT_CALL(visitor, OnInvalidFrame(3, _));
7100
7101 const int64_t result = adapter->ProcessBytes(connection_error_frames);
7102 EXPECT_EQ(static_cast<size_t>(result), connection_error_frames.size());
7103
7104 EXPECT_TRUE(adapter->want_write());
7105
7106 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 6, 0x0));
7107 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 6, 0x0, 0));
7108 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x0));
7109 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x0, 0));
7110 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
7111 EXPECT_CALL(visitor,
7112 OnFrameSent(GOAWAY, 0, _, 0x0,
7113 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7114
7115 int send_result = adapter->Send();
7116 // Some bytes should have been serialized.
7117 EXPECT_EQ(0, send_result);
7118 // The GOAWAY apparently causes the other frames to be dropped except for the
7119 // non-ack SETTINGS frames; nghttp2 sends non-ack SETTINGS frames because they
7120 // could be the initial SETTINGS frame. However, nghttp2 still allows sending
7121 // multiple non-ack SETTINGS, which feels non-ideal.
7122 EXPECT_THAT(visitor.data(),
7123 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS,
7124 SpdyFrameType::GOAWAY}));
7125 visitor.Clear();
7126
7127 // Try to submit more frames for writing. They should not be written.
7128 adapter->SubmitPing(42);
7129 EXPECT_FALSE(adapter->want_write());
7130 send_result = adapter->Send();
7131 EXPECT_EQ(0, send_result);
7132 EXPECT_THAT(visitor.data(), testing::IsEmpty());
7133 }
7134
TEST(NgHttp2AdapterTest,ServerHandlesContentLength)7135 TEST(NgHttp2AdapterTest, ServerHandlesContentLength) {
7136 DataSavingVisitor visitor;
7137 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
7138
7139 testing::InSequence s;
7140
7141 const std::string stream_frames =
7142 TestFrameSequence()
7143 .ClientPreface()
7144 .Headers(1, {{":method", "GET"},
7145 {":scheme", "https"},
7146 {":authority", "example.com"},
7147 {":path", "/this/is/request/one"},
7148 {"content-length", "2"}})
7149 .Data(1, "hi", /*fin=*/true)
7150 .Headers(3,
7151 {{":method", "GET"},
7152 {":scheme", "https"},
7153 {":authority", "example.com"},
7154 {":path", "/this/is/request/two"},
7155 {"content-length", "nan"}},
7156 /*fin=*/true)
7157 .Serialize();
7158
7159 // Client preface (empty SETTINGS)
7160 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
7161 EXPECT_CALL(visitor, OnSettingsStart());
7162 EXPECT_CALL(visitor, OnSettingsEnd());
7163
7164 // Stream 1: content-length is correct
7165 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
7166 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
7167 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(5);
7168 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
7169 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 1));
7170 EXPECT_CALL(visitor, OnBeginDataForStream(1, 2));
7171 EXPECT_CALL(visitor, OnDataForStream(1, "hi"));
7172 EXPECT_CALL(visitor, OnEndStream(1));
7173
7174 // Stream 3: content-length is not a number
7175 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 5));
7176 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
7177 EXPECT_CALL(visitor, OnHeaderForStream(3, _, _)).Times(4);
7178 EXPECT_CALL(
7179 visitor,
7180 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
7181 "stream: 3, name: [content-length], value: [nan]"));
7182 EXPECT_CALL(
7183 visitor,
7184 OnInvalidFrame(3, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
7185
7186 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
7187 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
7188
7189 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
7190 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
7191 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 3, _, 0x0));
7192 EXPECT_CALL(visitor,
7193 OnFrameSent(RST_STREAM, 3, _, 0x0,
7194 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7195 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::PROTOCOL_ERROR));
7196
7197 EXPECT_TRUE(adapter->want_write());
7198 int result = adapter->Send();
7199 EXPECT_EQ(0, result);
7200 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
7201 SpdyFrameType::RST_STREAM}));
7202 }
7203
TEST(NgHttp2AdapterTest,ServerHandlesContentLengthMismatch)7204 TEST(NgHttp2AdapterTest, ServerHandlesContentLengthMismatch) {
7205 DataSavingVisitor visitor;
7206 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
7207
7208 testing::InSequence s;
7209
7210 const std::string stream_frames =
7211 TestFrameSequence()
7212 .ClientPreface()
7213 .Headers(1, {{":method", "GET"},
7214 {":scheme", "https"},
7215 {":authority", "example.com"},
7216 {":path", "/this/is/request/two"},
7217 {"content-length", "2"}})
7218 .Data(1, "h", /*fin=*/true)
7219 .Headers(3, {{":method", "GET"},
7220 {":scheme", "https"},
7221 {":authority", "example.com"},
7222 {":path", "/this/is/request/three"},
7223 {"content-length", "2"}})
7224 .Data(3, "howdy", /*fin=*/true)
7225 .Headers(5,
7226 {{":method", "GET"},
7227 {":scheme", "https"},
7228 {":authority", "example.com"},
7229 {":path", "/this/is/request/four"},
7230 {"content-length", "2"}},
7231 /*fin=*/true)
7232 .Headers(7,
7233 {{":method", "GET"},
7234 {":scheme", "https"},
7235 {":authority", "example.com"},
7236 {":path", "/this/is/request/four"},
7237 {"content-length", "2"}},
7238 /*fin=*/false)
7239 .Data(7, "h", /*fin=*/false)
7240 .Headers(7, {{"extra-info", "Trailers with content-length mismatch"}},
7241 /*fin=*/true)
7242 .Serialize();
7243
7244 // Client preface (empty SETTINGS)
7245 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
7246 EXPECT_CALL(visitor, OnSettingsStart());
7247 EXPECT_CALL(visitor, OnSettingsEnd());
7248
7249 // Stream 1: content-length is larger than actual data
7250 // All data is delivered to the visitor, but OnInvalidFrame() is not.
7251 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
7252 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
7253 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(5);
7254 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
7255 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 1));
7256 EXPECT_CALL(visitor, OnBeginDataForStream(1, 1));
7257 EXPECT_CALL(visitor, OnDataForStream(1, "h"));
7258
7259 // Stream 3: content-length is smaller than actual data
7260 // The beginning of data is delivered to the visitor, but not the actual data,
7261 // and neither is OnInvalidFrame().
7262 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 4));
7263 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
7264 EXPECT_CALL(visitor, OnHeaderForStream(3, _, _)).Times(5);
7265 EXPECT_CALL(visitor, OnEndHeadersForStream(3));
7266 EXPECT_CALL(visitor, OnFrameHeader(3, _, DATA, 1));
7267 EXPECT_CALL(visitor, OnBeginDataForStream(3, 5));
7268
7269 // Stream 5: content-length is invalid and HEADERS ends the stream
7270 // When the stream ends with HEADERS, nghttp2 invokes OnInvalidFrame().
7271 EXPECT_CALL(visitor, OnFrameHeader(5, _, HEADERS, 5));
7272 EXPECT_CALL(visitor, OnBeginHeadersForStream(5));
7273 EXPECT_CALL(visitor, OnHeaderForStream(5, _, _)).Times(5);
7274 EXPECT_CALL(visitor,
7275 OnInvalidFrame(
7276 5, Http2VisitorInterface::InvalidFrameError::kHttpMessaging));
7277
7278 // Stream 7: content-length is invalid and trailers end the stream
7279 // When the stream ends with trailers, nghttp2 invokes OnInvalidFrame().
7280 EXPECT_CALL(visitor, OnFrameHeader(7, _, HEADERS, 4));
7281 EXPECT_CALL(visitor, OnBeginHeadersForStream(7));
7282 EXPECT_CALL(visitor, OnHeaderForStream(7, _, _)).Times(5);
7283 EXPECT_CALL(visitor, OnEndHeadersForStream(7));
7284 EXPECT_CALL(visitor, OnFrameHeader(7, _, DATA, 0));
7285 EXPECT_CALL(visitor, OnBeginDataForStream(7, 1));
7286 EXPECT_CALL(visitor, OnDataForStream(7, "h"));
7287 EXPECT_CALL(visitor, OnFrameHeader(7, _, HEADERS, 5));
7288 EXPECT_CALL(visitor, OnBeginHeadersForStream(7));
7289 EXPECT_CALL(visitor, OnHeaderForStream(7, _, _));
7290 EXPECT_CALL(visitor,
7291 OnInvalidFrame(
7292 7, Http2VisitorInterface::InvalidFrameError::kHttpMessaging));
7293
7294 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
7295 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
7296
7297 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
7298 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
7299 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
7300 EXPECT_CALL(visitor,
7301 OnFrameSent(RST_STREAM, 1, _, 0x0,
7302 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7303 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
7304 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 3, _, 0x0));
7305 EXPECT_CALL(visitor,
7306 OnFrameSent(RST_STREAM, 3, _, 0x0,
7307 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7308 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::PROTOCOL_ERROR));
7309 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 5, _, 0x0));
7310 EXPECT_CALL(visitor,
7311 OnFrameSent(RST_STREAM, 5, _, 0x0,
7312 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7313 EXPECT_CALL(visitor, OnCloseStream(5, Http2ErrorCode::PROTOCOL_ERROR));
7314 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 7, _, 0x0));
7315 EXPECT_CALL(visitor,
7316 OnFrameSent(RST_STREAM, 7, _, 0x0,
7317 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7318 EXPECT_CALL(visitor, OnCloseStream(7, Http2ErrorCode::PROTOCOL_ERROR));
7319
7320 EXPECT_TRUE(adapter->want_write());
7321 int result = adapter->Send();
7322 EXPECT_EQ(0, result);
7323 EXPECT_THAT(
7324 visitor.data(),
7325 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::RST_STREAM,
7326 SpdyFrameType::RST_STREAM, SpdyFrameType::RST_STREAM,
7327 SpdyFrameType::RST_STREAM}));
7328 }
7329
TEST(NgHttp2AdapterTest,ServerHandlesAsteriskPathForOptions)7330 TEST(NgHttp2AdapterTest, ServerHandlesAsteriskPathForOptions) {
7331 DataSavingVisitor visitor;
7332 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
7333
7334 testing::InSequence s;
7335
7336 const std::string stream_frames = TestFrameSequence()
7337 .ClientPreface()
7338 .Headers(1,
7339 {{":scheme", "https"},
7340 {":authority", "example.com"},
7341 {":path", "*"},
7342 {":method", "OPTIONS"}},
7343 /*fin=*/true)
7344 .Serialize();
7345
7346 // Client preface (empty SETTINGS)
7347 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
7348 EXPECT_CALL(visitor, OnSettingsStart());
7349 EXPECT_CALL(visitor, OnSettingsEnd());
7350
7351 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
7352 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
7353 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
7354 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
7355 EXPECT_CALL(visitor, OnEndStream(1));
7356
7357 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
7358 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
7359
7360 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
7361 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
7362
7363 EXPECT_TRUE(adapter->want_write());
7364 int result = adapter->Send();
7365 EXPECT_EQ(0, result);
7366 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
7367 }
7368
TEST(NgHttp2AdapterTest,ServerHandlesInvalidPath)7369 TEST(NgHttp2AdapterTest, ServerHandlesInvalidPath) {
7370 DataSavingVisitor visitor;
7371 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
7372
7373 testing::InSequence s;
7374
7375 const std::string stream_frames =
7376 TestFrameSequence()
7377 .ClientPreface()
7378 .Headers(1,
7379 {{":scheme", "https"},
7380 {":authority", "example.com"},
7381 {":path", "*"},
7382 {":method", "GET"}},
7383 /*fin=*/true)
7384 .Headers(3,
7385 {{":scheme", "https"},
7386 {":authority", "example.com"},
7387 {":path", "other/non/slash/starter"},
7388 {":method", "GET"}},
7389 /*fin=*/true)
7390 .Headers(5,
7391 {{":scheme", "https"},
7392 {":authority", "example.com"},
7393 {":path", ""},
7394 {":method", "GET"}},
7395 /*fin=*/true)
7396 .Serialize();
7397
7398 // Client preface (empty SETTINGS)
7399 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
7400 EXPECT_CALL(visitor, OnSettingsStart());
7401 EXPECT_CALL(visitor, OnSettingsEnd());
7402
7403 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
7404 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
7405 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
7406 EXPECT_CALL(visitor,
7407 OnInvalidFrame(
7408 1, Http2VisitorInterface::InvalidFrameError::kHttpMessaging));
7409
7410 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 5));
7411 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
7412 EXPECT_CALL(visitor, OnHeaderForStream(3, _, _)).Times(4);
7413 EXPECT_CALL(visitor,
7414 OnInvalidFrame(
7415 3, Http2VisitorInterface::InvalidFrameError::kHttpMessaging));
7416
7417 EXPECT_CALL(visitor, OnFrameHeader(5, _, HEADERS, 5));
7418 EXPECT_CALL(visitor, OnBeginHeadersForStream(5));
7419 EXPECT_CALL(visitor, OnHeaderForStream(5, _, _)).Times(2);
7420 EXPECT_CALL(
7421 visitor,
7422 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
7423 "stream: 5, name: [:path], value: []"));
7424 EXPECT_CALL(
7425 visitor,
7426 OnInvalidFrame(5, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
7427
7428 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
7429 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
7430
7431 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
7432 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
7433 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
7434 EXPECT_CALL(visitor,
7435 OnFrameSent(RST_STREAM, 1, _, 0x0,
7436 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7437 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
7438 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 3, _, 0x0));
7439 EXPECT_CALL(visitor,
7440 OnFrameSent(RST_STREAM, 3, _, 0x0,
7441 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7442 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::PROTOCOL_ERROR));
7443 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 5, _, 0x0));
7444 EXPECT_CALL(visitor,
7445 OnFrameSent(RST_STREAM, 5, _, 0x0,
7446 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7447 EXPECT_CALL(visitor, OnCloseStream(5, Http2ErrorCode::PROTOCOL_ERROR));
7448
7449 EXPECT_TRUE(adapter->want_write());
7450 int result = adapter->Send();
7451 EXPECT_EQ(0, result);
7452 EXPECT_THAT(
7453 visitor.data(),
7454 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::RST_STREAM,
7455 SpdyFrameType::RST_STREAM, SpdyFrameType::RST_STREAM}));
7456 }
7457
TEST(NgHttp2AdapterTest,ServerHandlesTeHeader)7458 TEST(NgHttp2AdapterTest, ServerHandlesTeHeader) {
7459 DataSavingVisitor visitor;
7460 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
7461
7462 testing::InSequence s;
7463
7464 const std::string stream_frames = TestFrameSequence()
7465 .ClientPreface()
7466 .Headers(1,
7467 {{":scheme", "https"},
7468 {":authority", "example.com"},
7469 {":path", "/"},
7470 {":method", "GET"},
7471 {"te", "trailers"}},
7472 /*fin=*/true)
7473 .Headers(3,
7474 {{":scheme", "https"},
7475 {":authority", "example.com"},
7476 {":path", "/"},
7477 {":method", "GET"},
7478 {"te", "trailers, deflate"}},
7479 /*fin=*/true)
7480 .Serialize();
7481
7482 // Client preface (empty SETTINGS)
7483 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
7484 EXPECT_CALL(visitor, OnSettingsStart());
7485 EXPECT_CALL(visitor, OnSettingsEnd());
7486
7487 // Stream 1: TE: trailers should be allowed.
7488 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
7489 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
7490 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(5);
7491 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
7492 EXPECT_CALL(visitor, OnEndStream(1));
7493
7494 // Stream 3: TE: <non-trailers> should be rejected.
7495 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 5));
7496 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
7497 EXPECT_CALL(visitor, OnHeaderForStream(3, _, _)).Times(4);
7498 EXPECT_CALL(
7499 visitor,
7500 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
7501 "stream: 3, name: [te], value: [trailers, deflate]"));
7502 EXPECT_CALL(
7503 visitor,
7504 OnInvalidFrame(3, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
7505
7506 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
7507 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
7508
7509 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
7510 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
7511 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 3, _, 0x0));
7512 EXPECT_CALL(visitor,
7513 OnFrameSent(RST_STREAM, 3, _, 0x0,
7514 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7515 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::PROTOCOL_ERROR));
7516
7517 EXPECT_TRUE(adapter->want_write());
7518 int result = adapter->Send();
7519 EXPECT_EQ(0, result);
7520 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
7521 SpdyFrameType::RST_STREAM}));
7522 }
7523
TEST(NgHttp2AdapterTest,ServerHandlesConnectionSpecificHeaders)7524 TEST(NgHttp2AdapterTest, ServerHandlesConnectionSpecificHeaders) {
7525 DataSavingVisitor visitor;
7526 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
7527
7528 testing::InSequence s;
7529
7530 const std::string stream_frames =
7531 TestFrameSequence()
7532 .ClientPreface()
7533 .Headers(1,
7534 {{":scheme", "https"},
7535 {":authority", "example.com"},
7536 {":path", "/"},
7537 {":method", "GET"},
7538 {"connection", "keep-alive"}},
7539 /*fin=*/true)
7540 .Headers(3,
7541 {{":scheme", "https"},
7542 {":authority", "example.com"},
7543 {":path", "/"},
7544 {":method", "GET"},
7545 {"proxy-connection", "keep-alive"}},
7546 /*fin=*/true)
7547 .Headers(5,
7548 {{":scheme", "https"},
7549 {":authority", "example.com"},
7550 {":path", "/"},
7551 {":method", "GET"},
7552 {"keep-alive", "timeout=42"}},
7553 /*fin=*/true)
7554 .Headers(7,
7555 {{":scheme", "https"},
7556 {":authority", "example.com"},
7557 {":path", "/"},
7558 {":method", "GET"},
7559 {"transfer-encoding", "chunked"}},
7560 /*fin=*/true)
7561 .Headers(9,
7562 {{":scheme", "https"},
7563 {":authority", "example.com"},
7564 {":path", "/"},
7565 {":method", "GET"},
7566 {"upgrade", "h2c"}},
7567 /*fin=*/true)
7568 .Serialize();
7569
7570 // Client preface (empty SETTINGS)
7571 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
7572 EXPECT_CALL(visitor, OnSettingsStart());
7573 EXPECT_CALL(visitor, OnSettingsEnd());
7574
7575 // All streams contain a connection-specific header and should be rejected.
7576 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
7577 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
7578 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
7579 EXPECT_CALL(
7580 visitor,
7581 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
7582 "stream: 1, name: [connection], value: [keep-alive]"));
7583 EXPECT_CALL(
7584 visitor,
7585 OnInvalidFrame(1, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
7586 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 5));
7587 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
7588 EXPECT_CALL(visitor, OnHeaderForStream(3, _, _)).Times(4);
7589 EXPECT_CALL(
7590 visitor,
7591 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
7592 "stream: 3, name: [proxy-connection], value: [keep-alive]"));
7593 EXPECT_CALL(
7594 visitor,
7595 OnInvalidFrame(3, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
7596 EXPECT_CALL(visitor, OnFrameHeader(5, _, HEADERS, 5));
7597 EXPECT_CALL(visitor, OnBeginHeadersForStream(5));
7598 EXPECT_CALL(visitor, OnHeaderForStream(5, _, _)).Times(4);
7599 EXPECT_CALL(
7600 visitor,
7601 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
7602 "stream: 5, name: [keep-alive], value: [timeout=42]"));
7603 EXPECT_CALL(
7604 visitor,
7605 OnInvalidFrame(5, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
7606 EXPECT_CALL(visitor, OnFrameHeader(7, _, HEADERS, 5));
7607 EXPECT_CALL(visitor, OnBeginHeadersForStream(7));
7608 EXPECT_CALL(visitor, OnHeaderForStream(7, _, _)).Times(4);
7609 EXPECT_CALL(
7610 visitor,
7611 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
7612 "stream: 7, name: [transfer-encoding], value: [chunked]"));
7613 EXPECT_CALL(
7614 visitor,
7615 OnInvalidFrame(7, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
7616 EXPECT_CALL(visitor, OnFrameHeader(9, _, HEADERS, 5));
7617 EXPECT_CALL(visitor, OnBeginHeadersForStream(9));
7618 EXPECT_CALL(visitor, OnHeaderForStream(9, _, _)).Times(4);
7619 EXPECT_CALL(
7620 visitor,
7621 OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
7622 "stream: 9, name: [upgrade], value: [h2c]"));
7623 EXPECT_CALL(
7624 visitor,
7625 OnInvalidFrame(9, Http2VisitorInterface::InvalidFrameError::kHttpHeader));
7626
7627 const int64_t stream_result = adapter->ProcessBytes(stream_frames);
7628 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
7629
7630 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
7631 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
7632 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, _, 0x0));
7633 EXPECT_CALL(visitor,
7634 OnFrameSent(RST_STREAM, 1, _, 0x0,
7635 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7636 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
7637 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 3, _, 0x0));
7638 EXPECT_CALL(visitor,
7639 OnFrameSent(RST_STREAM, 3, _, 0x0,
7640 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7641 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::PROTOCOL_ERROR));
7642 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 5, _, 0x0));
7643 EXPECT_CALL(visitor,
7644 OnFrameSent(RST_STREAM, 5, _, 0x0,
7645 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7646 EXPECT_CALL(visitor, OnCloseStream(5, Http2ErrorCode::PROTOCOL_ERROR));
7647 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 7, _, 0x0));
7648 EXPECT_CALL(visitor,
7649 OnFrameSent(RST_STREAM, 7, _, 0x0,
7650 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7651 EXPECT_CALL(visitor, OnCloseStream(7, Http2ErrorCode::PROTOCOL_ERROR));
7652 EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 9, _, 0x0));
7653 EXPECT_CALL(visitor,
7654 OnFrameSent(RST_STREAM, 9, _, 0x0,
7655 static_cast<int>(Http2ErrorCode::PROTOCOL_ERROR)));
7656 EXPECT_CALL(visitor, OnCloseStream(9, Http2ErrorCode::PROTOCOL_ERROR));
7657
7658 EXPECT_TRUE(adapter->want_write());
7659 int result = adapter->Send();
7660 EXPECT_EQ(0, result);
7661 EXPECT_THAT(
7662 visitor.data(),
7663 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::RST_STREAM,
7664 SpdyFrameType::RST_STREAM, SpdyFrameType::RST_STREAM,
7665 SpdyFrameType::RST_STREAM, SpdyFrameType::RST_STREAM}));
7666 }
7667
TEST(OgHttp2AdapterTest,ServerConsumesDataWithPadding)7668 TEST(OgHttp2AdapterTest, ServerConsumesDataWithPadding) {
7669 DataSavingVisitor visitor;
7670 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
7671
7672 TestFrameSequence seq = std::move(TestFrameSequence().ClientPreface().Headers(
7673 1,
7674 {{":method", "POST"},
7675 {":scheme", "https"},
7676 {":authority", "example.com"},
7677 {":path", "/this/is/request/one"}},
7678 /*fin=*/false));
7679 // Generates a bunch of DATA frames, with the bulk of the payloads consisting
7680 // of padding.
7681 size_t total_size = 0;
7682 while (total_size < 62 * 1024) {
7683 seq.Data(1, "a", /*fin=*/false, /*padding=*/254);
7684 total_size += 255;
7685 }
7686 const std::string frames = seq.Serialize();
7687
7688 // Client preface (empty SETTINGS)
7689 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
7690 EXPECT_CALL(visitor, OnSettingsStart());
7691 EXPECT_CALL(visitor, OnSettingsEnd());
7692
7693 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
7694 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
7695 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
7696 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
7697 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0x8))
7698 .Times(testing::AtLeast(1));
7699 EXPECT_CALL(visitor, OnBeginDataForStream(1, _)).Times(testing::AtLeast(1));
7700 EXPECT_CALL(visitor, OnDataForStream(1, "a")).Times(testing::AtLeast(1));
7701 EXPECT_CALL(visitor, OnDataPaddingLength(1, _)).Times(testing::AtLeast(1));
7702
7703 const int64_t result = adapter->ProcessBytes(frames);
7704 EXPECT_EQ(result, frames.size());
7705
7706 EXPECT_TRUE(adapter->want_write());
7707
7708 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, ACK_FLAG));
7709 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, ACK_FLAG, 0));
7710 // Since most of the flow control window consumed is padding, the adapter
7711 // generates window updates.
7712 EXPECT_CALL(visitor, OnBeforeFrameSent(WINDOW_UPDATE, 1, _, 0x0)).Times(1);
7713 EXPECT_CALL(visitor, OnFrameSent(WINDOW_UPDATE, 1, _, 0x0, 0)).Times(1);
7714 EXPECT_CALL(visitor, OnBeforeFrameSent(WINDOW_UPDATE, 0, _, 0x0)).Times(1);
7715 EXPECT_CALL(visitor, OnFrameSent(WINDOW_UPDATE, 0, _, 0x0, 0)).Times(1);
7716
7717 const int send_result = adapter->Send();
7718 EXPECT_EQ(0, send_result);
7719 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS,
7720 SpdyFrameType::WINDOW_UPDATE,
7721 SpdyFrameType::WINDOW_UPDATE}));
7722 }
7723
TEST(NgHttp2AdapterTest,NegativeFlowControlStreamResumption)7724 TEST(NgHttp2AdapterTest, NegativeFlowControlStreamResumption) {
7725 DataSavingVisitor visitor;
7726 auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
7727
7728 const std::string frames =
7729 TestFrameSequence()
7730 .ClientPreface({{INITIAL_WINDOW_SIZE, 128u * 1024u}})
7731 .WindowUpdate(0, 1 << 20)
7732 .Headers(1,
7733 {{":method", "GET"},
7734 {":scheme", "https"},
7735 {":authority", "example.com"},
7736 {":path", "/this/is/request/one"}},
7737 /*fin=*/true)
7738 .Serialize();
7739 testing::InSequence s;
7740
7741 // Client preface (empty SETTINGS)
7742 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
7743 EXPECT_CALL(visitor, OnSettingsStart());
7744 EXPECT_CALL(visitor,
7745 OnSetting(Http2Setting{Http2KnownSettingsId::INITIAL_WINDOW_SIZE,
7746 128u * 1024u}));
7747 EXPECT_CALL(visitor, OnSettingsEnd());
7748
7749 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
7750 EXPECT_CALL(visitor, OnWindowUpdate(0, 1 << 20));
7751
7752 // Stream 1
7753 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x5));
7754 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
7755 EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
7756 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
7757 EXPECT_CALL(visitor, OnEndStream(1));
7758
7759 const int64_t read_result = adapter->ProcessBytes(frames);
7760 EXPECT_EQ(static_cast<size_t>(read_result), frames.size());
7761
7762 // Submit a response for the stream.
7763 auto body = std::make_unique<TestDataFrameSource>(visitor, true);
7764 TestDataFrameSource& body_ref = *body;
7765 body_ref.AppendPayload(std::string(70000, 'a'));
7766 int submit_result = adapter->SubmitResponse(
7767 1, ToHeaders({{":status", "200"}}), std::move(body));
7768 ASSERT_EQ(0, submit_result);
7769
7770 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
7771 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
7772 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
7773 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
7774 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0)).Times(5);
7775
7776 adapter->Send();
7777 EXPECT_FALSE(adapter->want_write());
7778
7779 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
7780 EXPECT_CALL(visitor, OnSettingsStart());
7781 EXPECT_CALL(visitor,
7782 OnSetting(Http2Setting{Http2KnownSettingsId::INITIAL_WINDOW_SIZE,
7783 64u * 1024u}));
7784 EXPECT_CALL(visitor, OnSettingsEnd());
7785
7786 // Processing these SETTINGS will cause stream 1's send window to become
7787 // negative.
7788 adapter->ProcessBytes(TestFrameSequence()
7789 .Settings({{INITIAL_WINDOW_SIZE, 64u * 1024u}})
7790 .Serialize());
7791 EXPECT_TRUE(adapter->want_write());
7792 // nghttp2 does not expose the fact that the send window size is negative.
7793 EXPECT_EQ(adapter->GetStreamSendWindowSize(1), 0);
7794
7795 body_ref.AppendPayload("Stream should be resumed.");
7796 adapter->ResumeStream(1);
7797
7798 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
7799 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
7800 adapter->Send();
7801 EXPECT_FALSE(adapter->want_write());
7802
7803 // Upon receiving the WINDOW_UPDATE, stream 1 should be ready to write.
7804 EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
7805 EXPECT_CALL(visitor, OnWindowUpdate(1, 10000));
7806 adapter->ProcessBytes(TestFrameSequence().WindowUpdate(1, 10000).Serialize());
7807 EXPECT_TRUE(adapter->want_write());
7808 EXPECT_GT(adapter->GetStreamSendWindowSize(1), 0);
7809
7810 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
7811 adapter->Send();
7812 }
7813
7814 } // namespace
7815 } // namespace test
7816 } // namespace adapter
7817 } // namespace http2
7818