proxygen
TestUtil.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015-present, Facebook, Inc.
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. An additional grant
7  * of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
12 
13 #include <fstream>
14 #include <glog/logging.h>
15 #include <folly/io/Cursor.h>
18 
19 using folly::IOBuf;
20 using std::ofstream;
21 using std::string;
22 using std::unique_ptr;
23 using std::vector;
24 
25 namespace proxygen { namespace hpack {
26 
27 void dumpToFile(const string& filename, const IOBuf* buf) {
28  ofstream outfile(filename, ofstream::binary);
29  if (buf) {
30  const IOBuf* p = buf;
31  do {
32  outfile.write((const char *)p->data(), p->length());
33  p = p->next();
34  } while (p->next() != buf);
35  }
36  outfile.close();
37 }
38 
39 void verifyHeaders(vector<HPACKHeader>& headers,
40  vector<HPACKHeader>& decodedHeaders) {
41  EXPECT_EQ(headers.size(), decodedHeaders.size());
42  std::sort(decodedHeaders.begin(), decodedHeaders.end());
43  std::sort(headers.begin(), headers.end());
44  if (headers.size() != decodedHeaders.size()) {
45  std::cerr << printDelta(decodedHeaders, headers);
46  CHECK(false) << "Mismatched headers size";
47  }
48  EXPECT_EQ(headers, decodedHeaders);
49  if (headers != decodedHeaders) {
50  std::cerr << printDelta(headers, decodedHeaders);
51  CHECK(false) << "Mismatched headers";
52  }
53 }
54 
55 unique_ptr<IOBuf> encodeDecode(
56  vector<HPACKHeader>& headers,
57  HPACKEncoder& encoder,
58  HPACKDecoder& decoder) {
59  unique_ptr<IOBuf> encoded = encoder.encode(headers);
60  auto decodedHeaders = hpack::decode(decoder, encoded.get());
61  CHECK(!decoder.hasError());
62 
63  verifyHeaders(headers, *decodedHeaders);
64 
65  // header tables should look the same
66  CHECK(encoder.getTable() == decoder.getTable());
67  EXPECT_EQ(encoder.getTable(), decoder.getTable());
68 
69  return encoded;
70 }
71 
73  vector<HPACKHeader>& headers,
74  QPACKEncoder& encoder,
75  QPACKDecoder& decoder) {
76  auto encoded = encoder.encode(headers, 0, 1);
78  if (encoded.control) {
79  decoder.decodeEncoderStream(std::move(encoded.control));
80  encoder.decodeDecoderStream(decoder.encodeTableStateSync());
81  }
82  CHECK(encoded.stream);
83  auto length = encoded.stream->computeChainDataLength();
84  decoder.decodeStreaming(1, std::move(encoded.stream), length, &cb);
85  CHECK(!cb.hasError());
86  auto decodedHeaders = cb.hpackHeaders();
87  verifyHeaders(headers, *decodedHeaders);
88  encoder.decodeDecoderStream(decoder.encodeHeaderAck(1));
89 
90  // header tables should look the same
91  CHECK(encoder.getTable() == decoder.getTable());
92  EXPECT_EQ(encoder.getTable(), decoder.getTable());
93 }
94 
95 unique_ptr<HPACKDecoder::headers_t> decode(HPACKDecoder& decoder,
96  const IOBuf* buffer) {
97  auto headers = std::make_unique<HPACKDecoder::headers_t>();
98  folly::io::Cursor cursor(buffer);
99  uint32_t totalBytes = buffer ? cursor.totalLength() : 0;
101  decoder.decodeStreaming(cursor, totalBytes, &cb);
102  if (cb.hasError()) {
103  return headers;
104  }
105  return cb.hpackHeaders();
106 }
107 
108 vector<compress::Header> headersFromArray(vector<vector<string>>& a) {
109  vector<compress::Header> headers;
110  for (auto& ha : a) {
111  headers.push_back(compress::Header::makeHeaderForTest(ha[0], ha[1]));
112  }
113  return headers;
114 }
115 
116 vector<compress::Header> basicHeaders() {
117  static vector<vector<string>> headersStrings = {
118  {":path", "/index.php"},
119  {":authority", "www.facebook.com"},
120  {":method", "GET"},
121  {":scheme", "https"},
122  {"Host", "www.facebook.com"},
123  {"accept-encoding", "gzip"}
124  };
125  static vector<compress::Header> headers = headersFromArray(headersStrings);
126  return headers;
127 }
128 
129 }}
unique_ptr< IOBuf > encodeDecode(vector< HPACKHeader > &headers, HPACKEncoder &encoder, HPACKDecoder &decoder)
Definition: TestUtil.cpp:55
std::vector< uint8_t > buffer(kBufferSize+16)
std::unique_ptr< folly::IOBuf > encodeTableStateSync()
HPACK::DecodeError decodeEncoderStream(std::unique_ptr< folly::IOBuf > buf)
void verifyHeaders(vector< HPACKHeader > &headers, vector< HPACKHeader > &decodedHeaders)
Definition: TestUtil.cpp:39
vector< compress::Header > basicHeaders()
Definition: TestUtil.cpp:116
const QPACKHeaderTable & getTable() const
Definition: QPACKContext.h:29
std::unique_ptr< std::vector< HPACKHeader > > hpackHeaders() const
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
vector< compress::Header > headersFromArray(vector< vector< string >> &a)
Definition: TestUtil.cpp:108
const uint8_t * data() const
Definition: IOBuf.h:499
HPACK::DecodeError decodeDecoderStream(std::unique_ptr< folly::IOBuf > buf)
string printDelta(const vector< HPACKHeader > &v1, const vector< HPACKHeader > &v2)
Definition: Logging.cpp:38
EncodeResult encode(const std::vector< HPACKHeader > &headers, uint32_t headroom, uint64_t streamId)
unique_ptr< HPACKDecoder::headers_t > decode(HPACKDecoder &decoder, const IOBuf *buffer)
Definition: TestUtil.cpp:95
void decodeStreaming(uint64_t streamId, std::unique_ptr< folly::IOBuf > block, uint32_t totalBytes, HPACK::StreamingCallback *streamingCb)
std::size_t length() const
Definition: IOBuf.h:533
char a
IOBuf * next()
Definition: IOBuf.h:600
void decodeStreaming(folly::io::Cursor &cursor, uint32_t totalBytes, HPACK::StreamingCallback *streamingCb)
const HeaderTable & getTable() const
Definition: HPACKContext.h:48
std::unique_ptr< folly::IOBuf > encode(const std::vector< HPACKHeader > &headers, uint32_t headroom=0)
void dumpToFile(const string &filename, const IOBuf *buf)
Definition: TestUtil.cpp:27
const char * string
Definition: Conv.cpp:212
std::unique_ptr< folly::IOBuf > encodeHeaderAck(uint64_t streamId) const
static Header makeHeaderForTest(const std::string &n, const std::string &v)
Definition: Header.h:41