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