1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #include <proxygen/lib/http/session/test/HQUpstreamSessionTest.h>
10 
11 #include <proxygen/lib/http/codec/CodecUtil.h>
12 #include <proxygen/lib/http/session/HQUpstreamSession.h>
13 
14 #include <folly/futures/Future.h>
15 #include <folly/portability/GTest.h>
16 #include <limits>
17 #include <proxygen/lib/http/HTTPHeaderSize.h>
18 #include <proxygen/lib/http/codec/HQControlCodec.h>
19 #include <proxygen/lib/http/codec/HQStreamCodec.h>
20 #include <proxygen/lib/http/codec/HQUnidirectionalCodec.h>
21 #include <proxygen/lib/http/codec/HTTP1xCodec.h>
22 #include <proxygen/lib/http/codec/test/TestUtils.h>
23 #include <proxygen/lib/http/session/test/HQSessionMocks.h>
24 #include <proxygen/lib/http/session/test/HQSessionTestCommon.h>
25 #include <proxygen/lib/http/session/test/HTTPSessionMocks.h>
26 #include <proxygen/lib/http/session/test/HTTPTransactionMocks.h>
27 #include <proxygen/lib/http/session/test/MockQuicSocketDriver.h>
28 #include <proxygen/lib/http/session/test/TestUtils.h>
29 #include <quic/api/test/MockQuicSocket.h>
30 #include <wangle/acceptor/ConnectionManager.h>
31 
32 using namespace proxygen;
33 using namespace proxygen::hq;
34 using namespace quic;
35 using namespace folly;
36 using namespace testing;
37 using namespace std::chrono;
38 
39 namespace {
40 constexpr quic::StreamId kQPACKEncoderIngressStreamId = 7;
41 constexpr quic::StreamId kQPACKDecoderEgressStreamId = 10;
42 } // namespace
43 
44 std::pair<HTTPCodec::StreamID, std::unique_ptr<HTTPCodec>>
makeCodec(HTTPCodec::StreamID id)45 HQUpstreamSessionTest::makeCodec(HTTPCodec::StreamID id) {
46   if (IS_HQ) {
47     return {id,
48             std::make_unique<hq::HQStreamCodec>(
49                 id,
50                 TransportDirection::DOWNSTREAM,
51                 qpackCodec_,
52                 encoderWriteBuf_,
53                 decoderWriteBuf_,
54                 [] { return std::numeric_limits<uint64_t>::max(); },
55                 ingressSettings_)};
56   } else {
57     auto codec = std::make_unique<HTTP1xCodec>(TransportDirection::DOWNSTREAM);
58     // When the codec is created, need to fake the request
59     FakeHTTPCodecCallback cb;
60     codec->setCallback(&cb);
61     codec->onIngress(*folly::IOBuf::copyBuffer("GET / HTTP/1.1\r\n\r\n"));
62     return {1, std::move(codec)};
63   }
64 }
65 
sendResponse(quic::StreamId id,const HTTPMessage & resp,std::unique_ptr<folly::IOBuf> body,bool eom)66 void HQUpstreamSessionTest::sendResponse(quic::StreamId id,
67                                          const HTTPMessage& resp,
68                                          std::unique_ptr<folly::IOBuf> body,
69                                          bool eom) {
70   auto c = makeCodec(id);
71   auto res =
72       streams_.emplace(std::piecewise_construct,
73                        std::forward_as_tuple(id),
74                        std::forward_as_tuple(c.first, std::move(c.second)));
75   auto& stream = res.first->second;
76   stream.readEOF = eom;
77   stream.codec->generateHeader(
78       stream.buf, stream.codecId, resp, body == nullptr ? eom : false);
79   if (body && body->computeChainDataLength() > 0) {
80     stream.codec->generateBody(
81         stream.buf, stream.codecId, std::move(body), folly::none, eom);
82   }
83 }
84 
sendPartialBody(quic::StreamId id,std::unique_ptr<folly::IOBuf> body,bool eom)85 void HQUpstreamSessionTest::sendPartialBody(quic::StreamId id,
86                                             std::unique_ptr<folly::IOBuf> body,
87                                             bool eom) {
88   auto it = streams_.find(id);
89   CHECK(it != streams_.end());
90   auto& stream = it->second;
91 
92   stream.readEOF = eom;
93   if (body) {
94     stream.codec->generateBody(
95         stream.buf, stream.codecId, std::move(body), folly::none, eom);
96   }
97 }
98 
nextUnidirectionalStreamId()99 quic::StreamId HQUpstreamSessionTest::nextUnidirectionalStreamId() {
100   auto id = nextUnidirectionalStreamId_;
101   nextUnidirectionalStreamId_ += 4;
102   return id;
103 }
104 
SetUp()105 void HQUpstreamSessionTest::SetUp() {
106   HQSessionTest::SetUp();
107   dynamic_cast<HQUpstreamSession*>(hqSession_)->setConnectCallback(&connectCb_);
108 
109   EXPECT_CALL(connectCb_, connectSuccess());
110 
111   hqSession_->onTransportReady();
112 
113   createControlStreams();
114 
115   flushAndLoop();
116   if (IS_HQ) {
117     EXPECT_EQ(httpCallbacks_.settings, 1);
118   }
119 }
120 
TearDown()121 void HQUpstreamSessionTest::TearDown() {
122   if (!IS_H1Q_FB_V1) {
123     // With control streams we may need an extra loop for proper shutdown
124     if (!socketDriver_->isClosed()) {
125       // Send the first GOAWAY with MAX_STREAM_ID immediately
126       sendGoaway(HTTPCodec::MaxStreamID);
127       // Schedule the second GOAWAY with the last seen stream ID, after some
128       // delay
129       sendGoaway(socketDriver_->getMaxStreamId(), milliseconds(50));
130     }
131     eventBase_.loopOnce();
132   }
133 }
134 
sendGoaway(quic::StreamId lastStreamId,milliseconds delay)135 void HQUpstreamSessionTest::sendGoaway(quic::StreamId lastStreamId,
136                                        milliseconds delay) {
137   folly::IOBufQueue writeBuf{folly::IOBufQueue::cacheChainLength()};
138   egressControlCodec_->generateGoaway(
139       writeBuf, lastStreamId, ErrorCode::NO_ERROR);
140   socketDriver_->addReadEvent(connControlStreamId_, writeBuf.move(), delay);
141 }
142 
143 template <class HandlerType>
144 std::unique_ptr<StrictMock<HandlerType>>
openTransactionBase(bool expectStartPaused)145 HQUpstreamSessionTest::openTransactionBase(bool expectStartPaused) {
146   // Returns a mock handler with txn_ field set in it
147   auto handler = std::make_unique<StrictMock<HandlerType>>();
148   handler->expectTransaction();
149   if (expectStartPaused) {
150     handler->expectEgressPaused();
151   }
152   HTTPTransaction* txn = hqSession_->newTransaction(handler.get());
153   EXPECT_EQ(txn, handler->txn_);
154   return handler;
155 }
156 
157 std::unique_ptr<StrictMock<MockHTTPHandler>>
openTransaction()158 HQUpstreamSessionTest::openTransaction() {
159   return openTransactionBase<MockHTTPHandler>();
160 }
161 
flushAndLoop(bool eof,milliseconds eofDelay,milliseconds initialDelay,std::function<void ()> extraEventsFn)162 void HQUpstreamSessionTest::flushAndLoop(bool eof,
163                                          milliseconds eofDelay,
164                                          milliseconds initialDelay,
165                                          std::function<void()> extraEventsFn) {
166   flush(eof, eofDelay, initialDelay, extraEventsFn);
167   CHECK(eventBase_.loop());
168 }
169 
flushAndLoopN(uint64_t n,bool eof,milliseconds eofDelay,milliseconds initialDelay,std::function<void ()> extraEventsFn)170 void HQUpstreamSessionTest::flushAndLoopN(uint64_t n,
171                                           bool eof,
172                                           milliseconds eofDelay,
173                                           milliseconds initialDelay,
174                                           std::function<void()> extraEventsFn) {
175   flush(eof, eofDelay, initialDelay, extraEventsFn);
176   for (uint64_t i = 0; i < n; i++) {
177     eventBase_.loopOnce();
178   }
179 }
180 
flush(bool eof,milliseconds eofDelay,milliseconds initialDelay,std::function<void ()> extraEventsFn)181 bool HQUpstreamSessionTest::flush(bool eof,
182                                   milliseconds eofDelay,
183                                   milliseconds initialDelay,
184                                   std::function<void()> extraEventsFn) {
185   bool done = true;
186   if (!encoderWriteBuf_.empty()) {
187     socketDriver_->addReadEvent(
188         kQPACKEncoderIngressStreamId, encoderWriteBuf_.move(), milliseconds(0));
189   }
190   for (auto& stream : streams_) {
191     if (socketDriver_->isStreamIdle(stream.first)) {
192       continue;
193     }
194     if (stream.second.buf.chainLength() > 0) {
195       socketDriver_->addReadEvent(
196           stream.first, stream.second.buf.move(), initialDelay);
197       done = false;
198     }
199     // EOM -> stream EOF
200     if (stream.second.readEOF) {
201       socketDriver_->addReadEOF(stream.first, eofDelay);
202       done = false;
203     }
204   }
205   if (!socketDriver_->inDatagrams_.empty()) {
206     socketDriver_->addDatagramsAvailableReadEvent(initialDelay);
207   }
208   if (extraEventsFn) {
209     extraEventsFn();
210   }
211   if (eof || eofDelay.count() > 0) {
212     /*  wonkiness.  Should somehow close the connection?
213      * socketDriver_->addReadEOF(1, eofDelay);
214      */
215   }
216   return done;
217 }
218 
getMockController()219 StrictMock<MockController>& HQUpstreamSessionTest::getMockController() {
220   return controllerContainer_.mockController;
221 }
222 
223 // Use this test class for h1q-fb-v1 only tests
224 using HQUpstreamSessionTestH1qv1 = HQUpstreamSessionTest;
225 // Use this test class for h1q-fb-v2 and hq tests
226 using HQUpstreamSessionTestH1qv2HQ = HQUpstreamSessionTest;
227 // Use this test class for hq only tests
228 using HQUpstreamSessionTestHQ = HQUpstreamSessionTest;
229 // Use this test class for hq only tests with qpack encoder streams on/off
230 using HQUpstreamSessionTestQPACK = HQUpstreamSessionTest;
231 // Use this test class for hq only tests with Datagram support
232 using HQUpstreamSessionTestHQDatagram = HQUpstreamSessionTest;
233 
TEST_P(HQUpstreamSessionTest,SimpleGet)234 TEST_P(HQUpstreamSessionTest, SimpleGet) {
235   auto handler = openTransaction();
236   handler->txn_->sendHeaders(getGetRequest());
237   handler->txn_->sendEOM();
238   handler->expectHeaders();
239   handler->expectBody();
240   handler->expectEOM();
241   handler->expectDetachTransaction();
242   auto resp = makeResponse(200, 100);
243   sendResponse(handler->txn_->getID(),
244                *std::get<0>(resp),
245                std::move(std::get<1>(resp)),
246                true);
247   flushAndLoop();
248   hqSession_->closeWhenIdle();
249 }
250 
251 // H1Q does not support trailers, since it requires the messages to use HTTP
252 // chunk encoding
TEST_P(HQUpstreamSessionTestHQ,GetWithTrailers)253 TEST_P(HQUpstreamSessionTestHQ, GetWithTrailers) {
254   auto handler = openTransaction();
255   auto req = getGetRequest();
256   handler->txn_->sendHeaders(req);
257   HTTPHeaders trailers;
258   trailers.add("x-trailer-1", "trailer1");
259   handler->txn_->sendTrailers(trailers);
260   handler->txn_->sendEOM();
261   handler->expectHeaders();
262   handler->expectBody();
263   handler->expectTrailers();
264   handler->expectEOM();
265   handler->expectDetachTransaction();
266   auto resp = makeResponse(200, 100);
267   auto id = handler->txn_->getID();
268   sendResponse(id, *std::get<0>(resp), std::move(std::get<1>(resp)), false);
269   auto it = streams_.find(id);
270   CHECK(it != streams_.end());
271   auto& stream = it->second;
272   trailers.remove("x-trailer-1");
273   trailers.add("x-trailer-2", "trailer2");
274   stream.codec->generateTrailers(stream.buf, stream.codecId, trailers);
275   stream.codec->generateEOM(stream.buf, stream.codecId);
276   stream.readEOF = true;
277   flushAndLoop();
278   hqSession_->closeWhenIdle();
279 }
280 
TEST_P(HQUpstreamSessionTest,PriorityUpdateIntoTransport)281 TEST_P(HQUpstreamSessionTest, PriorityUpdateIntoTransport) {
282   if (IS_HQ) {
283     auto handler = openTransaction();
284     auto req = getGetRequest();
285     req.getHeaders().add(HTTP_HEADER_PRIORITY, "u=3, i");
286     EXPECT_CALL(*socketDriver_->getSocket(), setStreamPriority(_, 3, true));
287     handler->txn_->sendHeadersWithEOM(req);
288 
289     handler->expectHeaders();
290     handler->expectBody();
291     handler->expectEOM();
292     handler->expectDetachTransaction();
293     auto resp = makeResponse(200, 100);
294     std::get<0>(resp)->getHeaders().add(HTTP_HEADER_PRIORITY, "u=5");
295     sendResponse(handler->txn_->getID(),
296                  *std::get<0>(resp),
297                  std::move(std::get<1>(resp)),
298                  true);
299     EXPECT_CALL(*socketDriver_->getSocket(), setStreamPriority(_, 5, false));
300     flushAndLoop();
301   }
302   hqSession_->closeWhenIdle();
303 }
304 
TEST_P(HQUpstreamSessionTest,SendPriorityUpdate)305 TEST_P(HQUpstreamSessionTest, SendPriorityUpdate) {
306   if (IS_HQ) {
307     auto handler = openTransaction();
308     handler->txn_->sendHeaders(getGetRequest());
309     handler->expectHeaders();
310     handler->expectBody([&]() {
311       EXPECT_CALL(*socketDriver_->getSocket(),
312                   setStreamPriority(handler->txn_->getID(), 5, true));
313       handler->txn_->updateAndSendPriority(5, true);
314     });
315     handler->txn_->sendEOM();
316     handler->expectEOM();
317     handler->expectDetachTransaction();
318     auto resp = makeResponse(200, 100);
319     sendResponse(handler->txn_->getID(),
320                  *std::get<0>(resp),
321                  std::move(std::get<1>(resp)),
322                  true);
323     flushAndLoop();
324   }
325   hqSession_->closeWhenIdle();
326 }
327 
TEST_P(HQUpstreamSessionTest,SkipPriorityUpdateAfterSeenEOM)328 TEST_P(HQUpstreamSessionTest, SkipPriorityUpdateAfterSeenEOM) {
329   if (IS_HQ) {
330     auto handler = openTransaction();
331     handler->txn_->sendHeaders(getGetRequest());
332     handler->expectHeaders();
333     handler->expectBody();
334     handler->expectEOM([&]() {
335       EXPECT_CALL(*socketDriver_->getSocket(),
336                   setStreamPriority(handler->txn_->getID(), 5, true))
337           .Times(0);
338       handler->txn_->updateAndSendPriority(5, true);
339     });
340     handler->txn_->sendEOM();
341 
342     handler->expectDetachTransaction();
343     auto resp = makeResponse(200, 100);
344     sendResponse(handler->txn_->getID(),
345                  *std::get<0>(resp),
346                  std::move(std::get<1>(resp)),
347                  true);
348     flushAndLoop();
349   }
350   hqSession_->closeWhenIdle();
351 }
352 
TEST_P(HQUpstreamSessionTest,NoNewTransactionIfSockIsNotGood)353 TEST_P(HQUpstreamSessionTest, NoNewTransactionIfSockIsNotGood) {
354   socketDriver_->sockGood_ = false;
355   EXPECT_EQ(hqSession_->newTransaction(nullptr), nullptr);
356   hqSession_->closeWhenIdle();
357 }
358 
TEST_P(HQUpstreamSessionTest,DropConnectionWithEarlyDataFailedError)359 TEST_P(HQUpstreamSessionTest, DropConnectionWithEarlyDataFailedError) {
360   auto handler = openTransaction();
361   handler->txn_->sendHeaders(getGetRequest());
362   handler->txn_->sendEOM();
363 
364   EXPECT_CALL(*handler, onError(_))
365       .WillOnce(Invoke([](const HTTPException& error) {
366         EXPECT_EQ(error.getProxygenError(), kErrorEarlyDataFailed);
367         EXPECT_TRUE(std::string(error.what()).find("quic loses race") !=
368                     std::string::npos);
369       }));
370   handler->expectDetachTransaction();
371   socketDriver_->deliverConnectionError(
372       {HTTP3::ErrorCode::GIVEUP_ZERO_RTT, "quic loses race"});
373 }
374 
TEST_P(HQUpstreamSessionTest,TestGetHistoricalMaxOutgoingStreams)375 TEST_P(HQUpstreamSessionTest, TestGetHistoricalMaxOutgoingStreams) {
376   EXPECT_EQ(hqSession_->getHistoricalMaxOutgoingStreams(), 0);
377   auto handler = openTransaction();
378   handler->txn_->sendHeaders(getGetRequest());
379   handler->txn_->sendEOM();
380   handler->expectHeaders();
381   handler->expectBody();
382   handler->expectEOM();
383   handler->expectDetachTransaction();
384   auto resp = makeResponse(200, 100);
385   sendResponse(handler->txn_->getID(),
386                *std::get<0>(resp),
387                std::move(std::get<1>(resp)),
388                true);
389   auto handler1 = openTransaction();
390   handler1->txn_->sendHeaders(getGetRequest());
391   handler1->txn_->sendEOM();
392   handler1->expectHeaders();
393   handler1->expectBody();
394   handler1->expectEOM();
395   handler1->expectDetachTransaction();
396   auto resp1 = makeResponse(200, 100);
397   sendResponse(handler1->txn_->getID(),
398                *std::get<0>(resp1),
399                std::move(std::get<1>(resp1)),
400                true);
401   flushAndLoop();
402   EXPECT_EQ(hqSession_->getHistoricalMaxOutgoingStreams(), 2);
403   hqSession_->closeWhenIdle();
404 }
405 
TEST_P(HQUpstreamSessionTest,InjectTraceEvent)406 TEST_P(HQUpstreamSessionTest, InjectTraceEvent) {
407   EXPECT_EQ(hqSession_->getHistoricalMaxOutgoingStreams(), 0);
408 
409   auto handler = openTransaction();
410   handler->expectDetachTransaction();
411 
412   auto handler1 = openTransaction();
413   handler1->expectDetachTransaction();
414 
415   EXPECT_CALL(*handler, traceEventAvailable(_)).Times(1);
416   EXPECT_CALL(*handler1, traceEventAvailable(_)).Times(1);
417 
418   TraceEvent te(TraceEventType::TotalRequest);
419   hqSession_->injectTraceEventIntoAllTransactions(te);
420 
421   handler->txn_->sendAbort();
422   handler1->txn_->sendAbort();
423 
424   flushAndLoop();
425   EXPECT_EQ(hqSession_->getHistoricalMaxOutgoingStreams(), 2);
426   hqSession_->closeWhenIdle();
427 }
428 
TEST_P(HQUpstreamSessionTest,ResponseTermedByFin)429 TEST_P(HQUpstreamSessionTest, ResponseTermedByFin) {
430   auto handler = openTransaction();
431   handler->txn_->sendHeaders(getGetRequest());
432   handler->txn_->sendEOM();
433   handler->expectHeaders();
434   handler->expectBody();
435   handler->expectEOM();
436   handler->expectDetachTransaction();
437   HTTPMessage resp;
438   resp.setStatusCode(200);
439   resp.setHTTPVersion(1, 0);
440   // HTTP/1.0 response with no content-length, termed by tranport FIN
441   sendResponse(handler->txn_->getID(), resp, makeBuf(100), true);
442   flushAndLoop();
443   hqSession_->closeWhenIdle();
444 }
445 
TEST_P(HQUpstreamSessionTest,WaitForReplaySafeCallback)446 TEST_P(HQUpstreamSessionTest, WaitForReplaySafeCallback) {
447   auto handler = openTransaction();
448   StrictMock<folly::test::MockReplaySafetyCallback> cb1;
449   StrictMock<folly::test::MockReplaySafetyCallback> cb2;
450   StrictMock<folly::test::MockReplaySafetyCallback> cb3;
451 
452   auto sock = socketDriver_->getSocket();
453   EXPECT_CALL(*sock, replaySafe()).WillRepeatedly(Return(false));
454   handler->txn_->addWaitingForReplaySafety(&cb1);
455   handler->txn_->addWaitingForReplaySafety(&cb2);
456   handler->txn_->addWaitingForReplaySafety(&cb3);
457   handler->txn_->removeWaitingForReplaySafety(&cb2);
458 
459   ON_CALL(*sock, replaySafe()).WillByDefault(Return(true));
460   EXPECT_CALL(cb1, onReplaySafe_());
461   EXPECT_CALL(cb3, onReplaySafe_());
462   hqSession_->onReplaySafe();
463 
464   handler->expectDetachTransaction();
465   handler->txn_->sendAbort();
466   hqSession_->closeWhenIdle();
467   eventBase_.loopOnce();
468 }
469 
TEST_P(HQUpstreamSessionTest,AlreadyReplaySafe)470 TEST_P(HQUpstreamSessionTest, AlreadyReplaySafe) {
471   auto handler = openTransaction();
472 
473   StrictMock<folly::test::MockReplaySafetyCallback> cb;
474 
475   auto sock = socketDriver_->getSocket();
476   EXPECT_CALL(*sock, replaySafe()).WillRepeatedly(Return(true));
477   EXPECT_CALL(cb, onReplaySafe_());
478   handler->txn_->addWaitingForReplaySafety(&cb);
479 
480   handler->expectDetachTransaction();
481   handler->txn_->sendAbort();
482   hqSession_->closeWhenIdle();
483   eventBase_.loopOnce();
484 }
485 
TEST_P(HQUpstreamSessionTest,Test100Continue)486 TEST_P(HQUpstreamSessionTest, Test100Continue) {
487   InSequence enforceOrder;
488   auto handler = openTransaction();
489   auto req = getPostRequest(10);
490   req.getHeaders().add(HTTP_HEADER_EXPECT, "100-continue");
491   handler->txn_->sendHeaders(req);
492   handler->txn_->sendEOM();
493   handler->expectHeaders();
494   handler->expectHeaders();
495   handler->expectBody();
496   handler->expectEOM();
497   handler->expectDetachTransaction();
498   sendResponse(handler->txn_->getID(), *makeResponse(100), nullptr, false);
499   auto resp = makeResponse(200, 100);
500   sendResponse(handler->txn_->getID(),
501                *std::get<0>(resp),
502                std::move(std::get<1>(resp)),
503                true);
504   flushAndLoop();
505   hqSession_->closeWhenIdle();
506 }
507 
TEST_P(HQUpstreamSessionTest,TestSetIngressTimeoutAfterSendEom)508 TEST_P(HQUpstreamSessionTest, TestSetIngressTimeoutAfterSendEom) {
509   hqSession_->setIngressTimeoutAfterEom(true);
510 
511   // Send EOM separately.
512   auto handler1 = openTransaction();
513   handler1->expectHeaders();
514   handler1->expectBody();
515   handler1->expectEOM();
516   handler1->expectDetachTransaction();
517 
518   auto transaction1 = handler1->txn_;
519   EXPECT_TRUE(transaction1->hasIdleTimeout());
520   transaction1->setIdleTimeout(std::chrono::milliseconds(100));
521   EXPECT_FALSE(transaction1->isScheduled());
522 
523   transaction1->sendHeaders(getPostRequest(10));
524   eventBase_.loopOnce();
525   EXPECT_FALSE(transaction1->isScheduled());
526 
527   transaction1->sendBody(makeBuf(100) /* body */);
528   eventBase_.loopOnce();
529   EXPECT_FALSE(transaction1->isScheduled());
530 
531   transaction1->sendEOM();
532   eventBase_.loopOnce();
533   EXPECT_TRUE(transaction1->isScheduled());
534 
535   auto response1 = makeResponse(200, 100);
536   sendResponse(transaction1->getID(),
537                *std::get<0>(response1),
538                std::move(std::get<1>(response1)),
539                true);
540   flushAndLoop();
541 
542   // Send EOM with header.
543   auto handler2 = openTransaction();
544   handler2->expectHeaders();
545   handler2->expectBody();
546   handler2->expectEOM();
547   handler2->expectDetachTransaction();
548 
549   auto transaction2 = handler2->txn_;
550   EXPECT_FALSE(transaction2->isScheduled());
551   transaction2->sendHeadersWithOptionalEOM(getPostRequest(), true /* eom */);
552   eventBase_.loopOnce();
553   EXPECT_TRUE(transaction2->isScheduled());
554 
555   auto response2 = makeResponse(200, 100);
556   sendResponse(transaction2->getID(),
557                *std::get<0>(response2),
558                std::move(std::get<1>(response2)),
559                true);
560   flushAndLoop();
561 
562   // Send EOM with body.
563   auto handler3 = openTransaction();
564   handler3->expectHeaders();
565   handler3->expectBody();
566   handler3->expectEOM();
567   handler3->expectDetachTransaction();
568 
569   auto transaction3 = handler3->txn_;
570   EXPECT_FALSE(transaction3->isScheduled());
571   transaction3->sendHeaders(getPostRequest());
572   eventBase_.loopOnce();
573   EXPECT_FALSE(transaction3->isScheduled());
574   transaction3->sendBody(makeBuf(100) /* body */);
575   transaction3->sendEOM();
576   eventBase_.loopOnce();
577   EXPECT_TRUE(transaction3->isScheduled());
578 
579   auto response3 = makeResponse(200, 100);
580   sendResponse(transaction3->getID(),
581                *std::get<0>(response3),
582                std::move(std::get<1>(response3)),
583                true);
584   flushAndLoop();
585   hqSession_->closeWhenIdle();
586 }
587 
TEST_P(HQUpstreamSessionTest,GetAddresses)588 TEST_P(HQUpstreamSessionTest, GetAddresses) {
589   EXPECT_EQ(socketDriver_->localAddress_, hqSession_->getLocalAddress());
590   EXPECT_EQ(socketDriver_->peerAddress_, hqSession_->getPeerAddress());
591   hqSession_->dropConnection();
592 }
593 
TEST_P(HQUpstreamSessionTest,GetAddressesFromBase)594 TEST_P(HQUpstreamSessionTest, GetAddressesFromBase) {
595   HTTPSessionBase* sessionBase = dynamic_cast<HTTPSessionBase*>(hqSession_);
596   EXPECT_EQ(socketDriver_->localAddress_, sessionBase->getLocalAddress());
597   EXPECT_EQ(socketDriver_->peerAddress_, sessionBase->getPeerAddress());
598   hqSession_->dropConnection();
599 }
600 
TEST_P(HQUpstreamSessionTest,GetAddressesAfterDropConnection)601 TEST_P(HQUpstreamSessionTest, GetAddressesAfterDropConnection) {
602   HQSession::DestructorGuard dg(hqSession_);
603   hqSession_->dropConnection();
604   EXPECT_EQ(socketDriver_->localAddress_, hqSession_->getLocalAddress());
605   EXPECT_EQ(socketDriver_->peerAddress_, hqSession_->getPeerAddress());
606 }
607 
TEST_P(HQUpstreamSessionTest,DropConnectionTwice)608 TEST_P(HQUpstreamSessionTest, DropConnectionTwice) {
609   HQSession::DestructorGuard dg(hqSession_);
610   hqSession_->closeWhenIdle();
611   hqSession_->dropConnection();
612 }
613 
TEST_P(HQUpstreamSessionTest,DropConnectionTwiceWithPendingStreams)614 TEST_P(HQUpstreamSessionTest, DropConnectionTwiceWithPendingStreams) {
615   folly::IOBufQueue writeBuf{folly::IOBufQueue::cacheChainLength()};
616   socketDriver_->addReadEvent(15, writeBuf.move());
617   flushAndLoopN(1);
618   HQSession::DestructorGuard dg(hqSession_);
619   hqSession_->dropConnection();
620   eventBase_.loopOnce();
621   hqSession_->closeWhenIdle();
622 }
623 
TEST_P(HQUpstreamSessionTest,DropConnectionAfterCloseWhenIdle)624 TEST_P(HQUpstreamSessionTest, DropConnectionAfterCloseWhenIdle) {
625   HQSession::DestructorGuard dg(hqSession_);
626   hqSession_->closeWhenIdle();
627   flushAndLoopN(1);
628   hqSession_->dropConnection();
629 }
630 
TEST_P(HQUpstreamSessionTest,DropConnectionWithStreamAfterCloseWhenIdle)631 TEST_P(HQUpstreamSessionTest, DropConnectionWithStreamAfterCloseWhenIdle) {
632   HQSession::DestructorGuard dg(hqSession_);
633   auto handler = openTransaction();
634   handler->txn_->sendHeaders(getGetRequest());
635   hqSession_->closeWhenIdle();
636   flushAndLoopN(1);
637   handler->expectError([&](const HTTPException& err) {
638     EXPECT_TRUE(err.hasProxygenError());
639     EXPECT_EQ(err.getHttp3ErrorCode(), HTTP3::ErrorCode::HTTP_NO_ERROR);
640   });
641   handler->expectDetachTransaction();
642   hqSession_->dropConnection();
643 }
644 
TEST_P(HQUpstreamSessionTest,NotifyConnectCallbackBeforeDestruct)645 TEST_P(HQUpstreamSessionTest, NotifyConnectCallbackBeforeDestruct) {
646   MockConnectCallback connectCb;
647   dynamic_cast<HQUpstreamSession*>(hqSession_)->setConnectCallback(&connectCb);
648   EXPECT_CALL(connectCb, connectError(_)).Times(1);
649   socketDriver_->deliverConnectionError(
650       {quic::LocalErrorCode::CONNECT_FAILED, "Peer closed"});
651 }
652 
TEST_P(HQUpstreamSessionTest,DropFromConnectError)653 TEST_P(HQUpstreamSessionTest, DropFromConnectError) {
654   MockConnectCallback connectCb;
655   HQUpstreamSession* upstreamSess =
656       dynamic_cast<HQUpstreamSession*>(hqSession_);
657   upstreamSess->setConnectCallback(&connectCb);
658   EXPECT_CALL(connectCb, connectError(_)).WillOnce(InvokeWithoutArgs([&] {
659     hqSession_->dropConnection();
660   }));
661   socketDriver_->addOnConnectionEndEvent(0);
662   eventBase_.loop();
663 }
664 
TEST_P(HQUpstreamSessionTest,FirstPeerPacketProcessed)665 TEST_P(HQUpstreamSessionTest, FirstPeerPacketProcessed) {
666   MockConnectCallback connectCb;
667   HQUpstreamSession* upstreamSess =
668       dynamic_cast<HQUpstreamSession*>(hqSession_);
669   upstreamSess->setConnectCallback(&connectCb);
670   EXPECT_CALL(connectCb, onFirstPeerPacketProcessed());
671   upstreamSess->onFirstPeerPacketProcessed();
672 
673   upstreamSess->closeWhenIdle();
674   eventBase_.loopOnce();
675 }
676 
TEST_P(HQUpstreamSessionTest,NotifyReplaySafeAfterTransportReady)677 TEST_P(HQUpstreamSessionTest, NotifyReplaySafeAfterTransportReady) {
678   MockConnectCallback connectCb;
679   HQUpstreamSession* upstreamSess =
680       dynamic_cast<HQUpstreamSession*>(hqSession_);
681   upstreamSess->setConnectCallback(&connectCb);
682 
683   // onTransportReady gets called in SetUp() already
684 
685   EXPECT_CALL(connectCb, onReplaySafe());
686   upstreamSess->onReplaySafe();
687 
688   upstreamSess->closeWhenIdle();
689   eventBase_.loopOnce();
690 }
691 
TEST_P(HQUpstreamSessionTest,TestConnectionToken)692 TEST_P(HQUpstreamSessionTest, TestConnectionToken) {
693   HQSession::DestructorGuard dg(hqSession_);
694   auto handler = openTransaction();
695   handler->expectError();
696   handler->expectDetachTransaction();
697 
698   // The transaction should not have a connection token
699   // by default.
700   EXPECT_EQ(handler->txn_->getConnectionToken(), folly::none);
701 
702   // Passing connection token to a session should
703   // make it visible to the transaction.
704   HTTPTransaction::ConnectionToken connToken{"TOKEN1234"};
705   hqSession_->setConnectionToken(connToken);
706 
707   EXPECT_NE(handler->txn_->getConnectionToken(), folly::none);
708   EXPECT_EQ(*handler->txn_->getConnectionToken(), connToken);
709 
710   // Clean up the session and the transaction.
711   hqSession_->onConnectionError(
712       std::make_pair(quic::LocalErrorCode::CONNECT_FAILED,
713                      "Connect Failure with Open streams"));
714   eventBase_.loop();
715   EXPECT_EQ(hqSession_->getConnectionCloseReason(),
716             ConnectionCloseReason::SHUTDOWN);
717 }
718 
TEST_P(HQUpstreamSessionTest,OnConnectionErrorWithOpenStreams)719 TEST_P(HQUpstreamSessionTest, OnConnectionErrorWithOpenStreams) {
720   HQSession::DestructorGuard dg(hqSession_);
721   auto handler = openTransaction();
722   handler->expectError();
723   handler->expectDetachTransaction();
724   hqSession_->onConnectionError(
725       std::make_pair(quic::LocalErrorCode::CONNECT_FAILED,
726                      "Connect Failure with Open streams"));
727   eventBase_.loop();
728   EXPECT_EQ(hqSession_->getConnectionCloseReason(),
729             ConnectionCloseReason::SHUTDOWN);
730 }
731 
TEST_P(HQUpstreamSessionTest,OnConnectionErrorWithOpenStreamsPause)732 TEST_P(HQUpstreamSessionTest, OnConnectionErrorWithOpenStreamsPause) {
733   HQSession::DestructorGuard dg(hqSession_);
734   auto handler1 = openTransaction();
735   auto handler2 = openTransaction();
736   handler1->txn_->sendHeaders(getGetRequest());
737   handler1->txn_->sendEOM();
738   handler2->txn_->sendHeaders(getGetRequest());
739   handler2->txn_->sendEOM();
740   auto resp = makeResponse(200, 100);
741   sendResponse(handler1->txn_->getID(),
742                *std::get<0>(resp),
743                std::move(std::get<1>(resp)),
744                true);
745   resp = makeResponse(200, 100);
746   sendResponse(handler2->txn_->getID(),
747                *std::get<0>(resp),
748                std::move(std::get<1>(resp)),
749                true);
750   flush();
751   eventBase_.runInLoop([&] {
752     hqSession_->onConnectionError(
753         std::make_pair(quic::LocalErrorCode::CONNECT_FAILED,
754                        "Connect Failure with Open streams"));
755   });
756   handler1->expectError(
757       [&](const HTTPException&) { handler2->txn_->pauseIngress(); });
758   handler1->expectDetachTransaction();
759   handler2->expectError();
760   handler2->expectDetachTransaction();
761   eventBase_.loop();
762   EXPECT_EQ(hqSession_->getConnectionCloseReason(),
763             ConnectionCloseReason::SHUTDOWN);
764 }
765 
TEST_P(HQUpstreamSessionTest,RejectDelegateSending)766 TEST_P(HQUpstreamSessionTest, RejectDelegateSending) {
767   auto handler = openTransaction();
768   auto dsrRequestSender = std::make_unique<MockDSRRequestSender>();
769   EXPECT_FALSE(handler->txn_->sendHeadersWithDelegate(
770       getGetRequest(), std::move(dsrRequestSender)));
771   handler->expectDetachTransaction();
772   handler->terminate();
773   eventBase_.loop();
774   hqSession_->closeWhenIdle();
775 }
776 
TEST_P(HQUpstreamSessionTestH1qv2HQ,GoawayStreamsUnacknowledged)777 TEST_P(HQUpstreamSessionTestH1qv2HQ, GoawayStreamsUnacknowledged) {
778   std::vector<std::unique_ptr<StrictMock<MockHTTPHandler>>> handlers;
779   auto numStreams = 4;
780   quic::StreamId goawayId = (numStreams * 4) / 2 + 4;
781   for (auto n = 1; n <= numStreams; n++) {
782     handlers.emplace_back(openTransaction());
783     auto handler = handlers.back().get();
784     handler->txn_->sendHeaders(getGetRequest());
785     handler->txn_->sendEOM();
786     EXPECT_CALL(*handler, onGoaway(testing::_)).Times(2);
787     if (handler->txn_->getID() >= goawayId) {
788       handler->expectError([hdlr = handler](const HTTPException& err) {
789         EXPECT_TRUE(err.hasProxygenError());
790         EXPECT_EQ(err.getProxygenError(), kErrorStreamUnacknowledged);
791         ASSERT_EQ(
792             folly::to<std::string>("StreamUnacknowledged on transaction id: ",
793                                    hdlr->txn_->getID()),
794             std::string(err.what()));
795       });
796     } else {
797       handler->expectHeaders();
798       handler->expectBody();
799       handler->expectEOM();
800     }
801 
802     if (n < numStreams) {
803       handler->expectDetachTransaction();
804     } else {
805       handler->expectDetachTransaction([&] {
806         // Make sure the session can't create any more transactions.
807         MockHTTPHandler handler2;
808         EXPECT_EQ(hqSession_->newTransaction(&handler2), nullptr);
809         // Send the responses for the acknowledged streams
810         for (auto& hdlr : handlers) {
811           auto id = hdlr->txn_->getID();
812           if (id < goawayId) {
813             auto resp = makeResponse(200, 100);
814             sendResponse(
815                 id, *std::get<0>(resp), std::move(std::get<1>(resp)), true);
816           }
817         }
818         flush();
819       });
820     }
821   }
822 
823   sendGoaway(HTTPCodec::MaxStreamID, milliseconds(50));
824   sendGoaway(goawayId, milliseconds(100));
825   flushAndLoop();
826 }
827 
TEST_P(HQUpstreamSessionTestHQ,GoawayIncreased)828 TEST_P(HQUpstreamSessionTestHQ, GoawayIncreased) {
829   folly::IOBufQueue writeBuf{folly::IOBufQueue::cacheChainLength()};
830   egressControlCodec_->generateGoaway(writeBuf, 12, ErrorCode::NO_ERROR);
831   socketDriver_->addReadEvent(connControlStreamId_, writeBuf.move());
832   flushAndLoopN(1);
833   proxygen::hq::HQControlCodec egressControlCodec2(
834       nextUnidirectionalStreamId_,
835       proxygen::TransportDirection::DOWNSTREAM,
836       proxygen::hq::StreamDirection::EGRESS,
837       egressSettings_);
838   egressControlCodec2.generateGoaway(writeBuf, 16, ErrorCode::NO_ERROR);
839   socketDriver_->addReadEvent(connControlStreamId_, writeBuf.move());
840   flushAndLoop();
841   EXPECT_EQ(*socketDriver_->streams_[kConnectionStreamId].error,
842             HTTP3::ErrorCode::HTTP_ID_ERROR);
843 }
844 
TEST_P(HQUpstreamSessionTestHQ,DelayedQPACK)845 TEST_P(HQUpstreamSessionTestHQ, DelayedQPACK) {
846   InSequence enforceOrder;
847   auto handler = openTransaction();
848   handler->txn_->sendHeaders(getGetRequest());
849   handler->txn_->sendEOM();
850   handler->expectHeaders();
851   handler->expectHeaders();
852   handler->expectBody();
853   handler->expectEOM();
854   handler->expectDetachTransaction();
855   auto cont = makeResponse(100);
856   auto resp = makeResponse(200, 100);
857   cont->getHeaders().add("X-FB-Debug", "jvrbfihvuvvclgvfkbkikjlcbruleekj");
858   std::get<0>(resp)->getHeaders().add("X-FB-Debug",
859                                       "egedljtrbullljdjjvtjkekebffefclj");
860   sendResponse(handler->txn_->getID(), *cont, nullptr, false);
861   sendResponse(handler->txn_->getID(),
862                *std::get<0>(resp),
863                std::move(std::get<1>(resp)),
864                true);
865   auto control = encoderWriteBuf_.move();
866   flushAndLoopN(1);
867   encoderWriteBuf_.append(std::move(control));
868   flushAndLoop();
869   hqSession_->closeWhenIdle();
870 }
871 
TEST_P(HQUpstreamSessionTestHQ,DelayedQPACKTimeout)872 TEST_P(HQUpstreamSessionTestHQ, DelayedQPACKTimeout) {
873   InSequence enforceOrder;
874   auto handler = openTransaction();
875   handler->txn_->sendHeaders(getGetRequest());
876   handler->txn_->sendEOM();
877   handler->expectError();
878   auto resp = makeResponse(200, 100);
879   std::get<0>(resp)->getHeaders().add("X-FB-Debug",
880                                       "egedljtrbullljdjjvtjkekebffefclj");
881   sendResponse(handler->txn_->getID(),
882                *std::get<0>(resp),
883                std::move(std::get<1>(resp)),
884                true);
885   auto control = encoderWriteBuf_.move();
886   handler->expectDetachTransaction([this, &control]() mutable {
887     // have the header block arrive after destruction
888     encoderWriteBuf_.append(std::move(control));
889     eventBase_.runInLoop([this] { flush(); });
890     eventBase_.runAfterDelay([this] { hqSession_->closeWhenIdle(); }, 100);
891   });
892   flushAndLoop();
893 }
894 
TEST_P(HQUpstreamSessionTestHQ,QPACKDecoderStreamFlushed)895 TEST_P(HQUpstreamSessionTestHQ, QPACKDecoderStreamFlushed) {
896   InSequence enforceOrder;
897   auto handler = openTransaction();
898   handler->txn_->sendHeadersWithOptionalEOM(getGetRequest(), true);
899   flushAndLoopN(1);
900   handler->expectDetachTransaction();
901   handler->txn_->sendAbort();
902   flushAndLoop();
903   auto& decoderStream = socketDriver_->streams_[kQPACKDecoderEgressStreamId];
904   // type byte plus cancel
905   EXPECT_EQ(decoderStream.writeBuf.chainLength(), 2);
906 
907   handler = openTransaction();
908   handler->txn_->sendHeadersWithOptionalEOM(getGetRequest(), true);
909   handler->expectHeaders();
910   handler->expectBody();
911   handler->expectEOM();
912   auto resp = makeResponse(200, 100);
913   std::get<0>(resp)->getHeaders().add("Response", "Dynamic");
914   sendResponse(handler->txn_->getID(),
915                *std::get<0>(resp),
916                std::move(std::get<1>(resp)),
917                true);
918   auto qpackData = encoderWriteBuf_.move();
919   flushAndLoopN(1);
920   encoderWriteBuf_.append(std::move(qpackData));
921   handler->expectDetachTransaction();
922   hqSession_->closeWhenIdle();
923   flushAndLoop();
924   // type byte plus cancel plus ack
925   EXPECT_EQ(decoderStream.writeBuf.chainLength(), 3);
926 }
927 
TEST_P(HQUpstreamSessionTestHQ,DelayedQPACKAfterReset)928 TEST_P(HQUpstreamSessionTestHQ, DelayedQPACKAfterReset) {
929   // Stand on your head and spit wooden nickels
930   // Ensure the session does not deliver input data to a transaction detached
931   // earlier the same loop
932   InSequence enforceOrder;
933   // Send two requests
934   auto handler1 = openTransaction();
935   auto handler2 = openTransaction();
936   handler1->txn_->sendHeadersWithOptionalEOM(getGetRequest(), true);
937   handler2->txn_->sendHeadersWithOptionalEOM(getGetRequest(), true);
938   // Send a response to txn1 that will block on QPACK data
939   auto resp1 = makeResponse(302, 0);
940   std::get<0>(resp1)->getHeaders().add("Response1", "Dynamic");
941   sendResponse(handler1->txn_->getID(),
942                *std::get<0>(resp1),
943                std::move(std::get<1>(resp1)),
944                true);
945   // Save first QPACK data
946   auto qpackData1 = encoderWriteBuf_.move();
947   // Send response to txn2 that will block on *different* QPACK data
948   auto resp2 = makeResponse(302, 0);
949   std::get<0>(resp2)->getHeaders().add("Respnse2", "Dynamic");
950   sendResponse(handler2->txn_->getID(),
951                *std::get<0>(resp2),
952                std::move(std::get<1>(resp2)),
953                false);
954   // Save second QPACK data
955   auto qpackData2 = encoderWriteBuf_.move();
956 
957   // Abort *both* txns when txn1 gets headers.  This will leave txn2 detached
958   // with pending input data in this loop.
959   handler1->expectHeaders([&] {
960     handler1->txn_->sendAbort();
961     handler2->txn_->sendAbort();
962   });
963 
964   auto streamIt1 = streams_.find(handler1->txn_->getID());
965   CHECK(streamIt1 != streams_.end());
966   auto streamIt2 = streams_.find(handler2->txn_->getID());
967   CHECK(streamIt2 != streams_.end());
968   // add all the events in the same callback, with the stream data coming
969   // before the QPACK data
970   std::vector<MockQuicSocketDriver::ReadEvent> events;
971   events.emplace_back(handler2->txn_->getID(),
972                       streamIt2->second.buf.move(),
973                       streamIt2->second.readEOF,
974                       folly::none,
975                       false);
976   events.emplace_back(handler1->txn_->getID(),
977                       streamIt1->second.buf.move(),
978                       streamIt1->second.readEOF,
979                       folly::none,
980                       false);
981   events.emplace_back(kQPACKEncoderIngressStreamId,
982                       std::move(qpackData1),
983                       false,
984                       folly::none,
985                       false);
986   socketDriver_->addReadEvents(std::move(events));
987   handler2->expectDetachTransaction();
988   handler1->expectDetachTransaction();
989   eventBase_.loopOnce();
990   // Add the QPACK data that would unblock txn2.  It's long gone and this
991   // should be a no-op.
992   socketDriver_->addReadEvent(kQPACKEncoderIngressStreamId,
993                               std::move(qpackData2));
994   eventBase_.loopOnce();
995   hqSession_->closeWhenIdle();
996 }
997 
TEST_P(HQUpstreamSessionTestQPACK,QPACKQueuedOnClose)998 TEST_P(HQUpstreamSessionTestQPACK, QPACKQueuedOnClose) {
999   InSequence enforceOrder;
1000   auto handler = openTransaction();
1001   handler->txn_->sendHeaders(getGetRequest());
1002   handler->txn_->sendEOM();
1003   handler->expectError();
1004   handler->expectDetachTransaction();
1005   auto resp = makeResponse(200, 100);
1006   std::get<0>(resp)->getHeaders().add("X-FB-Debug",
1007                                       "egedljtrbullljdjjvtjkekebffefclj");
1008   sendResponse(handler->txn_->getID(),
1009                *std::get<0>(resp),
1010                std::move(std::get<1>(resp)),
1011                true);
1012   auto control = encoderWriteBuf_.move();
1013   // Entire response is delivered from the transport to the session
1014   flushAndLoopN(1);
1015   // Connection end but the stream is still pending
1016   socketDriver_->addOnConnectionEndEvent(0);
1017   eventBase_.loop();
1018 }
1019 
TEST_P(HQUpstreamSessionTestHQ,TestDropConnectionSynchronously)1020 TEST_P(HQUpstreamSessionTestHQ, TestDropConnectionSynchronously) {
1021   std::unique_ptr<testing::NiceMock<proxygen::MockHTTPSessionInfoCallback>>
1022       infoCb = std::make_unique<
1023           testing::NiceMock<proxygen::MockHTTPSessionInfoCallback>>();
1024   auto handler = openTransaction();
1025   handler->txn_->sendHeaders(getGetRequest());
1026   handler->expectError();
1027   handler->expectDetachTransaction();
1028   hqSession_->setInfoCallback(infoCb.get());
1029   // the session is destroyed synchronously, so the destroy callback gets
1030   // invoked
1031   EXPECT_CALL(*infoCb.get(), onDestroy(_)).Times(1);
1032   hqSession_->dropConnection();
1033   infoCb.reset();
1034   eventBase_.loopOnce();
1035 }
1036 
TEST_P(HQUpstreamSessionTestHQ,TestOnStopSendingHTTPRequestRejected)1037 TEST_P(HQUpstreamSessionTestHQ, TestOnStopSendingHTTPRequestRejected) {
1038   auto handler = openTransaction();
1039   auto streamId = handler->txn_->getID();
1040   handler->txn_->sendHeaders(getGetRequest());
1041   eventBase_.loopOnce();
1042   EXPECT_CALL(*socketDriver_->getSocket(),
1043               resetStream(streamId, HTTP3::ErrorCode::HTTP_REQUEST_CANCELLED))
1044       .Times(2) // once from on stopSending and once from sendAbort
1045       .WillRepeatedly(
1046           Invoke([&](quic::StreamId id, quic::ApplicationErrorCode) {
1047             // setWriteError will cancaleDeliveryCallbacks which will invoke
1048             // onCanceled to decrementPendingByteEvents on the txn.
1049             socketDriver_->setWriteError(id);
1050             return folly::unit;
1051           }));
1052   EXPECT_CALL(*handler, onError(_))
1053       .Times(1)
1054       .WillOnce(Invoke([](HTTPException ex) {
1055         EXPECT_EQ(kErrorStreamUnacknowledged, ex.getProxygenError());
1056       }));
1057   handler->expectDetachTransaction();
1058   hqSession_->onStopSending(streamId, HTTP3::ErrorCode::HTTP_REQUEST_REJECTED);
1059   hqSession_->closeWhenIdle();
1060 }
1061 
TEST_P(HQUpstreamSessionTestHQ,TestGreaseFramePerSession)1062 TEST_P(HQUpstreamSessionTestHQ, TestGreaseFramePerSession) {
1063   // a grease frame is created when creating the first transaction
1064   auto handler1 = openTransaction();
1065   auto streamId1 = handler1->txn_->getID();
1066   handler1->txn_->sendHeaders(getGetRequest());
1067   handler1->txn_->sendEOM();
1068   handler1->expectHeaders();
1069   handler1->expectBody();
1070   handler1->expectEOM();
1071   handler1->expectDetachTransaction();
1072   auto resp1 = makeResponse(200, 100);
1073   sendResponse(handler1->txn_->getID(),
1074                *std::get<0>(resp1),
1075                std::move(std::get<1>(resp1)),
1076                true);
1077   flushAndLoop();
1078   FakeHTTPCodecCallback callback1;
1079   std::unique_ptr<HQStreamCodec> downstreamCodec =
1080       std::make_unique<hq::HQStreamCodec>(
1081           streamId1,
1082           TransportDirection::DOWNSTREAM,
1083           qpackCodec_,
1084           encoderWriteBuf_,
1085           decoderWriteBuf_,
1086           [] { return std::numeric_limits<uint64_t>::max(); },
1087           ingressSettings_);
1088   downstreamCodec->setCallback(&callback1);
1089   downstreamCodec->onIngress(
1090       *socketDriver_->streams_[streamId1].writeBuf.front());
1091   EXPECT_EQ(callback1.unknownFrames, 1);
1092   EXPECT_EQ(callback1.greaseFrames, 1);
1093 
1094   // no grease frame is created when creating the second transaction
1095   auto handler2 = openTransaction();
1096   auto streamId2 = handler2->txn_->getID();
1097   handler2->txn_->sendHeaders(getGetRequest());
1098   handler2->txn_->sendEOM();
1099   handler2->expectHeaders();
1100   handler2->expectBody();
1101   handler2->expectEOM();
1102   handler2->expectDetachTransaction();
1103   auto resp2 = makeResponse(200, 100);
1104   sendResponse(handler2->txn_->getID(),
1105                *std::get<0>(resp2),
1106                std::move(std::get<1>(resp2)),
1107                true);
1108   flushAndLoop();
1109   FakeHTTPCodecCallback callback2;
1110   downstreamCodec->setCallback(&callback2);
1111   downstreamCodec->onIngress(
1112       *socketDriver_->streams_[streamId2].writeBuf.front());
1113   EXPECT_EQ(callback2.unknownFrames, 0);
1114   EXPECT_EQ(callback2.greaseFrames, 0);
1115   hqSession_->closeWhenIdle();
1116 }
1117 
1118 // This test is checking two different scenarios for different protocol
1119 //   - in HQ we already have sent SETTINGS in SetUp, so tests that multiple
1120 //     setting frames are not allowed
1121 //   - in h1q-fb-v2 tests that receiving even a single SETTINGS frame errors
1122 //     out the connection
TEST_P(HQUpstreamSessionTestH1qv2HQ,ExtraSettings)1123 TEST_P(HQUpstreamSessionTestH1qv2HQ, ExtraSettings) {
1124   auto handler = openTransaction();
1125   handler->txn_->sendHeaders(getGetRequest());
1126   handler->txn_->sendEOM();
1127   handler->expectError();
1128   handler->expectDetachTransaction();
1129 
1130   // Need to use a new codec. Since generating settings twice is
1131   // forbidden
1132   HQControlCodec auxControlCodec_{nextUnidirectionalStreamId_,
1133                                   TransportDirection::DOWNSTREAM,
1134                                   StreamDirection::EGRESS,
1135                                   egressSettings_,
1136                                   UnidirectionalStreamType::H1Q_CONTROL};
1137   folly::IOBufQueue writeBuf{folly::IOBufQueue::cacheChainLength()};
1138   auxControlCodec_.generateSettings(writeBuf);
1139   socketDriver_->addReadEvent(
1140       connControlStreamId_, writeBuf.move(), milliseconds(0));
1141 
1142   flushAndLoop();
1143 
1144   EXPECT_EQ(*socketDriver_->streams_[kConnectionStreamId].error,
1145             HTTP3::ErrorCode::HTTP_FRAME_UNEXPECTED);
1146 }
1147 
1148 // Test Cases for which Settings are not sent in the test SetUp
1149 using HQUpstreamSessionTestHQNoSettings = HQUpstreamSessionTest;
1150 
1151 INSTANTIATE_TEST_CASE_P(HQUpstreamSessionTest,
1152                         HQUpstreamSessionTestHQNoSettings,
__anon346abe7d1302null1153                         Values([] {
1154                           TestParams tp;
1155                           tp.alpn_ = "h3";
1156                           tp.shouldSendSettings_ = false;
1157                           return tp;
1158                         }()),
1159                         paramsToTestName);
TEST_P(HQUpstreamSessionTestHQNoSettings,SimpleGet)1160 TEST_P(HQUpstreamSessionTestHQNoSettings, SimpleGet) {
1161   EXPECT_CALL(connectCb_, connectError(_)).Times(1);
1162   socketDriver_->deliverConnectionError(
1163       {quic::LocalErrorCode::CONNECT_FAILED, "Peer closed"});
1164 }
1165 
TEST_P(HQUpstreamSessionTestHQNoSettings,GoawayBeforeSettings)1166 TEST_P(HQUpstreamSessionTestHQNoSettings, GoawayBeforeSettings) {
1167   auto handler = openTransaction();
1168   handler->txn_->sendHeaders(getGetRequest());
1169   handler->txn_->sendEOM();
1170   handler->expectError();
1171   handler->expectDetachTransaction();
1172 
1173   sendGoaway(HTTPCodec::MaxStreamID);
1174   flushAndLoop();
1175 
1176   EXPECT_EQ(*socketDriver_->streams_[kConnectionStreamId].error,
1177             HTTP3::ErrorCode::HTTP_MISSING_SETTINGS);
1178 }
1179 
TEST_P(HQUpstreamSessionTestH1qv1,TestConnectionClose)1180 TEST_P(HQUpstreamSessionTestH1qv1, TestConnectionClose) {
1181   hqSession_->drain();
1182   auto handler = openTransaction();
1183   handler->txn_->sendHeaders(getGetRequest());
1184   handler->txn_->sendEOM();
1185   handler->expectHeaders();
1186   handler->expectBody();
1187   handler->expectEOM();
1188   handler->expectDetachTransaction();
1189   auto resp = makeResponse(200, 100);
1190   std::get<0>(resp)->getHeaders().set(HTTP_HEADER_CONNECTION, "close");
1191   sendResponse(handler->txn_->getID(),
1192                *std::get<0>(resp),
1193                std::move(std::get<1>(resp)),
1194                true);
1195   hqSession_->closeWhenIdle();
1196   flushAndLoop();
1197 }
1198 
1199 /**
1200  * Push tests
1201  */
1202 
1203 class HQUpstreamSessionTestHQPush : public HQUpstreamSessionTest {
1204  public:
SetUp()1205   void SetUp() override {
1206     HQUpstreamSessionTest::SetUp();
1207     SetUpAssocHandler();
1208     nextPushId_ = kInitialPushId;
1209     lastPushPromiseHeadersSize_.compressed = 0;
1210     lastPushPromiseHeadersSize_.uncompressed = 0;
1211   }
1212 
SetUpAssocHandler()1213   void SetUpAssocHandler() {
1214     // Create the primary request
1215     assocHandler_ = openTransaction();
1216     assocHandler_->txn_->sendHeaders(getGetRequest());
1217     assocHandler_->expectDetachTransaction();
1218   }
1219 
TearDown()1220   void TearDown() override {
1221     HQUpstreamSessionTest::TearDown();
1222   }
1223 
SetUpServerPushLifecycleCallbacks()1224   void SetUpServerPushLifecycleCallbacks() {
1225     if (!SLCcallback_) {
1226       SLCcallback_ = std::make_unique<MockServerPushLifecycleCallback>();
1227       hqSession_->setServerPushLifecycleCallback(SLCcallback_.get());
1228     }
1229   }
1230 
nextPushId()1231   hq::PushId nextPushId() {
1232     auto id = nextPushId_;
1233     nextPushId_ += kPushIdIncrement;
1234     return id;
1235   }
1236 
1237   // NOTE: Using odd numbers for push ids, to allow detecting
1238   // subtle bugs where streamID and pushID are quietly misplaced
isPushIdValid(hq::PushId pushId)1239   bool isPushIdValid(hq::PushId pushId) {
1240     return (pushId % 2) == 1;
1241   }
1242 
1243   using WriteFunctor = std::function<folly::Optional<size_t>(IOBufQueue&)>;
writeUpTo(quic::StreamId id,size_t maxlen,WriteFunctor functor)1244   folly::Optional<size_t> writeUpTo(quic::StreamId id,
1245                                     size_t maxlen,
1246                                     WriteFunctor functor) {
1247     // Lookup the stream
1248     auto findRes = streams_.find(id);
1249     if (findRes == streams_.end()) {
1250       return folly::none;
1251     }
1252 
1253     IOBufQueue tmpbuf{IOBufQueue::cacheChainLength()};
1254     auto funcres = functor(tmpbuf);
1255     if (!funcres) {
1256       return folly::none;
1257     }
1258 
1259     auto eventbuf = tmpbuf.splitAtMost(maxlen);
1260     auto wlen = eventbuf->length();
1261     CHECK_LE(wlen, maxlen) << "The written len must not exceed the max len";
1262     socketDriver_->addReadEvent(id, std::move(eventbuf), milliseconds(0));
1263     return wlen;
1264   }
1265 
1266   // Use the common facilities to write the quic integer
writePushStreamPreface(quic::StreamId id,size_t maxlen)1267   folly::Optional<size_t> writePushStreamPreface(quic::StreamId id,
1268                                                  size_t maxlen) {
1269     WriteFunctor f = [](IOBufQueue& outbuf) {
1270       return generateStreamPreface(outbuf, hq::UnidirectionalStreamType::PUSH);
1271     };
1272 
1273     auto res = writeUpTo(id, maxlen, f);
1274     return res;
1275   }
1276 
writeUnframedPushId(quic::StreamId id,size_t maxlen,hq::PushId pushId)1277   folly::Optional<size_t> writeUnframedPushId(quic::StreamId id,
1278                                               size_t maxlen,
1279                                               hq::PushId pushId) {
1280     WriteFunctor f = [=](IOBufQueue& outbuf) -> folly::Optional<size_t> {
1281       folly::io::QueueAppender appender(&outbuf, 8);
1282       uint8_t size = 1 << (folly::Random::rand32() % 4);
1283       auto wlen = encodeQuicIntegerWithAtLeast(pushId, size, appender);
1284       CHECK_GE(wlen, size);
1285       return wlen;
1286     };
1287 
1288     auto res = writeUpTo(id, maxlen, f);
1289     return res;
1290   }
1291 
expectPushPromiseBegin(std::function<void (HTTPCodec::StreamID,hq::PushId)> callback=std::function<void (HTTPCodec::StreamID,hq::PushId)> ())1292   void expectPushPromiseBegin(
1293       std::function<void(HTTPCodec::StreamID, hq::PushId)> callback =
1294           std::function<void(HTTPCodec::StreamID, hq::PushId)>()) {
1295     SetUpServerPushLifecycleCallbacks();
1296     SLCcallback_->expectPushPromiseBegin(callback);
1297   }
1298 
expectPushPromise(std::function<void (HTTPCodec::StreamID,hq::PushId,HTTPMessage *)> callback=std::function<void (HTTPCodec::StreamID,hq::PushId,HTTPMessage *)> ())1299   void expectPushPromise(
1300       std::function<void(HTTPCodec::StreamID, hq::PushId, HTTPMessage*)>
1301           callback = std::function<
1302               void(HTTPCodec::StreamID, hq::PushId, HTTPMessage*)>()) {
1303     SetUpServerPushLifecycleCallbacks();
1304     SLCcallback_->expectPushPromise(callback);
1305   }
1306 
expectNascentPushStreamBegin(std::function<void (HTTPCodec::StreamID,bool)> callback=std::function<void (HTTPCodec::StreamID,bool)> ())1307   void expectNascentPushStreamBegin(
1308       std::function<void(HTTPCodec::StreamID, bool)> callback =
1309           std::function<void(HTTPCodec::StreamID, bool)>()) {
1310     SetUpServerPushLifecycleCallbacks();
1311     SLCcallback_->expectNascentPushStreamBegin(callback);
1312   }
1313 
expectNascentPushStream(std::function<void (HTTPCodec::StreamID,hq::PushId,bool)> callback=std::function<void (HTTPCodec::StreamID,hq::PushId,bool)> ())1314   void expectNascentPushStream(
1315       std::function<void(HTTPCodec::StreamID, hq::PushId, bool)> callback =
1316           std::function<void(HTTPCodec::StreamID, hq::PushId, bool)>()) {
1317     SetUpServerPushLifecycleCallbacks();
1318     SLCcallback_->expectNascentPushStream(callback);
1319   }
1320 
expectNascentEof(std::function<void (HTTPCodec::StreamID,folly::Optional<hq::PushId>)> callback=std::function<void (HTTPCodec::StreamID,folly::Optional<hq::PushId>)> ())1321   void expectNascentEof(
1322       std::function<void(HTTPCodec::StreamID, folly::Optional<hq::PushId>)>
1323           callback = std::function<void(HTTPCodec::StreamID,
1324                                         folly::Optional<hq::PushId>)>()) {
1325     SetUpServerPushLifecycleCallbacks();
1326     SLCcallback_->expectNascentEof(callback);
1327   }
1328 
expectOrphanedNascentStream(std::function<void (HTTPCodec::StreamID,folly::Optional<hq::PushId>)> callback=std::function<void (HTTPCodec::StreamID,folly::Optional<hq::PushId>)> ())1329   void expectOrphanedNascentStream(
1330       std::function<void(HTTPCodec::StreamID, folly::Optional<hq::PushId>)>
1331           callback = std::function<void(HTTPCodec::StreamID,
1332                                         folly::Optional<hq::PushId>)>()) {
1333 
1334     SetUpServerPushLifecycleCallbacks();
1335     SLCcallback_->expectOrphanedNascentStream(callback);
1336   }
1337 
expectHalfOpenPushedTxn(std::function<void (const HTTPTransaction *,hq::PushId,HTTPCodec::StreamID,bool)> callback=std::function<void (const HTTPTransaction *,hq::PushId,HTTPCodec::StreamID,bool)> ())1338   void expectHalfOpenPushedTxn(
1339       std::function<
1340           void(const HTTPTransaction*, hq::PushId, HTTPCodec::StreamID, bool)>
1341           callback = std::function<void(const HTTPTransaction*,
1342                                         hq::PushId,
1343                                         HTTPCodec::StreamID,
1344                                         bool)>()) {
1345     SetUpServerPushLifecycleCallbacks();
1346     SLCcallback_->expectHalfOpenPushedTxn(callback);
1347   }
1348 
expectPushedTxn(std::function<void (const HTTPTransaction *,HTTPCodec::StreamID,hq::PushId,HTTPCodec::StreamID,bool)> callback=std::function<void (const HTTPTransaction *,HTTPCodec::StreamID,hq::PushId,HTTPCodec::StreamID,bool)> ())1349   void expectPushedTxn(std::function<void(const HTTPTransaction*,
1350                                           HTTPCodec::StreamID,
1351                                           hq::PushId,
1352                                           HTTPCodec::StreamID,
1353                                           bool)> callback =
1354                            std::function<void(const HTTPTransaction*,
1355                                               HTTPCodec::StreamID,
1356                                               hq::PushId,
1357                                               HTTPCodec::StreamID,
1358                                               bool)>()) {
1359     SetUpServerPushLifecycleCallbacks();
1360     SLCcallback_->expectPushedTxn(callback);
1361   }
1362 
expectPushedTxnTimeout(std::function<void (const HTTPTransaction *)> callback=std::function<void (const HTTPTransaction *)> ())1363   void expectPushedTxnTimeout(
1364       std::function<void(const HTTPTransaction*)> callback =
1365           std::function<void(const HTTPTransaction*)>()) {
1366     SetUpServerPushLifecycleCallbacks();
1367     SLCcallback_->expectPushedTxnTimeout(callback);
1368   }
1369 
expectOrphanedHalfOpenPushedTxn(std::function<void (const HTTPTransaction *)> callback=std::function<void (const HTTPTransaction *)> ())1370   void expectOrphanedHalfOpenPushedTxn(
1371       std::function<void(const HTTPTransaction*)> callback =
1372           std::function<void(const HTTPTransaction*)>()) {
1373     SetUpServerPushLifecycleCallbacks();
1374     SLCcallback_->expectOrphanedHalfOpenPushedTxn(callback);
1375   }
1376 
sendPushPromise(quic::StreamId streamId,hq::PushId pushId=kUnknownPushId,const std::string & url="/",proxygen::HTTPHeaderSize * outHeaderSize=nullptr,bool eom=false)1377   void sendPushPromise(quic::StreamId streamId,
1378                        hq::PushId pushId = kUnknownPushId,
1379                        const std::string& url = "/",
1380                        proxygen::HTTPHeaderSize* outHeaderSize = nullptr,
1381                        bool eom = false) {
1382     auto promise = getGetRequest(url);
1383     promise.setURL(url);
1384 
1385     return sendPushPromise(streamId, promise, pushId, outHeaderSize, eom);
1386   }
1387 
sendPushPromise(quic::StreamId streamId,const HTTPMessage & promiseHeadersBlock,hq::PushId pushId=kUnknownPushId,proxygen::HTTPHeaderSize * outHeaderSize=nullptr,bool eom=false)1388   void sendPushPromise(quic::StreamId streamId,
1389                        const HTTPMessage& promiseHeadersBlock,
1390                        hq::PushId pushId = kUnknownPushId,
1391                        proxygen::HTTPHeaderSize* outHeaderSize = nullptr,
1392                        bool eom = false) {
1393 
1394     // In case the user is not interested in knowing the size
1395     // of headers, but just in the fact that the headers were
1396     // written, use a temporary size for checks
1397     if (outHeaderSize == nullptr) {
1398       outHeaderSize = &lastPushPromiseHeadersSize_;
1399     }
1400 
1401     if (pushId == kUnknownPushId) {
1402       pushId = nextPushId();
1403     }
1404 
1405     auto c = makeCodec(streamId);
1406     auto res =
1407         streams_.emplace(std::piecewise_construct,
1408                          std::forward_as_tuple(streamId),
1409                          std::forward_as_tuple(c.first, std::move(c.second)));
1410 
1411     auto& pushPromiseRequest = res.first->second;
1412     pushPromiseRequest.id = streamId;
1413 
1414     // Push promises should not have EOF set.
1415     pushPromiseRequest.readEOF = eom;
1416 
1417     // Write the push promise to the request buffer.
1418     // The push promise includes the headers
1419     pushPromiseRequest.codec->generatePushPromise(pushPromiseRequest.buf,
1420                                                   streamId,
1421                                                   promiseHeadersBlock,
1422                                                   pushId,
1423                                                   eom,
1424                                                   outHeaderSize);
1425   }
1426 
1427   // Shared implementation for different push stream
1428   // methods
createPushStreamImpl(quic::StreamId streamId,folly::Optional<hq::PushId> pushId,std::size_t len=kUnlimited,bool eom=true)1429   ServerStream& createPushStreamImpl(quic::StreamId streamId,
1430                                      folly::Optional<hq::PushId> pushId,
1431                                      std::size_t len = kUnlimited,
1432                                      bool eom = true) {
1433 
1434     auto c = makeCodec(streamId);
1435     // Setting a push id allows us to send push preface
1436     auto res = streams_.emplace(
1437         std::piecewise_construct,
1438         std::forward_as_tuple(streamId),
1439         std::forward_as_tuple(c.first, std::move(c.second), pushId));
1440 
1441     auto& stream = res.first->second;
1442     stream.id = stream.codec->createStream();
1443     stream.readEOF = eom;
1444 
1445     // Generate the push stream preface, and if there's enough headroom
1446     // the unframed push id that follows it
1447     auto prefaceRes = writePushStreamPreface(stream.id, len);
1448     if (pushId.has_value()) {
1449       if (prefaceRes) {
1450         len -= *prefaceRes;
1451         writeUnframedPushId(stream.id, len, *pushId);
1452       }
1453     }
1454 
1455     return stream;
1456   }
1457 
1458   // Create a push stream with a header block and body
createPushStream(quic::StreamId streamId,hq::PushId pushId,const HTTPMessage & resp,std::unique_ptr<folly::IOBuf> body=nullptr,bool eom=true)1459   void createPushStream(quic::StreamId streamId,
1460                         hq::PushId pushId,
1461                         const HTTPMessage& resp,
1462                         std::unique_ptr<folly::IOBuf> body = nullptr,
1463                         bool eom = true) {
1464 
1465     auto& stream = createPushStreamImpl(streamId, pushId, kUnlimited, eom);
1466 
1467     // Write the response
1468     stream.codec->generateHeader(
1469         stream.buf, stream.codecId, resp, body == nullptr ? eom : false);
1470     if (body) {
1471       stream.codec->generateBody(
1472           stream.buf, stream.codecId, std::move(body), folly::none, eom);
1473     }
1474   }
1475 
1476   // Convenience method for creating a push stream without the
1477   // need to allocate transport stream id
createPushStream(hq::PushId pushId,const HTTPMessage & resp,std::unique_ptr<folly::IOBuf> body=nullptr,bool eom=true)1478   void createPushStream(hq::PushId pushId,
1479                         const HTTPMessage& resp,
1480                         std::unique_ptr<folly::IOBuf> body = nullptr,
1481                         bool eom = true) {
1482     return createPushStream(
1483         nextUnidirectionalStreamId(), pushId, resp, std::move(body), eom);
1484   }
1485 
1486   // Create nascent stream (no body)
createNascentPushStream(quic::StreamId streamId,folly::Optional<hq::PushId> pushId,std::size_t len=kUnlimited,bool eom=true)1487   void createNascentPushStream(quic::StreamId streamId,
1488                                folly::Optional<hq::PushId> pushId,
1489                                std::size_t len = kUnlimited,
1490                                bool eom = true) {
1491     createPushStreamImpl(streamId, pushId, len, eom);
1492   }
1493 
lastPushPromiseHeadersSizeValid()1494   bool lastPushPromiseHeadersSizeValid() {
1495     return ((lastPushPromiseHeadersSize_.uncompressed > 0) &&
1496             (lastPushPromiseHeadersSize_.compressed > 0));
1497   }
1498 
createNascentPushStream(hq::PushId pushId,std::size_t prefaceBytes=kUnlimited,bool eom=true)1499   void createNascentPushStream(hq::PushId pushId,
1500                                std::size_t prefaceBytes = kUnlimited,
1501                                bool eom = true) {
1502     return createNascentPushStream(
1503         nextUnidirectionalStreamId(), pushId, prefaceBytes, eom);
1504   }
1505 
expectPushResponse()1506   std::unique_ptr<MockHTTPHandler> expectPushResponse() {
1507     auto pushHandler = std::make_unique<MockHTTPHandler>();
1508     pushHandler->expectTransaction();
1509     assocHandler_->expectPushedTransaction(pushHandler.get());
1510     // Promise/Response - with no lambda it lacks RetiresOnSaturation
1511     pushHandler->expectHeaders([](std::shared_ptr<HTTPMessage>) {});
1512     pushHandler->expectHeaders([](std::shared_ptr<HTTPMessage>) {});
1513     pushHandler->expectBody();
1514     pushHandler->expectEOM();
1515     pushHandler->expectDetachTransaction();
1516     return pushHandler;
1517   }
1518 
1519   proxygen::HTTPHeaderSize lastPushPromiseHeadersSize_;
1520   hq::PushId nextPushId_;
1521   std::unique_ptr<StrictMock<MockHTTPHandler>> assocHandler_;
1522 
1523   std::unique_ptr<MockServerPushLifecycleCallback> SLCcallback_;
1524 };
1525 
TEST_P(HQUpstreamSessionTestHQPush,DelayedQPACKPush)1526 TEST_P(HQUpstreamSessionTestHQPush, DelayedQPACKPush) {
1527   assocHandler_->txn_->sendAbort();
1528   assocHandler_ = openTransaction();
1529   assocHandler_->txn_->sendHeaders(getGetRequest());
1530   assocHandler_->txn_->sendEOM();
1531   assocHandler_->expectHeaders();
1532   assocHandler_->expectBody();
1533   auto pushHandler = expectPushResponse();
1534   assocHandler_->expectEOM();
1535   assocHandler_->expectDetachTransaction();
1536 
1537   auto resp = makeResponse(200, 100);
1538   sendResponse(assocHandler_->txn_->getID(),
1539                *std::get<0>(resp),
1540                std::move(std::get<1>(resp)),
1541                false);
1542   flushAndLoopN(1);
1543   auto pushPromiseRequest = getGetRequest();
1544   pushPromiseRequest.getHeaders().set("Dynamic1", "a");
1545   hq::PushId pushId = nextPushId();
1546   sendPushPromise(assocHandler_->txn_->getID(), pushPromiseRequest, pushId);
1547   sendPartialBody(assocHandler_->txn_->getID(), nullptr, true);
1548 
1549   auto control = encoderWriteBuf_.move();
1550   flushAndLoopN(1);
1551 
1552   encoderWriteBuf_.append(std::move(control));
1553   flushAndLoopN(1);
1554 
1555   HTTPMessage pushResp;
1556   pushResp.setStatusCode(200);
1557   pushResp.getHeaders().set("Dynamic2", "b");
1558   createPushStream(pushId, pushResp, makeBuf(100), true);
1559 
1560   control = encoderWriteBuf_.move();
1561   flushAndLoopN(1);
1562 
1563   encoderWriteBuf_.append(std::move(control));
1564   flushAndLoop();
1565   hqSession_->closeWhenIdle();
1566 }
1567 
TEST_P(HQUpstreamSessionTestHQPush,TestPushPromiseCallbacksInvoked)1568 TEST_P(HQUpstreamSessionTestHQPush, TestPushPromiseCallbacksInvoked) {
1569   // the push promise is not followed by a push stream, and the eof is not
1570   // set.
1571   // The transaction is supposed to stay open and to time out eventually.
1572   assocHandler_->expectError([&](const HTTPException& ex) {
1573     ASSERT_EQ(ex.getProxygenError(), kErrorTimeout);
1574   });
1575 
1576   hq::PushId pushId = nextPushId();
1577 
1578   auto pushPromiseRequest = getGetRequest();
1579 
1580   expectPushPromiseBegin(
1581       [&](HTTPCodec::StreamID owningStreamId, hq::PushId promisedPushId) {
1582         EXPECT_EQ(promisedPushId, pushId);
1583         EXPECT_EQ(owningStreamId, assocHandler_->txn_->getID());
1584       });
1585 
1586   expectPushPromise([&](HTTPCodec::StreamID owningStreamId,
1587                         hq::PushId promisedPushId,
1588                         HTTPMessage* msg) {
1589     EXPECT_EQ(promisedPushId, pushId);
1590     EXPECT_EQ(owningStreamId, assocHandler_->txn_->getID());
1591 
1592     EXPECT_THAT(msg, NotNull());
1593 
1594     auto expectedHeaders = pushPromiseRequest.getHeaders();
1595     auto actualHeaders = msg->getHeaders();
1596 
1597     expectedHeaders.forEach(
1598         [&](const std::string& header, const std::string& /* val */) {
1599           EXPECT_TRUE(actualHeaders.exists(header));
1600           EXPECT_EQ(expectedHeaders.getNumberOfValues(header),
1601                     actualHeaders.getNumberOfValues(header));
1602         });
1603   });
1604 
1605   HTTPCodec::StreamID nascentStreamId;
1606 
1607   expectNascentPushStreamBegin([&](HTTPCodec::StreamID streamId, bool isEOF) {
1608     nascentStreamId = streamId;
1609     EXPECT_FALSE(isEOF);
1610   });
1611 
1612   expectNascentPushStream([&](HTTPCodec::StreamID pushStreamId,
1613                               hq::PushId pushStreamPushId,
1614                               bool /* isEOF */) {
1615     EXPECT_EQ(pushStreamPushId, pushId);
1616     EXPECT_EQ(pushStreamId, nascentStreamId);
1617   });
1618 
1619   sendPushPromise(assocHandler_->txn_->getID(), pushPromiseRequest, pushId);
1620   EXPECT_TRUE(lastPushPromiseHeadersSizeValid());
1621 
1622   HTTPMessage resp;
1623   resp.setStatusCode(200);
1624   createPushStream(pushId, resp, makeBuf(100), true);
1625 
1626   assocHandler_->txn_->sendEOM();
1627 
1628   auto pushHandler = expectPushResponse();
1629 
1630   hqSession_->closeWhenIdle();
1631   flushAndLoop();
1632 }
1633 
TEST_P(HQUpstreamSessionTestHQPush,TestIngressPushStream)1634 TEST_P(HQUpstreamSessionTestHQPush, TestIngressPushStream) {
1635 
1636   hq::PushId pushId = nextPushId();
1637 
1638   auto pushPromiseRequest = getGetRequest();
1639 
1640   HTTPCodec::StreamID nascentStreamId;
1641 
1642   expectNascentPushStreamBegin([&](HTTPCodec::StreamID streamId, bool isEOF) {
1643     nascentStreamId = streamId;
1644     EXPECT_FALSE(isEOF);
1645   });
1646 
1647   expectNascentPushStream([&](HTTPCodec::StreamID streamId,
1648                               hq::PushId pushStreamPushId,
1649                               bool isEOF) {
1650     EXPECT_EQ(streamId, nascentStreamId);
1651     EXPECT_EQ(pushId, pushStreamPushId);
1652     EXPECT_EQ(isEOF, false);
1653   });
1654 
1655   // Since push promise is not sent, full ingress push stream
1656   // not going to be created
1657   /*
1658     expectOrphanedNascentStream([&](HTTPCodec::StreamID streamId,
1659                                     folly::Optional<hq::PushId> maybePushId) {
1660       ASSERT_EQ(streamId, nascentStreamId);
1661       EXPECT_EQ(maybePushId.has_value(), true);
1662       EXPECT_EQ(maybePushId.value(), pushId);
1663     });
1664   */
1665   HTTPMessage resp;
1666   resp.setStatusCode(200);
1667   createPushStream(pushId, resp, makeBuf(100), true);
1668 
1669   // Currently, the new transaction is not created corectly,
1670   // and an error is expected. to be extended in the following
1671   // diffs which add creation of pushed transaction
1672   assocHandler_->expectError();
1673 
1674   assocHandler_->txn_->sendEOM();
1675   hqSession_->closeWhenIdle();
1676   flushAndLoop(); // One read for the letter, one read for quic integer. Is
1677                   // enough?
1678 }
1679 
TEST_P(HQUpstreamSessionTestHQPush,TestPushPromiseFollowedByPushStream)1680 TEST_P(HQUpstreamSessionTestHQPush, TestPushPromiseFollowedByPushStream) {
1681   // the transaction is expected to timeout, since the PushPromise does not have
1682   // EOF set, and it is not followed by a PushStream.
1683   assocHandler_->expectError();
1684 
1685   hq::PushId pushId = nextPushId();
1686 
1687   auto pushPromiseRequest = getGetRequest();
1688 
1689   expectPushPromiseBegin(
1690       [&](HTTPCodec::StreamID owningStreamId, hq::PushId promisedPushId) {
1691         EXPECT_EQ(promisedPushId, pushId);
1692         EXPECT_EQ(owningStreamId, assocHandler_->txn_->getID());
1693       });
1694 
1695   expectPushPromise([&](HTTPCodec::StreamID owningStreamId,
1696                         hq::PushId promisedPushId,
1697                         HTTPMessage* msg) {
1698     EXPECT_EQ(promisedPushId, pushId);
1699     EXPECT_EQ(owningStreamId, assocHandler_->txn_->getID());
1700 
1701     EXPECT_THAT(msg, NotNull());
1702 
1703     auto expectedHeaders = pushPromiseRequest.getHeaders();
1704     auto actualHeaders = msg->getHeaders();
1705 
1706     expectedHeaders.forEach(
1707         [&](const std::string& header, const std::string& /* val */) {
1708           EXPECT_TRUE(actualHeaders.exists(header));
1709           EXPECT_EQ(expectedHeaders.getNumberOfValues(header),
1710                     actualHeaders.getNumberOfValues(header));
1711         });
1712   });
1713 
1714   HTTPCodec::StreamID nascentStreamId;
1715 
1716   expectNascentPushStreamBegin([&](HTTPCodec::StreamID streamId, bool isEOF) {
1717     nascentStreamId = streamId;
1718     folly::Optional<HTTPCodec::StreamID> expectedReadId(nascentStreamId);
1719     EXPECT_CALL(infoCb_, onRead(testing::_, testing::_, expectedReadId))
1720         .Times(testing::AtLeast(1));
1721     EXPECT_FALSE(isEOF);
1722   });
1723 
1724   // since push stream arrives after the promise,
1725   // full ingress push stream has to be created
1726   expectNascentPushStream([&](HTTPCodec::StreamID pushStreamId,
1727                               hq::PushId pushStreamPushId,
1728                               bool /* isEOF */) {
1729     EXPECT_EQ(pushStreamPushId, pushId);
1730     EXPECT_EQ(pushStreamId, nascentStreamId);
1731   });
1732 
1733   proxygen::HTTPHeaderSize pushPromiseSize;
1734 
1735   sendPushPromise(assocHandler_->txn_->getID(),
1736                   pushPromiseRequest,
1737                   pushId,
1738                   &pushPromiseSize);
1739   HTTPMessage resp;
1740   resp.setStatusCode(200);
1741   createPushStream(pushId, resp, makeBuf(100), true);
1742 
1743   assocHandler_->txn_->sendEOM();
1744 
1745   auto pushHandler = expectPushResponse();
1746 
1747   hqSession_->closeWhenIdle();
1748   flushAndLoop();
1749 }
1750 
TEST_P(HQUpstreamSessionTestHQPush,TestAbortedPushedTransactionAfterPromise)1751 TEST_P(HQUpstreamSessionTestHQPush, TestAbortedPushedTransactionAfterPromise) {
1752   assocHandler_->txn_->sendAbort();
1753   assocHandler_ = openTransaction();
1754   assocHandler_->txn_->sendHeaders(getGetRequest());
1755   assocHandler_->txn_->sendEOM();
1756   assocHandler_->expectHeaders();
1757   assocHandler_->expectBody();
1758   assocHandler_->expectEOM();
1759   assocHandler_->expectDetachTransaction();
1760 
1761   auto resp = makeResponse(200, 100);
1762   sendResponse(assocHandler_->txn_->getID(),
1763                *std::get<0>(resp),
1764                std::move(std::get<1>(resp)),
1765                false);
1766   flushAndLoopN(1);
1767 
1768   auto pushHandler = std::make_unique<MockHTTPHandler>();
1769   pushHandler->expectTransaction();
1770   assocHandler_->expectPushedTransaction(pushHandler.get());
1771   // Abort the pushed transaction upon reception of the push promise.
1772   pushHandler->expectHeaders(
1773       [&](std::shared_ptr<HTTPMessage>) { pushHandler->txn_->sendAbort(); });
1774 
1775   auto pushPromiseRequest = getGetRequest();
1776   hq::PushId pushId = nextPushId();
1777   sendPushPromise(assocHandler_->txn_->getID(), pushPromiseRequest, pushId);
1778   // Send body to close the main request stream
1779   sendPartialBody(assocHandler_->txn_->getID(), nullptr, true);
1780   pushHandler->expectDetachTransaction();
1781 
1782   flushAndLoop();
1783   hqSession_->closeWhenIdle();
1784 }
1785 
TEST_P(HQUpstreamSessionTestHQPush,TestAbortedPushedTransactionAfterResponse)1786 TEST_P(HQUpstreamSessionTestHQPush, TestAbortedPushedTransactionAfterResponse) {
1787   assocHandler_->txn_->sendAbort();
1788   assocHandler_ = openTransaction();
1789   assocHandler_->txn_->sendHeaders(getGetRequest());
1790   assocHandler_->txn_->sendEOM();
1791   assocHandler_->expectHeaders();
1792   assocHandler_->expectBody();
1793   assocHandler_->expectEOM();
1794   assocHandler_->expectDetachTransaction();
1795 
1796   auto resp = makeResponse(200, 100);
1797   sendResponse(assocHandler_->txn_->getID(),
1798                *std::get<0>(resp),
1799                std::move(std::get<1>(resp)),
1800                false);
1801   flushAndLoopN(1);
1802 
1803   auto pushHandler = std::make_unique<MockHTTPHandler>();
1804   pushHandler->expectTransaction();
1805   assocHandler_->expectPushedTransaction(pushHandler.get());
1806   // Expect normal promise.
1807   pushHandler->expectHeaders([](std::shared_ptr<HTTPMessage>) {});
1808 
1809   auto pushPromiseRequest = getGetRequest();
1810   pushPromiseRequest.getHeaders().set("Dynamic1", "a");
1811   hq::PushId pushId = nextPushId();
1812   sendPushPromise(assocHandler_->txn_->getID(), pushPromiseRequest, pushId);
1813   sendPartialBody(assocHandler_->txn_->getID(), nullptr, true);
1814   flushAndLoopN(1);
1815 
1816   // Abort the pushed transaction on response.
1817   pushHandler->expectHeaders(
1818       [&](std::shared_ptr<HTTPMessage>) { pushHandler->txn_->sendAbort(); });
1819   pushHandler->expectDetachTransaction();
1820   HTTPMessage pushResp;
1821   pushResp.setStatusCode(200);
1822   pushResp.getHeaders().set("Dynamic2", "b");
1823   createPushStream(pushId, pushResp, makeBuf(100), true);
1824 
1825   flushAndLoop();
1826   hqSession_->closeWhenIdle();
1827 }
1828 
TEST_P(HQUpstreamSessionTestHQPush,TestOnPushedTransaction)1829 TEST_P(HQUpstreamSessionTestHQPush, TestOnPushedTransaction) {
1830   // the transaction is expected to timeout, since the PushPromise does not have
1831   // EOF set, and it is not followed by a PushStream.
1832   assocHandler_->expectError();
1833   // assocHandler_->expectHeaders();
1834 
1835   hq::PushId pushId = nextPushId();
1836 
1837   auto pushPromiseRequest = getGetRequest();
1838 
1839   proxygen::HTTPHeaderSize pushPromiseSize;
1840 
1841   sendPushPromise(assocHandler_->txn_->getID(),
1842                   pushPromiseRequest,
1843                   pushId,
1844                   &pushPromiseSize);
1845 
1846   HTTPMessage resp;
1847   resp.setStatusCode(200);
1848   createPushStream(pushId, resp, makeBuf(100), true);
1849 
1850   // Once both push promise and push stream have been received, a push
1851   // transaction should be created
1852   assocHandler_->txn_->sendEOM();
1853 
1854   auto pushHandler = expectPushResponse();
1855 
1856   hqSession_->closeWhenIdle();
1857   flushAndLoop();
1858 }
1859 
TEST_P(HQUpstreamSessionTestHQPush,TestOnPushedTransactionOutOfOrder)1860 TEST_P(HQUpstreamSessionTestHQPush, TestOnPushedTransactionOutOfOrder) {
1861   // the transaction is expected to timeout, since the PushPromise does not have
1862   // EOF set, and it is not followed by a PushStream.
1863   assocHandler_->expectError();
1864   // assocHandler_->expectHeaders();
1865 
1866   hq::PushId pushId = nextPushId();
1867 
1868   HTTPMessage resp;
1869   resp.setStatusCode(200);
1870   createPushStream(pushId, resp, makeBuf(100), true);
1871 
1872   auto pushPromiseRequest = getGetRequest();
1873   proxygen::HTTPHeaderSize pushPromiseSize;
1874   sendPushPromise(assocHandler_->txn_->getID(),
1875                   pushPromiseRequest,
1876                   pushId,
1877                   &pushPromiseSize);
1878 
1879   // Once both push promise and push stream have been received, a push
1880   // transaction should be created
1881   auto pushHandler = expectPushResponse();
1882 
1883   assocHandler_->txn_->sendEOM();
1884 
1885   hqSession_->closeWhenIdle();
1886   flushAndLoop();
1887 }
1888 
TEST_P(HQUpstreamSessionTestHQPush,TestCloseDroppedConnection)1889 TEST_P(HQUpstreamSessionTestHQPush, TestCloseDroppedConnection) {
1890   HQSession::DestructorGuard dg(hqSession_);
1891   // Two "onError" calls are expected:
1892   // the first when MockQuicSocketDriver closes the socket
1893   // the second when the error is propagated to the stream
1894   EXPECT_CALL(*assocHandler_, onError(testing::_)).Times(2);
1895 
1896   // Create a nascent push stream with a preface only
1897   createNascentPushStream(1111 /* streamId */, folly::none /* pushId */);
1898 
1899   // Run the event loop to let the dispatcher register the nascent stream
1900   flushAndLoop();
1901 
1902   // Drop the connection
1903   hqSession_->dropConnection();
1904   flushAndLoop();
1905 }
1906 
TEST_P(HQUpstreamSessionTestHQPush,TestOrphanedPushStream)1907 TEST_P(HQUpstreamSessionTestHQPush, TestOrphanedPushStream) {
1908   // the transaction is expected to timeout, since the PushPromise does not have
1909   // EOF set, and it is not followed by a PushStream.
1910   assocHandler_->expectError();
1911 
1912   hq::PushId pushId = nextPushId();
1913 
1914   HTTPMessage resp;
1915   resp.setStatusCode(200);
1916   createPushStream(pushId, resp, makeBuf(100), true);
1917 
1918   assocHandler_->txn_->sendEOM();
1919 
1920   hqSession_->closeWhenIdle();
1921   flushAndLoop();
1922 }
1923 
TEST_P(HQUpstreamSessionTestHQ,TestNoDatagram)1924 TEST_P(HQUpstreamSessionTestHQ, TestNoDatagram) {
1925   EXPECT_FALSE(httpCallbacks_.datagramEnabled);
1926   auto handler = openTransaction();
1927   EXPECT_EQ(handler->txn_->getDatagramSizeLimit(), 0);
1928   auto resp = makeResponse(200, 100);
1929   sendResponse(handler->txn_->getID(),
1930                *std::get<0>(resp),
1931                std::move(std::get<1>(resp)),
1932                true);
1933   handler->txn_->sendHeaders(getGetRequest());
1934   handler->txn_->sendEOM();
1935   handler->expectHeaders();
1936   handler->expectBody();
1937   handler->expectEOM();
1938   handler->expectDetachTransaction();
1939   hqSession_->closeWhenIdle();
1940   flushAndLoop();
1941 }
1942 
TEST_P(HQUpstreamSessionTestHQDatagram,TestDatagramSettings)1943 TEST_P(HQUpstreamSessionTestHQDatagram, TestDatagramSettings) {
1944   EXPECT_TRUE(httpCallbacks_.datagramEnabled);
1945   auto handler = openTransaction();
1946   EXPECT_GT(handler->txn_->getDatagramSizeLimit(), 0);
1947   auto resp = makeResponse(200, 100);
1948   sendResponse(handler->txn_->getID(),
1949                *std::get<0>(resp),
1950                std::move(std::get<1>(resp)),
1951                true);
1952   handler->txn_->sendHeaders(getGetRequest());
1953   handler->txn_->sendEOM();
1954   handler->expectHeaders();
1955   handler->expectBody();
1956   handler->expectEOM();
1957   handler->expectDetachTransaction();
1958   hqSession_->closeWhenIdle();
1959   flushAndLoop();
1960 }
1961 
TEST_P(HQUpstreamSessionTestHQDatagram,TestReceiveDatagram)1962 TEST_P(HQUpstreamSessionTestHQDatagram, TestReceiveDatagram) {
1963   EXPECT_TRUE(httpCallbacks_.datagramEnabled);
1964   auto handler = openTransaction();
1965   auto id = handler->txn_->getID();
1966   EXPECT_GT(handler->txn_->getDatagramSizeLimit(), 0);
1967   MockHTTPTransactionTransportCallback transportCallback_;
1968   handler->txn_->setTransportCallback(&transportCallback_);
1969   EXPECT_CALL(transportCallback_, datagramBytesReceived(::testing::_)).Times(1);
1970   handler->txn_->sendHeaders(getGetRequest());
1971   handler->txn_->sendEOM();
1972   auto resp = makeResponse(200, 0);
1973   sendResponse(id, *std::get<0>(resp), std::move(std::get<1>(resp)), false);
1974   handler->expectHeaders();
1975   flushAndLoopN(1);
1976   auto h3Datagram = getH3Datagram(id, folly::IOBuf::wrapBuffer("testtest", 8));
1977   socketDriver_->addDatagram(std::move(h3Datagram));
1978   handler->expectDatagram();
1979   flushAndLoopN(1);
1980   auto it = streams_.find(id);
1981   CHECK(it != streams_.end());
1982   auto& stream = it->second;
1983   stream.readEOF = true;
1984   handler->expectEOM();
1985   handler->expectDetachTransaction();
1986   hqSession_->closeWhenIdle();
1987   flushAndLoop();
1988 }
1989 
TEST_P(HQUpstreamSessionTestHQDatagram,TestReceiveEarlyDatagramsSingleStream)1990 TEST_P(HQUpstreamSessionTestHQDatagram, TestReceiveEarlyDatagramsSingleStream) {
1991   EXPECT_TRUE(httpCallbacks_.datagramEnabled);
1992   auto handler = openTransaction();
1993   auto id = handler->txn_->getID();
1994   EXPECT_GT(handler->txn_->getDatagramSizeLimit(), 0);
1995   handler->txn_->sendHeaders(getGetRequest());
1996   handler->txn_->sendEOM();
1997   for (auto i = 0; i < kDefaultMaxBufferedDatagrams * 2; ++i) {
1998     auto h3Datagram =
1999         getH3Datagram(id, folly::IOBuf::wrapBuffer("testtest", 8));
2000     socketDriver_->addDatagram(std::move(h3Datagram));
2001   }
2002   flushAndLoopN(1);
2003   auto resp = makeResponse(200, 0);
2004   sendResponse(id, *std::get<0>(resp), std::move(std::get<1>(resp)), false);
2005   handler->expectHeaders();
2006   EXPECT_CALL(*handler, onDatagram(testing::_))
2007       .Times(kDefaultMaxBufferedDatagrams);
2008   flushAndLoopN(1);
2009   auto it = streams_.find(id);
2010   CHECK(it != streams_.end());
2011   auto& stream = it->second;
2012   stream.readEOF = true;
2013   handler->expectEOM();
2014   handler->expectDetachTransaction();
2015   hqSession_->closeWhenIdle();
2016   flushAndLoop();
2017 }
2018 
TEST_P(HQUpstreamSessionTestHQDatagram,TestReceiveEarlyDatagramsMultiStream)2019 TEST_P(HQUpstreamSessionTestHQDatagram, TestReceiveEarlyDatagramsMultiStream) {
2020   auto deliveredDatagrams = 0;
2021   EXPECT_TRUE(httpCallbacks_.datagramEnabled);
2022   std::vector<std::unique_ptr<StrictMock<MockHTTPHandler>>> handlers;
2023 
2024   for (auto i = 0; i < kMaxStreamsWithBufferedDatagrams * 2; ++i) {
2025     handlers.emplace_back(openTransaction());
2026     auto handler = handlers.back().get();
2027     auto id = handler->txn_->getID();
2028     EXPECT_GT(handler->txn_->getDatagramSizeLimit(), 0);
2029     handler->txn_->sendHeaders(getGetRequest());
2030     handler->txn_->sendEOM();
2031     auto h3Datagram =
2032         getH3Datagram(id, folly::IOBuf::wrapBuffer("testtest", 8));
2033     socketDriver_->addDatagram(std::move(h3Datagram));
2034     flushAndLoopN(1);
2035   }
2036 
2037   for (const auto& handler : handlers) {
2038     auto id = handler->txn_->getID();
2039     auto resp = makeResponse(200, 0);
2040     sendResponse(id, *std::get<0>(resp), std::move(std::get<1>(resp)), false);
2041     handler->expectHeaders();
2042     EXPECT_CALL(*handler, onDatagram(testing::_))
2043         .WillRepeatedly(InvokeWithoutArgs([&]() { deliveredDatagrams++; }));
2044     flushAndLoopN(1);
2045     auto it = streams_.find(id);
2046     CHECK(it != streams_.end());
2047     auto& stream = it->second;
2048     stream.readEOF = true;
2049     handler->expectEOM();
2050     handler->expectDetachTransaction();
2051     flushAndLoopN(1);
2052   }
2053   EXPECT_EQ(deliveredDatagrams, kMaxStreamsWithBufferedDatagrams);
2054   hqSession_->closeWhenIdle();
2055   flushAndLoop();
2056 }
2057 
2058 /**
2059  * Instantiate the Parametrized test cases
2060  */
2061 
2062 // Make sure all the tests keep working with all the supported protocol versions
2063 INSTANTIATE_TEST_CASE_P(HQUpstreamSessionTest,
2064                         HQUpstreamSessionTest,
2065                         Values(
__anon346abe7d2902null2066                             [] {
2067                               TestParams tp;
2068                               tp.alpn_ = "h1q-fb";
2069                               return tp;
2070                             }(),
__anon346abe7d2a02null2071                             [] {
2072                               TestParams tp;
2073                               tp.alpn_ = "h1q-fb-v2";
2074                               return tp;
2075                             }(),
__anon346abe7d2b02null2076                             [] {
2077                               TestParams tp;
2078                               tp.alpn_ = "h3";
2079                               return tp;
2080                             }()),
2081                         paramsToTestName);
2082 
2083 // Instantiate h1q-fb-v2 and hq only tests (goaway tests)
2084 INSTANTIATE_TEST_CASE_P(HQUpstreamSessionTest,
2085                         HQUpstreamSessionTestH1qv2HQ,
2086                         Values(
__anon346abe7d2c02null2087                             [] {
2088                               TestParams tp;
2089                               tp.alpn_ = "h1q-fb-v2";
2090                               return tp;
2091                             }(),
__anon346abe7d2d02null2092                             [] {
2093                               TestParams tp;
2094                               tp.alpn_ = "h3";
2095                               return tp;
2096                             }()),
2097                         paramsToTestName);
2098 
2099 // Instantiate h1q-fb-v1 only tests
2100 INSTANTIATE_TEST_CASE_P(HQUpstreamSessionTest,
2101                         HQUpstreamSessionTestH1qv1,
__anon346abe7d2e02null2102                         Values([] {
2103                           TestParams tp;
2104                           tp.alpn_ = "h1q-fb";
2105                           return tp;
2106                         }()),
2107                         paramsToTestName);
2108 
2109 // Instantiate hq only tests
2110 INSTANTIATE_TEST_CASE_P(HQUpstreamSessionTest,
2111                         HQUpstreamSessionTestHQ,
__anon346abe7d2f02null2112                         Values([] {
2113                           TestParams tp;
2114                           tp.alpn_ = "h3";
2115                           return tp;
2116                         }()),
2117                         paramsToTestName);
2118 
2119 // Instantiate tests for H3 Push functionality (requires HQ)
2120 INSTANTIATE_TEST_CASE_P(HQUpstreamSessionTest,
2121                         HQUpstreamSessionTestHQPush,
__anon346abe7d3002null2122                         Values([] {
2123                           TestParams tp;
2124                           tp.alpn_ = "h3";
2125                           tp.unidirectionalStreamsCredit = 4;
2126                           return tp;
2127                         }()),
2128                         paramsToTestName);
2129 
2130 // Instantiate tests with QPACK on/off
2131 INSTANTIATE_TEST_CASE_P(HQUpstreamSessionTest,
2132                         HQUpstreamSessionTestQPACK,
2133                         Values(
__anon346abe7d3102null2134                             [] {
2135                               TestParams tp;
2136                               tp.alpn_ = "h3";
2137                               return tp;
2138                             }(),
__anon346abe7d3202null2139                             [] {
2140                               TestParams tp;
2141                               tp.alpn_ = "h3";
2142                               tp.createQPACKStreams_ = false;
2143                               return tp;
2144                             }()),
2145                         paramsToTestName);
2146 
2147 // Instantiate h3 datagram tests
2148 INSTANTIATE_TEST_CASE_P(HQUpstreamSessionTest,
2149                         HQUpstreamSessionTestHQDatagram,
__anon346abe7d3302null2150                         Values([] {
2151                           TestParams tp;
2152                           tp.alpn_ = "h3";
2153                           tp.datagrams_ = true;
2154                           return tp;
2155                         }()),
2156                         paramsToTestName);
2157