1 #include "quiche/http2/adapter/oghttp2_adapter.h"
2 
3 #include <cstdint>
4 #include <memory>
5 #include <string>
6 #include <vector>
7 
8 #include "absl/strings/str_join.h"
9 #include "quiche/http2/adapter/http2_protocol.h"
10 #include "quiche/http2/adapter/http2_visitor_interface.h"
11 #include "quiche/http2/adapter/mock_http2_visitor.h"
12 #include "quiche/http2/adapter/oghttp2_util.h"
13 #include "quiche/http2/adapter/test_frame_sequence.h"
14 #include "quiche/http2/adapter/test_utils.h"
15 #include "quiche/common/platform/api/quiche_expect_bug.h"
16 #include "quiche/common/platform/api/quiche_test.h"
17 #include "quiche/spdy/core/http2_header_block.h"
18 
19 namespace http2 {
20 namespace adapter {
21 namespace test {
22 namespace {
23 
24 using ConnectionError = Http2VisitorInterface::ConnectionError;
25 
26 using spdy::SpdyFrameType;
27 using testing::_;
28 
29 enum FrameType {
30   DATA,
31   HEADERS,
32   PRIORITY,
33   RST_STREAM,
34   SETTINGS,
35   PUSH_PROMISE,
36   PING,
37   GOAWAY,
38   WINDOW_UPDATE,
39   CONTINUATION,
40 };
41 
TEST(OgHttp2AdapterTest,ClientHandlesMetadata)42 TEST(OgHttp2AdapterTest, ClientHandlesMetadata) {
43   DataSavingVisitor visitor;
44   OgHttp2Adapter::Options options;
45   options.perspective = Perspective::kClient;
46   auto adapter = OgHttp2Adapter::Create(visitor, options);
47 
48   testing::InSequence s;
49 
50   const std::vector<Header> headers1 =
51       ToHeaders({{":method", "GET"},
52                  {":scheme", "http"},
53                  {":authority", "example.com"},
54                  {":path", "/this/is/request/one"}});
55 
56   const char* kSentinel1 = "arbitrary pointer 1";
57   const int32_t stream_id1 =
58       adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
59   ASSERT_GT(stream_id1, 0);
60   QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
61 
62   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
63   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
64   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _,
65                                          END_STREAM_FLAG | END_HEADERS_FLAG));
66   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _,
67                                    END_STREAM_FLAG | END_HEADERS_FLAG, 0));
68 
69   int result = adapter->Send();
70   EXPECT_EQ(0, result);
71   absl::string_view data = visitor.data();
72   EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
73   data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
74   EXPECT_THAT(data,
75               EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
76   visitor.Clear();
77 
78   const std::string stream_frames =
79       TestFrameSequence()
80           .ServerPreface()
81           .Metadata(0, "Example connection metadata")
82           .Headers(1,
83                    {{":status", "200"},
84                     {"server", "my-fake-server"},
85                     {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
86                    /*fin=*/false)
87           .Metadata(1, "Example stream metadata")
88           .Data(1, "This is the response body.", true)
89           .Serialize();
90 
91   // Server preface (empty SETTINGS)
92   EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
93   EXPECT_CALL(visitor, OnSettingsStart());
94   EXPECT_CALL(visitor, OnSettingsEnd());
95 
96   EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
97   EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
98   EXPECT_CALL(visitor, OnMetadataForStream(0, _));
99   EXPECT_CALL(visitor, OnMetadataEndForStream(0));
100   EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
101   EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
102   EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
103   EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
104   EXPECT_CALL(visitor,
105               OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
106   EXPECT_CALL(visitor, OnEndHeadersForStream(1));
107   EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
108   EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
109   EXPECT_CALL(visitor, OnMetadataForStream(1, _));
110   EXPECT_CALL(visitor, OnMetadataEndForStream(1));
111   EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 1));
112   EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
113   EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
114   EXPECT_CALL(visitor, OnEndStream(1));
115   EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
116 
117   const int64_t stream_result = adapter->ProcessBytes(stream_frames);
118   EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
119 
120   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, ACK_FLAG));
121   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, ACK_FLAG, 0));
122 
123   EXPECT_TRUE(adapter->want_write());
124   result = adapter->Send();
125   EXPECT_EQ(0, result);
126   EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
127 }
128 
TEST(OgHttp2AdapterTest,ClientHandlesMetadataWithEmptyPayload)129 TEST(OgHttp2AdapterTest, ClientHandlesMetadataWithEmptyPayload) {
130   DataSavingVisitor visitor;
131   OgHttp2Adapter::Options options;
132   options.perspective = Perspective::kClient;
133   auto adapter = OgHttp2Adapter::Create(visitor, options);
134 
135   testing::InSequence s;
136 
137   const std::vector<Header> headers1 =
138       ToHeaders({{":method", "GET"},
139                  {":scheme", "http"},
140                  {":authority", "example.com"},
141                  {":path", "/this/is/request/one"}});
142 
143   const int32_t stream_id = adapter->SubmitRequest(headers1, nullptr, nullptr);
144   ASSERT_GT(stream_id, 0);
145 
146   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
147   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
148   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
149                                          END_STREAM_FLAG | END_HEADERS_FLAG));
150   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _,
151                                    END_STREAM_FLAG | END_HEADERS_FLAG, 0));
152 
153   int result = adapter->Send();
154   EXPECT_EQ(0, result);
155   absl::string_view data = visitor.data();
156   EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
157   data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
158   EXPECT_THAT(data,
159               EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
160   visitor.Clear();
161 
162   const std::string stream_frames =
163       TestFrameSequence()
164           .ServerPreface()
165           .Headers(1,
166                    {{":status", "200"},
167                     {"server", "my-fake-server"},
168                     {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
169                    /*fin=*/false)
170           .Metadata(1, "")
171           .Data(1, "This is the response body.", true)
172           .Serialize();
173 
174   // Server preface (empty SETTINGS)
175   EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
176   EXPECT_CALL(visitor, OnSettingsStart());
177   EXPECT_CALL(visitor, OnSettingsEnd());
178 
179   EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
180   EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
181   EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(3);
182   EXPECT_CALL(visitor, OnEndHeadersForStream(1));
183   EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
184   EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
185   EXPECT_CALL(visitor, OnMetadataEndForStream(1));
186   EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 1));
187   EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
188   EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
189   EXPECT_CALL(visitor, OnEndStream(1));
190   EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
191 
192   const int64_t stream_result = adapter->ProcessBytes(stream_frames);
193   EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
194 }
195 
TEST(OgHttp2AdapterTest,ClientHandlesMetadataWithPayloadError)196 TEST(OgHttp2AdapterTest, ClientHandlesMetadataWithPayloadError) {
197   DataSavingVisitor visitor;
198   OgHttp2Adapter::Options options;
199   options.perspective = Perspective::kClient;
200   auto adapter = OgHttp2Adapter::Create(visitor, options);
201 
202   testing::InSequence s;
203 
204   const std::vector<Header> headers =
205       ToHeaders({{":method", "GET"},
206                  {":scheme", "http"},
207                  {":authority", "example.com"},
208                  {":path", "/this/is/request/one"}});
209 
210   const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
211   ASSERT_GT(stream_id, 0);
212 
213   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
214   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
215   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
216                                          END_STREAM_FLAG | END_HEADERS_FLAG));
217   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _,
218                                    END_STREAM_FLAG | END_HEADERS_FLAG, 0));
219 
220   int result = adapter->Send();
221   EXPECT_EQ(0, result);
222   visitor.Clear();
223 
224   const std::string stream_frames =
225       TestFrameSequence()
226           .ServerPreface()
227           .Metadata(0, "Example connection metadata")
228           .Headers(stream_id,
229                    {{":status", "200"},
230                     {"server", "my-fake-server"},
231                     {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
232                    /*fin=*/false)
233           .Metadata(stream_id, "Example stream metadata")
234           .Data(stream_id, "This is the response body.", true)
235           .Serialize();
236 
237   // Server preface (empty SETTINGS)
238   EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
239   EXPECT_CALL(visitor, OnSettingsStart());
240   EXPECT_CALL(visitor, OnSettingsEnd());
241 
242   EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
243   EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
244   EXPECT_CALL(visitor, OnMetadataForStream(0, _));
245   EXPECT_CALL(visitor, OnMetadataEndForStream(0));
246   EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 4));
247   EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
248   EXPECT_CALL(visitor, OnHeaderForStream(stream_id, _, _)).Times(3);
249   EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
250   EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, kMetadataFrameType, 4));
251   EXPECT_CALL(visitor, OnBeginMetadataForStream(stream_id, _));
252   EXPECT_CALL(visitor, OnMetadataForStream(stream_id, _))
253       .WillOnce(testing::Return(false));
254   // Remaining frames are not processed due to the error.
255   EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
256 
257   const int64_t stream_result = adapter->ProcessBytes(stream_frames);
258   // Negative integer returned to indicate an error.
259   EXPECT_LT(stream_result, 0);
260 
261   EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
262   EXPECT_CALL(visitor,
263               OnFrameSent(GOAWAY, 0, _, 0x0,
264                           static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
265 
266   EXPECT_FALSE(adapter->want_read());
267   EXPECT_TRUE(adapter->want_write());
268   result = adapter->Send();
269   EXPECT_EQ(0, result);
270   EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
271 }
272 
TEST(OgHttp2AdapterTest,ClientHandlesMetadataWithCompletionError)273 TEST(OgHttp2AdapterTest, ClientHandlesMetadataWithCompletionError) {
274   DataSavingVisitor visitor;
275   OgHttp2Adapter::Options options;
276   options.perspective = Perspective::kClient;
277   auto adapter = OgHttp2Adapter::Create(visitor, options);
278 
279   testing::InSequence s;
280 
281   const std::vector<Header> headers =
282       ToHeaders({{":method", "GET"},
283                  {":scheme", "http"},
284                  {":authority", "example.com"},
285                  {":path", "/this/is/request/one"}});
286 
287   const int32_t stream_id = adapter->SubmitRequest(headers, nullptr, nullptr);
288   ASSERT_GT(stream_id, 0);
289 
290   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
291   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
292   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _,
293                                          END_STREAM_FLAG | END_HEADERS_FLAG));
294   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _,
295                                    END_STREAM_FLAG | END_HEADERS_FLAG, 0));
296 
297   int result = adapter->Send();
298   EXPECT_EQ(0, result);
299   visitor.Clear();
300 
301   const std::string stream_frames =
302       TestFrameSequence()
303           .ServerPreface()
304           .Metadata(0, "Example connection metadata")
305           .Headers(stream_id,
306                    {{":status", "200"},
307                     {"server", "my-fake-server"},
308                     {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
309                    /*fin=*/false)
310           .Metadata(stream_id, "Example stream metadata")
311           .Data(stream_id, "This is the response body.", true)
312           .Serialize();
313 
314   // Server preface (empty SETTINGS)
315   EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
316   EXPECT_CALL(visitor, OnSettingsStart());
317   EXPECT_CALL(visitor, OnSettingsEnd());
318 
319   EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
320   EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
321   EXPECT_CALL(visitor, OnMetadataForStream(0, _));
322   EXPECT_CALL(visitor, OnMetadataEndForStream(0));
323   EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 4));
324   EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
325   EXPECT_CALL(visitor, OnHeaderForStream(stream_id, _, _)).Times(3);
326   EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
327   EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, kMetadataFrameType, 4));
328   EXPECT_CALL(visitor, OnBeginMetadataForStream(stream_id, _));
329   EXPECT_CALL(visitor, OnMetadataForStream(stream_id, _));
330   EXPECT_CALL(visitor, OnMetadataEndForStream(stream_id))
331       .WillOnce(testing::Return(false));
332   // Remaining frames are not processed due to the error.
333   EXPECT_CALL(visitor, OnConnectionError(ConnectionError::kParseError));
334 
335   const int64_t stream_result = adapter->ProcessBytes(stream_frames);
336   // Negative integer returned to indicate an error.
337   EXPECT_LT(stream_result, 0);
338 
339   EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
340   EXPECT_CALL(visitor,
341               OnFrameSent(GOAWAY, 0, _, 0x0,
342                           static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
343 
344   EXPECT_FALSE(adapter->want_read());
345   EXPECT_TRUE(adapter->want_write());
346   result = adapter->Send();
347   EXPECT_EQ(0, result);
348   EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::GOAWAY}));
349 }
350 
TEST(OgHttp2AdapterTest,ClientSendsMetadataAfterFlowControlBlock)351 TEST(OgHttp2AdapterTest, ClientSendsMetadataAfterFlowControlBlock) {
352   DataSavingVisitor visitor;
353   OgHttp2Adapter::Options options;
354   options.perspective = Perspective::kClient;
355   auto adapter = OgHttp2Adapter::Create(visitor, options);
356 
357   testing::InSequence s;
358 
359   const std::vector<Header> headers1 =
360       ToHeaders({{":method", "GET"},
361                  {":scheme", "http"},
362                  {":authority", "example.com"},
363                  {":path", "/this/is/request/one"}});
364 
365   const std::string kBody = std::string(100 * 1024, 'a');
366   auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
367   body1->AppendPayload(kBody);
368   body1->EndData();
369 
370   const int32_t stream_id1 =
371       adapter->SubmitRequest(headers1, std::move(body1), nullptr);
372   ASSERT_GT(stream_id1, 0);
373 
374   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
375   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
376   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x4));
377   EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x4, 0));
378   // 4 DATA frames should saturate the default 64kB stream/connection flow
379   // control window.
380   EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id1, _, 0x0, 0)).Times(4);
381 
382   int result = adapter->Send();
383   EXPECT_EQ(0, result);
384   EXPECT_FALSE(adapter->want_write());
385   EXPECT_EQ(0, adapter->GetSendWindowSize());
386 
387   auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
388       {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
389   adapter->SubmitMetadata(1, 16384u, std::move(source));
390   EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
391   EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
392 
393   result = adapter->Send();
394   EXPECT_EQ(0, result);
395 }
396 
TEST(OgHttp2AdapterTest,ClientSendsMetadataWithContinuation)397 TEST(OgHttp2AdapterTest, ClientSendsMetadataWithContinuation) {
398   DataSavingVisitor visitor;
399   OgHttp2Adapter::Options options;
400   options.perspective = Perspective::kServer;
401   auto adapter = OgHttp2Adapter::Create(visitor, options);
402   EXPECT_FALSE(adapter->want_write());
403 
404   const std::string frames =
405       TestFrameSequence()
406           .ClientPreface()
407           .Metadata(0, "Example connection metadata in multiple frames", true)
408           .Headers(1,
409                    {{":method", "GET"},
410                     {":scheme", "https"},
411                     {":authority", "example.com"},
412                     {":path", "/this/is/request/one"}},
413                    /*fin=*/false,
414                    /*add_continuation=*/true)
415           .Metadata(1,
416                     "Some stream metadata that's also sent in multiple frames",
417                     true)
418           .Serialize();
419   testing::InSequence s;
420 
421   // Client preface (empty SETTINGS)
422   EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
423   EXPECT_CALL(visitor, OnSettingsStart());
424   EXPECT_CALL(visitor, OnSettingsEnd());
425   // Metadata on stream 0
426   EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 0));
427   EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
428   EXPECT_CALL(visitor, OnMetadataForStream(0, _));
429   EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
430   EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
431   EXPECT_CALL(visitor, OnMetadataForStream(0, _));
432   EXPECT_CALL(visitor, OnMetadataEndForStream(0));
433 
434   // Stream 1
435   EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0));
436   EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
437   EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
438   EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
439   EXPECT_CALL(visitor, OnFrameHeader(1, _, CONTINUATION, 4));
440   EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
441   EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
442   EXPECT_CALL(visitor, OnEndHeadersForStream(1));
443   // Metadata on stream 1
444   EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 0));
445   EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
446   EXPECT_CALL(visitor, OnMetadataForStream(1, _));
447   EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
448   EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
449   EXPECT_CALL(visitor, OnMetadataForStream(1, _));
450   EXPECT_CALL(visitor, OnMetadataEndForStream(1));
451 
452   const int64_t result = adapter->ProcessBytes(frames);
453   EXPECT_EQ(frames.size(), static_cast<size_t>(result));
454   EXPECT_EQ("Example connection metadata in multiple frames",
455             absl::StrJoin(visitor.GetMetadata(0), ""));
456   EXPECT_EQ("Some stream metadata that's also sent in multiple frames",
457             absl::StrJoin(visitor.GetMetadata(1), ""));
458 }
459 
TEST(OgHttp2AdapterTest,SubmitMetadata)460 TEST(OgHttp2AdapterTest, SubmitMetadata) {
461   DataSavingVisitor visitor;
462   OgHttp2Adapter::Options options;
463   options.perspective = Perspective::kServer;
464   auto adapter = OgHttp2Adapter::Create(visitor, options);
465 
466   auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
467       {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
468   adapter->SubmitMetadata(1, 16384u, std::move(source));
469   EXPECT_TRUE(adapter->want_write());
470 
471   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
472   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
473   EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
474   EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
475 
476   int result = adapter->Send();
477   EXPECT_EQ(0, result);
478   EXPECT_THAT(visitor.data(),
479               EqualsFrames({SpdyFrameType::SETTINGS,
480                             static_cast<SpdyFrameType>(kMetadataFrameType)}));
481   EXPECT_FALSE(adapter->want_write());
482 }
483 
TEST(OgHttp2AdapterTest,SubmitMetadataMultipleFrames)484 TEST(OgHttp2AdapterTest, SubmitMetadataMultipleFrames) {
485   DataSavingVisitor visitor;
486   OgHttp2Adapter::Options options;
487   options.perspective = Perspective::kServer;
488   auto adapter = OgHttp2Adapter::Create(visitor, options);
489 
490   const auto kLargeValue = std::string(63 * 1024, 'a');
491   auto source = std::make_unique<TestMetadataSource>(
492       ToHeaderBlock(ToHeaders({{"large-value", kLargeValue}})));
493   adapter->SubmitMetadata(1, 16384u, std::move(source));
494   EXPECT_TRUE(adapter->want_write());
495 
496   testing::InSequence seq;
497   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
498   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
499   EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
500   EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
501   EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
502   EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
503   EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x0));
504   EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x0, 0));
505   EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
506   EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
507 
508   int result = adapter->Send();
509   EXPECT_EQ(0, result);
510   absl::string_view serialized = visitor.data();
511   EXPECT_THAT(serialized,
512               EqualsFrames({SpdyFrameType::SETTINGS,
513                             static_cast<SpdyFrameType>(kMetadataFrameType),
514                             static_cast<SpdyFrameType>(kMetadataFrameType),
515                             static_cast<SpdyFrameType>(kMetadataFrameType),
516                             static_cast<SpdyFrameType>(kMetadataFrameType)}));
517   EXPECT_FALSE(adapter->want_write());
518 }
519 
TEST(OgHttp2AdapterTest,SubmitConnectionMetadata)520 TEST(OgHttp2AdapterTest, SubmitConnectionMetadata) {
521   DataSavingVisitor visitor;
522   OgHttp2Adapter::Options options;
523   options.perspective = Perspective::kServer;
524   auto adapter = OgHttp2Adapter::Create(visitor, options);
525 
526   auto source = std::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
527       {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
528   adapter->SubmitMetadata(0, 16384u, std::move(source));
529   EXPECT_TRUE(adapter->want_write());
530 
531   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
532   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
533   EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 0, _, 0x4));
534   EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 0, _, 0x4, 0));
535 
536   int result = adapter->Send();
537   EXPECT_EQ(0, result);
538   EXPECT_THAT(visitor.data(),
539               EqualsFrames({SpdyFrameType::SETTINGS,
540                             static_cast<SpdyFrameType>(kMetadataFrameType)}));
541   EXPECT_FALSE(adapter->want_write());
542 }
543 
TEST(OgHttp2AdapterTest,ServerQueuesMetadataThenTrailers)544 TEST(OgHttp2AdapterTest, ServerQueuesMetadataThenTrailers) {
545   DataSavingVisitor visitor;
546   OgHttp2Adapter::Options options;
547   options.perspective = Perspective::kServer;
548   auto adapter = OgHttp2Adapter::Create(visitor, options);
549   EXPECT_FALSE(adapter->want_write());
550 
551   const std::string frames = TestFrameSequence()
552                                  .ClientPreface()
553                                  .Headers(1,
554                                           {{":method", "GET"},
555                                            {":scheme", "https"},
556                                            {":authority", "example.com"},
557                                            {":path", "/"}},
558                                           /*fin=*/true)
559                                  .Serialize();
560   testing::InSequence s;
561 
562   // Client preface (empty SETTINGS)
563   EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
564   EXPECT_CALL(visitor, OnSettingsStart());
565   EXPECT_CALL(visitor, OnSettingsEnd());
566   // Stream 1
567   EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
568   EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
569   EXPECT_CALL(visitor, OnHeaderForStream(1, _, _)).Times(4);
570   EXPECT_CALL(visitor, OnEndHeadersForStream(1));
571   EXPECT_CALL(visitor, OnEndStream(1));
572 
573   const int64_t result = adapter->ProcessBytes(frames);
574   EXPECT_EQ(frames.size(), static_cast<size_t>(result));
575 
576   const absl::string_view kBody = "This is an example response body.";
577 
578   // The body source must indicate that the end of the body is not the end of
579   // the stream.
580   auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
581   body1->AppendPayload(kBody);
582   body1->EndData();
583   int submit_result = adapter->SubmitResponse(
584       1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
585       std::move(body1));
586   EXPECT_EQ(submit_result, 0);
587   EXPECT_TRUE(adapter->want_write());
588 
589   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
590   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
591   EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, ACK_FLAG));
592   EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, ACK_FLAG, 0));
593   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
594   EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
595   EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
596 
597   int send_result = adapter->Send();
598   EXPECT_EQ(0, send_result);
599   EXPECT_THAT(visitor.data(),
600               EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS,
601                             SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
602   EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
603   visitor.Clear();
604   EXPECT_FALSE(adapter->want_write());
605 
606   spdy::Http2HeaderBlock block;
607   block["key"] = "wild value!";
608   adapter->SubmitMetadata(
609       1, 16384u, std::make_unique<TestMetadataSource>(std::move(block)));
610 
611   int trailer_result =
612       adapter->SubmitTrailer(1, ToHeaders({{":final-status", "a-ok"}}));
613   ASSERT_EQ(trailer_result, 0);
614   EXPECT_TRUE(adapter->want_write());
615 
616   EXPECT_CALL(visitor, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
617   EXPECT_CALL(visitor, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
618 
619   EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _,
620                                          END_STREAM_FLAG | END_HEADERS_FLAG));
621   EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _,
622                                    END_STREAM_FLAG | END_HEADERS_FLAG, 0));
623 
624   EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
625 
626   send_result = adapter->Send();
627   EXPECT_EQ(0, send_result);
628   EXPECT_THAT(visitor.data(),
629               EqualsFrames({static_cast<SpdyFrameType>(kMetadataFrameType),
630                             SpdyFrameType::HEADERS}));
631 }
632 
633 }  // namespace
634 }  // namespace test
635 }  // namespace adapter
636 }  // namespace http2
637