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