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 #pragma once 10 #include <folly/portability/GTest.h> 11 #include <proxygen/lib/http/codec/HTTPParallelCodec.h> 12 #include <proxygen/lib/http/codec/test/TestUtils.h> 13 #include <proxygen/lib/utils/Logging.h> 14 15 class HTTPParallelCodecTest : public testing::Test { 16 public: HTTPParallelCodecTest(proxygen::HTTPParallelCodec & upstreamCodec,proxygen::HTTPParallelCodec & downstreamCodec)17 HTTPParallelCodecTest(proxygen::HTTPParallelCodec& upstreamCodec, 18 proxygen::HTTPParallelCodec& downstreamCodec) 19 : upstreamCodec_(upstreamCodec), downstreamCodec_(downstreamCodec) { 20 } 21 SetUp()22 void SetUp() override { 23 downstreamCodec_.setCallback(&callbacks_); 24 upstreamCodec_.setCallback(&callbacks_); 25 // Most tests are downstream tests, so generate the upstream conn preface 26 // by default 27 upstreamCodec_.generateConnectionPreface(output_); 28 } 29 SetUpUpstreamTest()30 void SetUpUpstreamTest() { 31 output_.move(); 32 downstreamCodec_.generateConnectionPreface(output_); // no-op 33 downstreamCodec_.generateSettings(output_); 34 } 35 36 bool parse(std::function<void(folly::IOBuf*)> hackIngress = 37 std::function<void(folly::IOBuf*)>()) { 38 return parseImpl(downstreamCodec_, hackIngress); 39 } 40 41 bool parseUpstream(std::function<void(folly::IOBuf*)> hackIngress = 42 std::function<void(folly::IOBuf*)>()) { 43 return parseImpl(upstreamCodec_, hackIngress); 44 } 45 46 /* 47 * hackIngress is used to keep the codec's strict checks while having 48 * separate checks for tests 49 */ parseImpl(proxygen::HTTPParallelCodec & codec,std::function<void (folly::IOBuf *)> hackIngress)50 bool parseImpl(proxygen::HTTPParallelCodec& codec, 51 std::function<void(folly::IOBuf*)> hackIngress) { 52 dumpToFile(codec.getTransportDirection() == 53 proxygen::TransportDirection::UPSTREAM); 54 auto ingress = output_.move(); 55 if (hackIngress) { 56 hackIngress(ingress.get()); 57 } 58 size_t parsed = codec.onIngress(*ingress); 59 return (parsed == ingress->computeChainDataLength()); 60 } 61 62 /* 63 * dumpToFile dumps binary frames to files ("/tmp/http2_*.bin"), 64 * allowing debugging individual frames. 65 * @note: assign true to dump_ to turn on dumpToFile 66 */ 67 void dumpToFile(bool isUpstream = false) { 68 if (!dump_) { 69 return; 70 } 71 auto endpoint = isUpstream ? "client" : "server"; 72 auto filename = folly::to<std::string>( 73 "/tmp/parallel_", endpoint, "_", testInfo_->name(), ".bin"); 74 proxygen::dumpBinToFile(filename, output_.front()); 75 } 76 77 protected: 78 proxygen::FakeHTTPCodecCallback callbacks_; 79 proxygen::HTTPParallelCodec& upstreamCodec_; 80 proxygen::HTTPParallelCodec& downstreamCodec_; 81 folly::IOBufQueue output_{folly::IOBufQueue::cacheChainLength()}; 82 const testing::TestInfo* testInfo_{ 83 testing::UnitTest::GetInstance()->current_test_info()}; 84 bool dump_{false}; 85 }; 86