1 #include "quiche/http2/adapter/oghttp2_session.h"
2
3 #include <memory>
4
5 #include "quiche/http2/adapter/mock_http2_visitor.h"
6 #include "quiche/http2/adapter/test_frame_sequence.h"
7 #include "quiche/http2/adapter/test_utils.h"
8 #include "quiche/common/platform/api/quiche_test.h"
9
10 namespace http2 {
11 namespace adapter {
12 namespace test {
13 namespace {
14
15 using spdy::SpdyFrameType;
16 using testing::_;
17
18 enum FrameType {
19 DATA,
20 HEADERS,
21 PRIORITY,
22 RST_STREAM,
23 SETTINGS,
24 PUSH_PROMISE,
25 PING,
26 GOAWAY,
27 WINDOW_UPDATE,
28 };
29
30 } // namespace
31
TEST(OgHttp2SessionTest,ClientConstruction)32 TEST(OgHttp2SessionTest, ClientConstruction) {
33 testing::StrictMock<MockHttp2Visitor> visitor;
34 OgHttp2Session::Options options;
35 options.perspective = Perspective::kClient;
36 OgHttp2Session session(visitor, options);
37 EXPECT_TRUE(session.want_read());
38 EXPECT_FALSE(session.want_write());
39 EXPECT_EQ(session.GetRemoteWindowSize(), kInitialFlowControlWindowSize);
40 EXPECT_FALSE(session.IsServerSession());
41 EXPECT_EQ(0, session.GetHighestReceivedStreamId());
42 EXPECT_EQ(100u, session.GetMaxOutboundConcurrentStreams());
43 }
44
TEST(OgHttp2SessionTest,ClientConstructionWithMaxStreams)45 TEST(OgHttp2SessionTest, ClientConstructionWithMaxStreams) {
46 testing::StrictMock<MockHttp2Visitor> visitor;
47 OgHttp2Session::Options options;
48 options.perspective = Perspective::kClient;
49 options.remote_max_concurrent_streams = 200u;
50 OgHttp2Session session(visitor, options);
51 EXPECT_EQ(200u, session.GetMaxOutboundConcurrentStreams());
52 }
53
TEST(OgHttp2SessionTest,ClientHandlesFrames)54 TEST(OgHttp2SessionTest, ClientHandlesFrames) {
55 testing::StrictMock<MockHttp2Visitor> visitor;
56 OgHttp2Session::Options options;
57 options.perspective = Perspective::kClient;
58 OgHttp2Session session(visitor, options);
59
60 const std::string initial_frames = TestFrameSequence()
61 .ServerPreface()
62 .Ping(42)
63 .WindowUpdate(0, 1000)
64 .Serialize();
65 testing::InSequence s;
66
67 // Server preface (empty SETTINGS)
68 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
69 EXPECT_CALL(visitor, OnSettingsStart());
70 EXPECT_CALL(visitor, OnSettingsEnd());
71
72 EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
73 EXPECT_CALL(visitor, OnPing(42, false));
74 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
75 EXPECT_CALL(visitor, OnWindowUpdate(0, 1000));
76
77 const int64_t initial_result = session.ProcessBytes(initial_frames);
78 EXPECT_EQ(initial_frames.size(), static_cast<size_t>(initial_result));
79
80 EXPECT_EQ(session.GetRemoteWindowSize(),
81 kInitialFlowControlWindowSize + 1000);
82 EXPECT_EQ(0, session.GetHighestReceivedStreamId());
83
84 // Connection has not yet received any data.
85 EXPECT_EQ(kInitialFlowControlWindowSize, session.GetReceiveWindowSize());
86
87 EXPECT_EQ(0, session.GetHpackDecoderDynamicTableSize());
88
89 // Submit a request to ensure the first stream is created.
90 const char* kSentinel1 = "arbitrary pointer 1";
91 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
92 body1->AppendPayload("This is an example request body.");
93 body1->EndData();
94 int stream_id =
95 session.SubmitRequest(ToHeaders({{":method", "POST"},
96 {":scheme", "http"},
97 {":authority", "example.com"},
98 {":path", "/this/is/request/one"}}),
99 std::move(body1), const_cast<char*>(kSentinel1));
100 EXPECT_EQ(stream_id, 1);
101
102 // Submit another request to ensure the next stream is created.
103 int stream_id2 =
104 session.SubmitRequest(ToHeaders({{":method", "GET"},
105 {":scheme", "http"},
106 {":authority", "example.com"},
107 {":path", "/this/is/request/two"}}),
108 nullptr, nullptr);
109 EXPECT_EQ(stream_id2, 3);
110
111 const std::string stream_frames =
112 TestFrameSequence()
113 .Headers(stream_id,
114 {{":status", "200"},
115 {"server", "my-fake-server"},
116 {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
117 /*fin=*/false)
118 .Data(stream_id, "This is the response body.")
119 .RstStream(stream_id2, Http2ErrorCode::INTERNAL_ERROR)
120 .GoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!")
121 .Serialize();
122
123 EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 4));
124 EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
125 EXPECT_CALL(visitor, OnHeaderForStream(stream_id, ":status", "200"));
126 EXPECT_CALL(visitor,
127 OnHeaderForStream(stream_id, "server", "my-fake-server"));
128 EXPECT_CALL(visitor, OnHeaderForStream(stream_id, "date",
129 "Tue, 6 Apr 2021 12:54:01 GMT"));
130 EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
131 EXPECT_CALL(visitor, OnFrameHeader(stream_id, 26, DATA, 0));
132 EXPECT_CALL(visitor, OnBeginDataForStream(stream_id, 26));
133 EXPECT_CALL(visitor,
134 OnDataForStream(stream_id, "This is the response body."));
135 EXPECT_CALL(visitor, OnFrameHeader(stream_id2, 4, RST_STREAM, 0));
136 EXPECT_CALL(visitor, OnRstStream(stream_id2, Http2ErrorCode::INTERNAL_ERROR));
137 EXPECT_CALL(visitor,
138 OnCloseStream(stream_id2, Http2ErrorCode::INTERNAL_ERROR));
139 EXPECT_CALL(visitor, OnFrameHeader(0, 19, GOAWAY, 0));
140 EXPECT_CALL(visitor, OnGoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, ""));
141 const int64_t stream_result = session.ProcessBytes(stream_frames);
142 EXPECT_EQ(stream_frames.size(), static_cast<size_t>(stream_result));
143 EXPECT_EQ(stream_id2, session.GetHighestReceivedStreamId());
144
145 // The first stream is active and has received some data.
146 EXPECT_GT(kInitialFlowControlWindowSize,
147 session.GetStreamReceiveWindowSize(stream_id));
148 // Connection receive window is equivalent to the first stream's.
149 EXPECT_EQ(session.GetReceiveWindowSize(),
150 session.GetStreamReceiveWindowSize(stream_id));
151 // Receive window upper bound is still the initial value.
152 EXPECT_EQ(kInitialFlowControlWindowSize,
153 session.GetStreamReceiveWindowLimit(stream_id));
154
155 EXPECT_GT(session.GetHpackDecoderDynamicTableSize(), 0);
156 }
157
158 // Verifies that a client session enqueues initial SETTINGS if Send() is called
159 // before any frames are explicitly queued.
TEST(OgHttp2SessionTest,ClientEnqueuesSettingsOnSend)160 TEST(OgHttp2SessionTest, ClientEnqueuesSettingsOnSend) {
161 DataSavingVisitor visitor;
162 OgHttp2Session::Options options;
163 options.perspective = Perspective::kClient;
164 OgHttp2Session session(visitor, options);
165 EXPECT_FALSE(session.want_write());
166
167 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
168 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
169
170 int result = session.Send();
171 EXPECT_EQ(0, result);
172 absl::string_view serialized = visitor.data();
173 EXPECT_THAT(serialized,
174 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
175 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
176 EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::SETTINGS}));
177 }
178
179 // Verifies that a client session enqueues initial SETTINGS before whatever
180 // frame type is passed to the first invocation of EnqueueFrame().
TEST(OgHttp2SessionTest,ClientEnqueuesSettingsBeforeOtherFrame)181 TEST(OgHttp2SessionTest, ClientEnqueuesSettingsBeforeOtherFrame) {
182 DataSavingVisitor visitor;
183 OgHttp2Session::Options options;
184 options.perspective = Perspective::kClient;
185 OgHttp2Session session(visitor, options);
186 EXPECT_FALSE(session.want_write());
187 session.EnqueueFrame(std::make_unique<spdy::SpdyPingIR>(42));
188 EXPECT_TRUE(session.want_write());
189
190 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
191 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
192 EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, 8, 0x0));
193 EXPECT_CALL(visitor, OnFrameSent(PING, 0, 8, 0x0, 0));
194
195 int result = session.Send();
196 EXPECT_EQ(0, result);
197 absl::string_view serialized = visitor.data();
198 EXPECT_THAT(serialized,
199 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
200 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
201 EXPECT_THAT(serialized,
202 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::PING}));
203 }
204
205 // Verifies that if the first call to EnqueueFrame() passes a SETTINGS frame,
206 // the client session will not enqueue an additional SETTINGS frame.
TEST(OgHttp2SessionTest,ClientEnqueuesSettingsOnce)207 TEST(OgHttp2SessionTest, ClientEnqueuesSettingsOnce) {
208 DataSavingVisitor visitor;
209 OgHttp2Session::Options options;
210 options.perspective = Perspective::kClient;
211 OgHttp2Session session(visitor, options);
212 EXPECT_FALSE(session.want_write());
213 session.EnqueueFrame(std::make_unique<spdy::SpdySettingsIR>());
214 EXPECT_TRUE(session.want_write());
215
216 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
217 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
218
219 int result = session.Send();
220 EXPECT_EQ(0, result);
221 absl::string_view serialized = visitor.data();
222 EXPECT_THAT(serialized,
223 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
224 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
225 EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::SETTINGS}));
226 }
227
TEST(OgHttp2SessionTest,ClientSubmitRequest)228 TEST(OgHttp2SessionTest, ClientSubmitRequest) {
229 DataSavingVisitor visitor;
230 OgHttp2Session::Options options;
231 options.perspective = Perspective::kClient;
232 OgHttp2Session session(visitor, options);
233
234 EXPECT_FALSE(session.want_write());
235
236 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
237 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
238
239 // Even though the user has not queued any frames for the session, it should
240 // still send the connection preface.
241 int result = session.Send();
242 EXPECT_EQ(0, result);
243 absl::string_view serialized = visitor.data();
244 EXPECT_THAT(serialized,
245 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
246 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
247 // Initial SETTINGS.
248 EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::SETTINGS}));
249 visitor.Clear();
250
251 const std::string initial_frames =
252 TestFrameSequence().ServerPreface().Serialize();
253 testing::InSequence s;
254
255 // Server preface (empty SETTINGS)
256 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
257 EXPECT_CALL(visitor, OnSettingsStart());
258 EXPECT_CALL(visitor, OnSettingsEnd());
259
260 const int64_t initial_result = session.ProcessBytes(initial_frames);
261 EXPECT_EQ(initial_frames.size(), static_cast<size_t>(initial_result));
262
263 // Session will want to write a SETTINGS ack.
264 EXPECT_TRUE(session.want_write());
265
266 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
267 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
268
269 result = session.Send();
270 EXPECT_EQ(0, result);
271 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
272 visitor.Clear();
273
274 EXPECT_EQ(0, session.GetHpackEncoderDynamicTableSize());
275
276 const char* kSentinel1 = "arbitrary pointer 1";
277 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
278 body1->AppendPayload("This is an example request body.");
279 body1->EndData();
280 int stream_id =
281 session.SubmitRequest(ToHeaders({{":method", "POST"},
282 {":scheme", "http"},
283 {":authority", "example.com"},
284 {":path", "/this/is/request/one"}}),
285 std::move(body1), const_cast<char*>(kSentinel1));
286 EXPECT_GT(stream_id, 0);
287 EXPECT_TRUE(session.want_write());
288 EXPECT_EQ(kSentinel1, session.GetStreamUserData(stream_id));
289
290 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
291 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
292 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
293
294 result = session.Send();
295 EXPECT_EQ(0, result);
296 EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS,
297 spdy::SpdyFrameType::DATA}));
298 visitor.Clear();
299 EXPECT_FALSE(session.want_write());
300
301 // Some data was sent, so the remaining send window size should be less than
302 // the default.
303 EXPECT_LT(session.GetStreamSendWindowSize(stream_id),
304 kInitialFlowControlWindowSize);
305 EXPECT_GT(session.GetStreamSendWindowSize(stream_id), 0);
306 // Send window for a nonexistent stream is not available.
307 EXPECT_EQ(-1, session.GetStreamSendWindowSize(stream_id + 2));
308
309 EXPECT_GT(session.GetHpackEncoderDynamicTableSize(), 0);
310
311 stream_id =
312 session.SubmitRequest(ToHeaders({{":method", "POST"},
313 {":scheme", "http"},
314 {":authority", "example.com"},
315 {":path", "/this/is/request/two"}}),
316 nullptr, nullptr);
317 EXPECT_GT(stream_id, 0);
318 EXPECT_TRUE(session.want_write());
319 const char* kSentinel2 = "arbitrary pointer 2";
320 EXPECT_EQ(nullptr, session.GetStreamUserData(stream_id));
321 session.SetStreamUserData(stream_id, const_cast<char*>(kSentinel2));
322 EXPECT_EQ(kSentinel2, session.GetStreamUserData(stream_id));
323
324 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
325 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
326
327 result = session.Send();
328 EXPECT_EQ(0, result);
329 EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS}));
330
331 // No data was sent (just HEADERS), so the remaining send window size should
332 // still be the default.
333 EXPECT_EQ(session.GetStreamSendWindowSize(stream_id),
334 kInitialFlowControlWindowSize);
335 }
336
TEST(OgHttp2SessionTest,ClientSubmitRequestWithLargePayload)337 TEST(OgHttp2SessionTest, ClientSubmitRequestWithLargePayload) {
338 DataSavingVisitor visitor;
339 OgHttp2Session::Options options;
340 options.perspective = Perspective::kClient;
341 OgHttp2Session session(visitor, options);
342
343 EXPECT_FALSE(session.want_write());
344
345 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
346 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
347
348 // Even though the user has not queued any frames for the session, it should
349 // still send the connection preface.
350 int result = session.Send();
351 EXPECT_EQ(0, result);
352 absl::string_view serialized = visitor.data();
353 EXPECT_THAT(serialized,
354 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
355 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
356 // Initial SETTINGS.
357 EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::SETTINGS}));
358 visitor.Clear();
359
360 const std::string initial_frames =
361 TestFrameSequence()
362 .ServerPreface(
363 {Http2Setting{Http2KnownSettingsId::MAX_FRAME_SIZE, 32768u}})
364 .Serialize();
365 testing::InSequence s;
366
367 // Server preface (empty SETTINGS)
368 EXPECT_CALL(visitor, OnFrameHeader(0, 6, SETTINGS, 0));
369 EXPECT_CALL(visitor, OnSettingsStart());
370 EXPECT_CALL(visitor, OnSetting(Http2Setting{
371 Http2KnownSettingsId::MAX_FRAME_SIZE, 32768u}));
372 EXPECT_CALL(visitor, OnSettingsEnd());
373
374 const int64_t initial_result = session.ProcessBytes(initial_frames);
375 EXPECT_EQ(initial_frames.size(), static_cast<size_t>(initial_result));
376
377 // Session will want to write a SETTINGS ack.
378 EXPECT_TRUE(session.want_write());
379
380 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
381 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
382
383 result = session.Send();
384 EXPECT_EQ(0, result);
385 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
386 visitor.Clear();
387
388 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
389 body1->AppendPayload(std::string(20000, 'a'));
390 body1->EndData();
391 int stream_id =
392 session.SubmitRequest(ToHeaders({{":method", "POST"},
393 {":scheme", "http"},
394 {":authority", "example.com"},
395 {":path", "/this/is/request/one"}}),
396 std::move(body1), nullptr);
397 EXPECT_GT(stream_id, 0);
398 EXPECT_TRUE(session.want_write());
399
400 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
401 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
402 // Single DATA frame with fin, indicating all 20k bytes fit in one frame.
403 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
404
405 result = session.Send();
406 EXPECT_EQ(0, result);
407 EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS,
408 spdy::SpdyFrameType::DATA}));
409 visitor.Clear();
410 EXPECT_FALSE(session.want_write());
411 }
412
413 // This test exercises the case where the client request body source is read
414 // blocked.
TEST(OgHttp2SessionTest,ClientSubmitRequestWithReadBlock)415 TEST(OgHttp2SessionTest, ClientSubmitRequestWithReadBlock) {
416 DataSavingVisitor visitor;
417 OgHttp2Session::Options options;
418 options.perspective = Perspective::kClient;
419 OgHttp2Session session(visitor, options);
420 EXPECT_FALSE(session.want_write());
421
422 const char* kSentinel1 = "arbitrary pointer 1";
423 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
424 TestDataFrameSource* body_ref = body1.get();
425 int stream_id =
426 session.SubmitRequest(ToHeaders({{":method", "POST"},
427 {":scheme", "http"},
428 {":authority", "example.com"},
429 {":path", "/this/is/request/one"}}),
430 std::move(body1), const_cast<char*>(kSentinel1));
431 EXPECT_GT(stream_id, 0);
432 EXPECT_TRUE(session.want_write());
433 EXPECT_EQ(kSentinel1, session.GetStreamUserData(stream_id));
434
435 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
436 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
437 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
438 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
439
440 int result = session.Send();
441 EXPECT_EQ(0, result);
442 absl::string_view serialized = visitor.data();
443 EXPECT_THAT(serialized,
444 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
445 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
446 EXPECT_THAT(serialized,
447 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
448 // No data frame, as body1 was read blocked.
449 visitor.Clear();
450 EXPECT_FALSE(session.want_write());
451
452 body_ref->AppendPayload("This is an example request body.");
453 body_ref->EndData();
454 EXPECT_TRUE(session.ResumeStream(stream_id));
455 EXPECT_TRUE(session.want_write());
456
457 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
458
459 result = session.Send();
460 EXPECT_EQ(0, result);
461 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::DATA}));
462 EXPECT_FALSE(session.want_write());
463
464 // Stream data is done, so this stream cannot be resumed.
465 EXPECT_FALSE(session.ResumeStream(stream_id));
466 EXPECT_FALSE(session.want_write());
467 }
468
469 // This test exercises the case where the client request body source is read
470 // blocked, then ends with an empty DATA frame.
TEST(OgHttp2SessionTest,ClientSubmitRequestEmptyDataWithFin)471 TEST(OgHttp2SessionTest, ClientSubmitRequestEmptyDataWithFin) {
472 DataSavingVisitor visitor;
473 OgHttp2Session::Options options;
474 options.perspective = Perspective::kClient;
475 OgHttp2Session session(visitor, options);
476 EXPECT_FALSE(session.want_write());
477
478 const char* kSentinel1 = "arbitrary pointer 1";
479 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
480 TestDataFrameSource* body_ref = body1.get();
481 int stream_id =
482 session.SubmitRequest(ToHeaders({{":method", "POST"},
483 {":scheme", "http"},
484 {":authority", "example.com"},
485 {":path", "/this/is/request/one"}}),
486 std::move(body1), const_cast<char*>(kSentinel1));
487 EXPECT_GT(stream_id, 0);
488 EXPECT_TRUE(session.want_write());
489 EXPECT_EQ(kSentinel1, session.GetStreamUserData(stream_id));
490
491 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
492 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
493 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
494 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
495
496 int result = session.Send();
497 EXPECT_EQ(0, result);
498 absl::string_view serialized = visitor.data();
499 EXPECT_THAT(serialized,
500 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
501 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
502 EXPECT_THAT(serialized,
503 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
504 // No data frame, as body1 was read blocked.
505 visitor.Clear();
506 EXPECT_FALSE(session.want_write());
507
508 body_ref->EndData();
509 EXPECT_TRUE(session.ResumeStream(stream_id));
510 EXPECT_TRUE(session.want_write());
511
512 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, 0, 0x1, 0));
513
514 result = session.Send();
515 EXPECT_EQ(0, result);
516 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::DATA}));
517 EXPECT_FALSE(session.want_write());
518
519 // Stream data is done, so this stream cannot be resumed.
520 EXPECT_FALSE(session.ResumeStream(stream_id));
521 EXPECT_FALSE(session.want_write());
522 }
523
524 // This test exercises the case where the connection to the peer is write
525 // blocked.
TEST(OgHttp2SessionTest,ClientSubmitRequestWithWriteBlock)526 TEST(OgHttp2SessionTest, ClientSubmitRequestWithWriteBlock) {
527 DataSavingVisitor visitor;
528 OgHttp2Session::Options options;
529 options.perspective = Perspective::kClient;
530 OgHttp2Session session(visitor, options);
531 EXPECT_FALSE(session.want_write());
532
533 const char* kSentinel1 = "arbitrary pointer 1";
534 auto body1 = std::make_unique<TestDataFrameSource>(visitor, true);
535 body1->AppendPayload("This is an example request body.");
536 body1->EndData();
537 int stream_id =
538 session.SubmitRequest(ToHeaders({{":method", "POST"},
539 {":scheme", "http"},
540 {":authority", "example.com"},
541 {":path", "/this/is/request/one"}}),
542 std::move(body1), const_cast<char*>(kSentinel1));
543 EXPECT_GT(stream_id, 0);
544 EXPECT_TRUE(session.want_write());
545 EXPECT_EQ(kSentinel1, session.GetStreamUserData(stream_id));
546 visitor.set_is_write_blocked(true);
547 int result = session.Send();
548 EXPECT_EQ(0, result);
549
550 EXPECT_THAT(visitor.data(), testing::IsEmpty());
551 EXPECT_TRUE(session.want_write());
552 visitor.set_is_write_blocked(false);
553
554 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
555 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
556 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
557 EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
558 EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
559
560 result = session.Send();
561 EXPECT_EQ(0, result);
562
563 absl::string_view serialized = visitor.data();
564 EXPECT_THAT(serialized,
565 testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
566 serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
567 EXPECT_THAT(serialized,
568 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS,
569 SpdyFrameType::DATA}));
570 EXPECT_FALSE(session.want_write());
571 }
572
TEST(OgHttp2SessionTest,ServerConstruction)573 TEST(OgHttp2SessionTest, ServerConstruction) {
574 testing::StrictMock<MockHttp2Visitor> visitor;
575 OgHttp2Session::Options options;
576 options.perspective = Perspective::kServer;
577 OgHttp2Session session(visitor, options);
578 EXPECT_TRUE(session.want_read());
579 EXPECT_FALSE(session.want_write());
580 EXPECT_EQ(session.GetRemoteWindowSize(), kInitialFlowControlWindowSize);
581 EXPECT_TRUE(session.IsServerSession());
582 EXPECT_EQ(0, session.GetHighestReceivedStreamId());
583 }
584
TEST(OgHttp2SessionTest,ServerHandlesFrames)585 TEST(OgHttp2SessionTest, ServerHandlesFrames) {
586 DataSavingVisitor visitor;
587 OgHttp2Session::Options options;
588 options.perspective = Perspective::kServer;
589 OgHttp2Session session(visitor, options);
590
591 EXPECT_EQ(0, session.GetHpackDecoderDynamicTableSize());
592
593 const std::string frames = TestFrameSequence()
594 .ClientPreface()
595 .Ping(42)
596 .WindowUpdate(0, 1000)
597 .Headers(1,
598 {{":method", "POST"},
599 {":scheme", "https"},
600 {":authority", "example.com"},
601 {":path", "/this/is/request/one"}},
602 /*fin=*/false)
603 .WindowUpdate(1, 2000)
604 .Data(1, "This is the request body.")
605 .Headers(3,
606 {{":method", "GET"},
607 {":scheme", "http"},
608 {":authority", "example.com"},
609 {":path", "/this/is/request/two"}},
610 /*fin=*/true)
611 .RstStream(3, Http2ErrorCode::CANCEL)
612 .Ping(47)
613 .Serialize();
614 testing::InSequence s;
615
616 const char* kSentinel1 = "arbitrary pointer 1";
617
618 // Client preface (empty SETTINGS)
619 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
620 EXPECT_CALL(visitor, OnSettingsStart());
621 EXPECT_CALL(visitor, OnSettingsEnd());
622
623 EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
624 EXPECT_CALL(visitor, OnPing(42, false));
625 EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
626 EXPECT_CALL(visitor, OnWindowUpdate(0, 1000));
627 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
628 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
629 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
630 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
631 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
632 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
633 EXPECT_CALL(visitor, OnEndHeadersForStream(1))
634 .WillOnce(testing::InvokeWithoutArgs([&session, kSentinel1]() {
635 session.SetStreamUserData(1, const_cast<char*>(kSentinel1));
636 return true;
637 }));
638 EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
639 EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
640 EXPECT_CALL(visitor, OnFrameHeader(1, 25, DATA, 0));
641 EXPECT_CALL(visitor, OnBeginDataForStream(1, 25));
642 EXPECT_CALL(visitor, OnDataForStream(1, "This is the request body."));
643 EXPECT_CALL(visitor, OnFrameHeader(3, _, HEADERS, 5));
644 EXPECT_CALL(visitor, OnBeginHeadersForStream(3));
645 EXPECT_CALL(visitor, OnHeaderForStream(3, ":method", "GET"));
646 EXPECT_CALL(visitor, OnHeaderForStream(3, ":scheme", "http"));
647 EXPECT_CALL(visitor, OnHeaderForStream(3, ":authority", "example.com"));
648 EXPECT_CALL(visitor, OnHeaderForStream(3, ":path", "/this/is/request/two"));
649 EXPECT_CALL(visitor, OnEndHeadersForStream(3));
650 EXPECT_CALL(visitor, OnEndStream(3));
651 EXPECT_CALL(visitor, OnFrameHeader(3, 4, RST_STREAM, 0));
652 EXPECT_CALL(visitor, OnRstStream(3, Http2ErrorCode::CANCEL));
653 EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::CANCEL));
654 EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
655 EXPECT_CALL(visitor, OnPing(47, false));
656
657 const int64_t result = session.ProcessBytes(frames);
658 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
659
660 EXPECT_EQ(kSentinel1, session.GetStreamUserData(1));
661
662 // The first stream is active and has received some data.
663 EXPECT_GT(kInitialFlowControlWindowSize,
664 session.GetStreamReceiveWindowSize(1));
665 // Connection receive window is equivalent to the first stream's.
666 EXPECT_EQ(session.GetReceiveWindowSize(),
667 session.GetStreamReceiveWindowSize(1));
668 // Receive window upper bound is still the initial value.
669 EXPECT_EQ(kInitialFlowControlWindowSize,
670 session.GetStreamReceiveWindowLimit(1));
671
672 EXPECT_GT(session.GetHpackDecoderDynamicTableSize(), 0);
673
674 // It should no longer be possible to set user data on a closed stream.
675 const char* kSentinel3 = "another arbitrary pointer";
676 session.SetStreamUserData(3, const_cast<char*>(kSentinel3));
677 EXPECT_EQ(nullptr, session.GetStreamUserData(3));
678
679 EXPECT_EQ(session.GetRemoteWindowSize(),
680 kInitialFlowControlWindowSize + 1000);
681 EXPECT_EQ(3, session.GetHighestReceivedStreamId());
682
683 EXPECT_TRUE(session.want_write());
684
685 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
686 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
687 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
688 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
689 EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, _, 0x1));
690 EXPECT_CALL(visitor, OnFrameSent(PING, 0, _, 0x1, 0));
691 EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, _, 0x1));
692 EXPECT_CALL(visitor, OnFrameSent(PING, 0, _, 0x1, 0));
693
694 // Some bytes should have been serialized.
695 int send_result = session.Send();
696 EXPECT_EQ(0, send_result);
697 // Initial SETTINGS, SETTINGS ack, and PING acks (for PING IDs 42 and 47).
698 EXPECT_THAT(visitor.data(),
699 EqualsFrames(
700 {spdy::SpdyFrameType::SETTINGS, spdy::SpdyFrameType::SETTINGS,
701 spdy::SpdyFrameType::PING, spdy::SpdyFrameType::PING}));
702 }
703
704 // Verifies that a server session enqueues initial SETTINGS before whatever
705 // frame type is passed to the first invocation of EnqueueFrame().
TEST(OgHttp2SessionTest,ServerEnqueuesSettingsBeforeOtherFrame)706 TEST(OgHttp2SessionTest, ServerEnqueuesSettingsBeforeOtherFrame) {
707 DataSavingVisitor visitor;
708 OgHttp2Session::Options options;
709 options.perspective = Perspective::kServer;
710 OgHttp2Session session(visitor, options);
711 EXPECT_FALSE(session.want_write());
712 session.EnqueueFrame(std::make_unique<spdy::SpdyPingIR>(42));
713 EXPECT_TRUE(session.want_write());
714
715 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
716 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
717 EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, _, 0x0));
718 EXPECT_CALL(visitor, OnFrameSent(PING, 0, _, 0x0, 0));
719
720 int result = session.Send();
721 EXPECT_EQ(0, result);
722 EXPECT_THAT(visitor.data(),
723 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::PING}));
724 }
725
726 // Verifies that if the first call to EnqueueFrame() passes a SETTINGS frame,
727 // the server session will not enqueue an additional SETTINGS frame.
TEST(OgHttp2SessionTest,ServerEnqueuesSettingsOnce)728 TEST(OgHttp2SessionTest, ServerEnqueuesSettingsOnce) {
729 DataSavingVisitor visitor;
730 OgHttp2Session::Options options;
731 options.perspective = Perspective::kServer;
732 OgHttp2Session session(visitor, options);
733 EXPECT_FALSE(session.want_write());
734 session.EnqueueFrame(std::make_unique<spdy::SpdySettingsIR>());
735 EXPECT_TRUE(session.want_write());
736
737 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
738 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
739
740 int result = session.Send();
741 EXPECT_EQ(0, result);
742 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
743 }
744
TEST(OgHttp2SessionTest,ServerSubmitResponse)745 TEST(OgHttp2SessionTest, ServerSubmitResponse) {
746 DataSavingVisitor visitor;
747 OgHttp2Session::Options options;
748 options.perspective = Perspective::kServer;
749 OgHttp2Session session(visitor, options);
750
751 EXPECT_FALSE(session.want_write());
752
753 const std::string frames = TestFrameSequence()
754 .ClientPreface()
755 .Headers(1,
756 {{":method", "GET"},
757 {":scheme", "https"},
758 {":authority", "example.com"},
759 {":path", "/this/is/request/one"}},
760 /*fin=*/true)
761 .Serialize();
762 testing::InSequence s;
763
764 const char* kSentinel1 = "arbitrary pointer 1";
765
766 // Client preface (empty SETTINGS)
767 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
768 EXPECT_CALL(visitor, OnSettingsStart());
769 EXPECT_CALL(visitor, OnSettingsEnd());
770 // Stream 1
771 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
772 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
773 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
774 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
775 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
776 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
777 EXPECT_CALL(visitor, OnEndHeadersForStream(1))
778 .WillOnce(testing::InvokeWithoutArgs([&session, kSentinel1]() {
779 session.SetStreamUserData(1, const_cast<char*>(kSentinel1));
780 return true;
781 }));
782 EXPECT_CALL(visitor, OnEndStream(1));
783
784 const int64_t result = session.ProcessBytes(frames);
785 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
786
787 EXPECT_EQ(1, session.GetHighestReceivedStreamId());
788
789 EXPECT_EQ(0, session.GetHpackEncoderDynamicTableSize());
790
791 // Server will want to send initial SETTINGS, and a SETTINGS ack.
792 EXPECT_TRUE(session.want_write());
793
794 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
795 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
796 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
797 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
798
799 int send_result = session.Send();
800 EXPECT_EQ(0, send_result);
801 EXPECT_THAT(visitor.data(),
802 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
803 visitor.Clear();
804
805 EXPECT_FALSE(session.want_write());
806 // A data fin is not sent so that the stream remains open, and the flow
807 // control state can be verified.
808 auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
809 body1->AppendPayload("This is an example response body.");
810 int submit_result = session.SubmitResponse(
811 1,
812 ToHeaders({{":status", "404"},
813 {"x-comment", "I have no idea what you're talking about."}}),
814 std::move(body1));
815 EXPECT_EQ(submit_result, 0);
816 EXPECT_TRUE(session.want_write());
817
818 // Stream user data should have been set successfully after receiving headers.
819 EXPECT_EQ(kSentinel1, session.GetStreamUserData(1));
820 session.SetStreamUserData(1, nullptr);
821 EXPECT_EQ(nullptr, session.GetStreamUserData(1));
822
823 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
824 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
825 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
826
827 send_result = session.Send();
828 EXPECT_EQ(0, send_result);
829 EXPECT_THAT(visitor.data(),
830 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
831 EXPECT_FALSE(session.want_write());
832
833 // Some data was sent, so the remaining send window size should be less than
834 // the default.
835 EXPECT_LT(session.GetStreamSendWindowSize(1), kInitialFlowControlWindowSize);
836 EXPECT_GT(session.GetStreamSendWindowSize(1), 0);
837 // Send window for a nonexistent stream is not available.
838 EXPECT_EQ(session.GetStreamSendWindowSize(3), -1);
839
840 EXPECT_GT(session.GetHpackEncoderDynamicTableSize(), 0);
841 }
842
843 // Tests the case where the server queues trailers after the data stream is
844 // exhausted.
TEST(OgHttp2SessionTest,ServerSendsTrailers)845 TEST(OgHttp2SessionTest, ServerSendsTrailers) {
846 DataSavingVisitor visitor;
847 OgHttp2Session::Options options;
848 options.perspective = Perspective::kServer;
849 OgHttp2Session session(visitor, options);
850
851 EXPECT_FALSE(session.want_write());
852
853 const std::string frames = TestFrameSequence()
854 .ClientPreface()
855 .Headers(1,
856 {{":method", "GET"},
857 {":scheme", "https"},
858 {":authority", "example.com"},
859 {":path", "/this/is/request/one"}},
860 /*fin=*/true)
861 .Serialize();
862 testing::InSequence s;
863
864 // Client preface (empty SETTINGS)
865 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
866 EXPECT_CALL(visitor, OnSettingsStart());
867 EXPECT_CALL(visitor, OnSettingsEnd());
868 // Stream 1
869 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
870 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
871 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
872 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
873 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
874 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
875 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
876 EXPECT_CALL(visitor, OnEndStream(1));
877
878 const int64_t result = session.ProcessBytes(frames);
879 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
880
881 // Server will want to send initial SETTINGS, and a SETTINGS ack.
882 EXPECT_TRUE(session.want_write());
883
884 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
885 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
886 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
887 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
888
889 int send_result = session.Send();
890 EXPECT_EQ(0, send_result);
891 EXPECT_THAT(visitor.data(),
892 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
893 visitor.Clear();
894
895 EXPECT_FALSE(session.want_write());
896
897 // The body source must indicate that the end of the body is not the end of
898 // the stream.
899 auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
900 body1->AppendPayload("This is an example response body.");
901 body1->EndData();
902 int submit_result = session.SubmitResponse(
903 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
904 std::move(body1));
905 EXPECT_EQ(submit_result, 0);
906 EXPECT_TRUE(session.want_write());
907
908 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
909 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
910 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
911
912 send_result = session.Send();
913 EXPECT_EQ(0, send_result);
914 EXPECT_THAT(visitor.data(),
915 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
916 visitor.Clear();
917 EXPECT_FALSE(session.want_write());
918
919 // The body source has been exhausted by the call to Send() above.
920 int trailer_result = session.SubmitTrailer(
921 1, ToHeaders({{"final-status", "a-ok"},
922 {"x-comment", "trailers sure are cool"}}));
923 ASSERT_EQ(trailer_result, 0);
924 EXPECT_TRUE(session.want_write());
925
926 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
927 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
928 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
929
930 send_result = session.Send();
931 EXPECT_EQ(0, send_result);
932 EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
933 }
934
935 // Tests the case where the server queues trailers immediately after headers and
936 // data, and before any writes have taken place.
TEST(OgHttp2SessionTest,ServerQueuesTrailersWithResponse)937 TEST(OgHttp2SessionTest, ServerQueuesTrailersWithResponse) {
938 DataSavingVisitor visitor;
939 OgHttp2Session::Options options;
940 options.perspective = Perspective::kServer;
941 OgHttp2Session session(visitor, options);
942
943 EXPECT_FALSE(session.want_write());
944
945 const std::string frames = TestFrameSequence()
946 .ClientPreface()
947 .Headers(1,
948 {{":method", "GET"},
949 {":scheme", "https"},
950 {":authority", "example.com"},
951 {":path", "/this/is/request/one"}},
952 /*fin=*/true)
953 .Serialize();
954 testing::InSequence s;
955
956 // Client preface (empty SETTINGS)
957 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
958 EXPECT_CALL(visitor, OnSettingsStart());
959 EXPECT_CALL(visitor, OnSettingsEnd());
960 // Stream 1
961 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
962 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
963 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
964 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
965 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
966 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
967 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
968 EXPECT_CALL(visitor, OnEndStream(1));
969
970 const int64_t result = session.ProcessBytes(frames);
971 EXPECT_EQ(frames.size(), static_cast<size_t>(result));
972
973 // Server will want to send initial SETTINGS, and a SETTINGS ack.
974 EXPECT_TRUE(session.want_write());
975
976 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
977 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
978 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
979 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
980
981 int send_result = session.Send();
982 EXPECT_EQ(0, send_result);
983 EXPECT_THAT(visitor.data(),
984 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
985 visitor.Clear();
986
987 EXPECT_FALSE(session.want_write());
988
989 // The body source must indicate that the end of the body is not the end of
990 // the stream.
991 auto body1 = std::make_unique<TestDataFrameSource>(visitor, false);
992 body1->AppendPayload("This is an example response body.");
993 body1->EndData();
994 int submit_result = session.SubmitResponse(
995 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
996 std::move(body1));
997 EXPECT_EQ(submit_result, 0);
998 EXPECT_TRUE(session.want_write());
999 // There has not been a call to Send() yet, so neither headers nor body have
1000 // been written.
1001 int trailer_result = session.SubmitTrailer(
1002 1, ToHeaders({{"final-status", "a-ok"},
1003 {"x-comment", "trailers sure are cool"}}));
1004 ASSERT_EQ(trailer_result, 0);
1005 EXPECT_TRUE(session.want_write());
1006
1007 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
1008 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
1009 EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
1010
1011 EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
1012 EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
1013 EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::HTTP2_NO_ERROR));
1014
1015 send_result = session.Send();
1016 EXPECT_EQ(0, send_result);
1017 EXPECT_THAT(visitor.data(),
1018 EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA,
1019 SpdyFrameType::HEADERS}));
1020 }
1021
TEST(OgHttp2SessionTest,ServerSeesErrorOnEndStream)1022 TEST(OgHttp2SessionTest, ServerSeesErrorOnEndStream) {
1023 DataSavingVisitor visitor;
1024 OgHttp2Session::Options options;
1025 options.perspective = Perspective::kServer;
1026 OgHttp2Session session(visitor, options);
1027
1028 const std::string frames = TestFrameSequence()
1029 .ClientPreface()
1030 .Headers(1,
1031 {{":method", "POST"},
1032 {":scheme", "https"},
1033 {":authority", "example.com"},
1034 {":path", "/"}},
1035 /*fin=*/false)
1036 .Data(1, "Request body", true)
1037 .Serialize();
1038 testing::InSequence s;
1039
1040 // Client preface (empty SETTINGS)
1041 EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
1042 EXPECT_CALL(visitor, OnSettingsStart());
1043 EXPECT_CALL(visitor, OnSettingsEnd());
1044 // Stream 1
1045 EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0x4));
1046 EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
1047 EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
1048 EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
1049 EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
1050 EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/"));
1051 EXPECT_CALL(visitor, OnEndHeadersForStream(1));
1052
1053 EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0x1));
1054 EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
1055 EXPECT_CALL(visitor, OnDataForStream(1, "Request body"));
1056 EXPECT_CALL(visitor, OnEndStream(1)).WillOnce(testing::Return(false));
1057 EXPECT_CALL(
1058 visitor,
1059 OnConnectionError(Http2VisitorInterface::ConnectionError::kParseError));
1060
1061 const int64_t result = session.ProcessBytes(frames);
1062 EXPECT_EQ(/*NGHTTP2_ERR_CALLBACK_FAILURE=*/-902, result);
1063
1064 EXPECT_TRUE(session.want_write());
1065
1066 EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
1067 EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
1068 EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
1069 EXPECT_CALL(
1070 visitor,
1071 OnFrameSent(GOAWAY, 0, _, 0x0,
1072 static_cast<int>(
1073 Http2VisitorInterface::ConnectionError::kParseError)));
1074
1075 int send_result = session.Send();
1076 EXPECT_EQ(0, send_result);
1077 EXPECT_THAT(visitor.data(),
1078 EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::GOAWAY}));
1079 visitor.Clear();
1080
1081 EXPECT_FALSE(session.want_write());
1082 }
1083
1084 } // namespace test
1085 } // namespace adapter
1086 } // namespace http2
1087