proxygen
HuffmanTests.cpp File Reference

Go to the source code of this file.

Classes

class  HuffmanTests
 
class  TestingHuffTree
 

Functions

 TEST_F (HuffmanTests, Codes)
 
 TEST_F (HuffmanTests, Size)
 
 TEST_F (HuffmanTests, Encode)
 
 TEST_F (HuffmanTests, Decode)
 
 TEST_F (HuffmanTests, NonPrintableDecode)
 
 TEST_F (HuffmanTests, ExampleCom)
 
 TEST_F (HuffmanTests, UserAgent)
 
 TEST_F (HuffmanTests, FitInBuffer)
 
uint32_t treeDfs (const SuperHuffNode *allSnodes, const uint32_t &snodeIndex, const uint32_t &depth, const uint32_t &fullCode, const uint32_t &eosCode, const uint32_t &eosCodeBits)
 
 TEST_F (HuffmanTests, SanityChecks)
 

Function Documentation

TEST_F ( HuffmanTests  ,
Codes   
)

Definition at line 29 of file HuffmanTests.cpp.

References EXPECT_EQ, uint32_t, and uint8_t.

29  {
30  uint32_t code;
31  uint8_t bits;
32  // check 'e' for both requests and responses
33  tie(code, bits) = tree_.getCode('e');
34  EXPECT_EQ(code, 0x05);
35  EXPECT_EQ(bits, 5);
36  // some extreme cases
37  tie(code, bits) = tree_.getCode(0);
38  EXPECT_EQ(code, 0x1ff8);
39  EXPECT_EQ(bits, 13);
40  tie(code, bits) = tree_.getCode(255);
41  EXPECT_EQ(code, 0x3ffffee);
42  EXPECT_EQ(bits, 26);
43 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TEST_F ( HuffmanTests  ,
Size   
)

Definition at line 45 of file HuffmanTests.cpp.

References folly::netops::accept(), EXPECT_EQ, folly::size(), and uint32_t.

45  {
46  uint32_t size;
47  folly::fbstring onebyte("x");
48  size = tree_.getEncodeSize(onebyte);
49  EXPECT_EQ(size, 1);
50 
51  folly::fbstring accept("accept-encoding");
52  size = tree_.getEncodeSize(accept);
53  EXPECT_EQ(size, 11);
54 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
NetworkSocket accept(NetworkSocket s, sockaddr *addr, socklen_t *addrlen)
Definition: NetOps.cpp:71
TEST_F ( HuffmanTests  ,
Encode   
)

Definition at line 56 of file HuffmanTests.cpp.

References folly::netops::accept(), folly::data(), folly::IOBuf::data(), folly::io::QueueAppender::ensure(), EXPECT_EQ, folly::IOBufQueue::front(), folly::size(), uint32_t, and uint8_t.

56  {
57  uint32_t size;
58  // this is going to fit perfectly into 3 bytes
59  folly::fbstring gzip("gzip");
60  IOBufQueue bufQueue;
61  QueueAppender appender(&bufQueue, 512);
62  // force the allocation
63  appender.ensure(512);
64 
65  size = tree_.encode(gzip, appender);
66  EXPECT_EQ(size, 3);
67  const IOBuf* buf = bufQueue.front();
68  const uint8_t* data = buf->data();
69  EXPECT_EQ(data[0], 0x9b); // 10011011
70  EXPECT_EQ(data[1], 0xd9); // 11011001
71  EXPECT_EQ(data[2], 0xab); // 10101011
72 
73  // size must equal with the actual encoding
74  folly::fbstring accept("accept-encoding");
75  size = tree_.getEncodeSize(accept);
76  uint32_t encodedSize = tree_.encode(accept, appender);
77  EXPECT_EQ(size, encodedSize);
78 }
const folly::IOBuf * front() const
Definition: IOBufQueue.h:476
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
const uint8_t * data() const
Definition: IOBuf.h:499
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
NetworkSocket accept(NetworkSocket s, sockaddr *addr, socklen_t *addrlen)
Definition: NetOps.cpp:71
TEST_F ( HuffmanTests  ,
Decode   
)

Definition at line 80 of file HuffmanTests.cpp.

References buffer(), folly::basic_fbstring< E, T, A, Storage >::clear(), EXPECT_EQ, and uint8_t.

80  {
81  uint8_t buffer[3];
82  // simple test with one byte
83  buffer[0] = 0x60; //
84  buffer[1] = 0xbf; //
85  folly::fbstring literal;
86  tree_.decode(buffer, 2, literal);
87  EXPECT_EQ(literal, "/e");
88 
89  // simple test with "gzip"
90  buffer[0] = 0x9b;
91  buffer[1] = 0xd9;
92  buffer[2] = 0xab;
93  literal.clear();
94  tree_.decode(buffer, 3, literal);
95  EXPECT_EQ(literal, "gzip");
96 
97  // something with padding
98  buffer[0] = 0x98;
99  buffer[1] = 0xbf;
100  literal.clear();
101  tree_.decode(buffer, 2, literal);
102  EXPECT_EQ(literal, "ge");
103 }
std::vector< uint8_t > buffer(kBufferSize+16)
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TEST_F ( HuffmanTests  ,
NonPrintableDecode   
)

Definition at line 108 of file HuffmanTests.cpp.

References EXPECT_EQ, folly::basic_fbstring< E, T, A, Storage >::size(), and uint8_t.

108  {
109  // character code 9 and 38 (&) that have 24 + 8 = 32 bits
110  uint8_t buffer1[4] = {
111  0xFF, 0xFF, 0xEA, 0xF8
112  };
113  folly::fbstring literal;
114  tree_.decode(buffer1, 4, literal);
115  EXPECT_EQ(literal.size(), 2);
116  EXPECT_EQ((uint8_t)literal[0], 9);
117  EXPECT_EQ((uint8_t)literal[1], 38);
118 
119  // two weird characters and padding
120  // 1 and 240 will have 26 + 23 = 49 bits + 7 bits padding
121  uint8_t buffer2[7] = {
122  0xFF, 0xFF, 0xB1, 0xFF, 0xFF, 0xF5, 0xFF
123  };
124  literal.clear();
125  tree_.decode(buffer2, 7, literal);
126  EXPECT_EQ(literal.size(), 2);
127  EXPECT_EQ((uint8_t) literal[0], 1);
128  EXPECT_EQ((uint8_t) literal[1], 240);
129 }
size_type size() const
Definition: FBString.h:1337
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
TEST_F ( HuffmanTests  ,
ExampleCom   
)

Definition at line 131 of file HuffmanTests.cpp.

References folly::IOBuf::data(), folly::io::QueueAppender::ensure(), EXPECT_EQ, folly::IOBufQueue::front(), folly::size(), and uint32_t.

131  {
132  // interesting case of one bit with value 0 in the last byte
133  IOBufQueue bufQueue;
134  QueueAppender appender(&bufQueue, 512);
135  appender.ensure(512);
136 
137  folly::fbstring example("www.example.com");
138  uint32_t size = tree_.getEncodeSize(example);
139  EXPECT_EQ(size, 12);
140  uint32_t encodedSize = tree_.encode(example, appender);
141  EXPECT_EQ(size, encodedSize);
142 
143  folly::fbstring decoded;
144  tree_.decode(bufQueue.front()->data(), size, decoded);
145  CHECK_EQ(example, decoded);
146 }
const folly::IOBuf * front() const
Definition: IOBufQueue.h:476
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
const uint8_t * data() const
Definition: IOBuf.h:499
Definition: lib.cpp:18
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
TEST_F ( HuffmanTests  ,
UserAgent   
)

Definition at line 148 of file HuffmanTests.cpp.

References folly::IOBuf::data(), proxygen::huffman::HuffTree::decode(), proxygen::huffman::HuffTree::encode(), folly::io::QueueAppender::ensure(), EXPECT_EQ, folly::IOBufQueue::front(), proxygen::huffman::HuffTree::getEncodeSize(), proxygen::huffman::huffTree(), folly::size(), and uint32_t.

148  {
149  folly::fbstring user_agent(
150  "Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51"
151  ".1 (KHTML, like Gecko) Mobile/11B554a [FBAN/FBIOS;FBAV/6.7;FBBV/566055;FBD"
152  "V/iPhone5,1;FBMD/iPhone;FBSN/iPhone OS;FBSV/7.0.4;FBSS/2; FBCR/AT&T;FBID/p"
153  "hone;FBLC/en_US;FBOP/5]");
154  IOBufQueue bufQueue;
155  QueueAppender appender(&bufQueue, 512);
156  appender.ensure(512);
157  const HuffTree& tree = huffTree();
158  uint32_t size = tree.getEncodeSize(user_agent);
159  uint32_t encodedSize = tree.encode(user_agent, appender);
160  EXPECT_EQ(size, encodedSize);
161 
162  folly::fbstring decoded;
163  tree.decode(bufQueue.front()->data(), size, decoded);
164  CHECK_EQ(user_agent, decoded);
165 }
const folly::IOBuf * front() const
Definition: IOBufQueue.h:476
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
const uint8_t * data() const
Definition: IOBuf.h:499
uint32_t encode(folly::StringPiece literal, folly::io::QueueAppender &buf) const
Definition: Huffman.cpp:133
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
uint32_t getEncodeSize(folly::StringPiece literal) const
Definition: Huffman.cpp:182
const HuffTree & huffTree()
Definition: Huffman.cpp:252
bool decode(const uint8_t *buf, uint32_t size, folly::fbstring &literal) const
Definition: Huffman.cpp:31
TEST_F ( HuffmanTests  ,
FitInBuffer   
)

Definition at line 170 of file HuffmanTests.cpp.

References folly::io::QueueAppender::append(), folly::io::QueueAppender::ensure(), and folly::io::QueueAppender::length().

170  {
171  IOBufQueue bufQueue;
172  QueueAppender appender(&bufQueue, 128);
173 
174  // call with an empty string
175  folly::fbstring literal("");
176  tree_.encode(literal, appender);
177 
178  // allow just 1 byte
179  appender.ensure(128);
180  appender.append(appender.length() - 1);
181  literal = "g";
182  tree_.encode(literal, appender);
183  CHECK_EQ(appender.length(), 0);
184 }
TEST_F ( HuffmanTests  ,
SanityChecks   
)

Definition at line 280 of file HuffmanTests.cpp.

References EXPECT_EQ, TestingHuffTree::getHuffTree(), TestingHuffTree::getInternalTable(), treeDfs(), and uint32_t.

280  {
282  const SuperHuffNode* allSnodesReq = reqTree.getInternalTable();
283  uint32_t totalReqChars = treeDfs(allSnodesReq, 0, 0, 0, 0x3fffffff, 30);
284  EXPECT_EQ(totalReqChars, 256);
285 }
uint32_t treeDfs(const SuperHuffNode *allSnodes, const uint32_t &snodeIndex, const uint32_t &depth, const uint32_t &fullCode, const uint32_t &eosCode, const uint32_t &eosCodeBits)
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static TestingHuffTree getHuffTree()
const SuperHuffNode * getInternalTable()
uint32_t treeDfs ( const SuperHuffNode allSnodes,
const uint32_t snodeIndex,
const uint32_t depth,
const uint32_t fullCode,
const uint32_t eosCode,
const uint32_t eosCodeBits 
)

Definition at line 199 of file HuffmanTests.cpp.

References proxygen::huffman::HuffNode::bits, proxygen::huffman::HuffNode::ch, proxygen::huffman::HuffNode::data, EXPECT_TRUE, i, proxygen::huffman::SuperHuffNode::index, proxygen::huffman::HuffNode::isLeaf(), proxygen::huffman::HuffNode::metadata, proxygen::huffman::HuffNode::superNodeIndex, and uint32_t.

Referenced by TEST_F().

205  {
206 
207  EXPECT_TRUE(depth < 4);
208 
209  unordered_set<uint32_t> leaves;
210  uint32_t subtreeLeafCount = 0;
211 
212  for (uint32_t i = 0; i < 256; i++) {
213  const HuffNode& node = allSnodes[snodeIndex].index[i];
214 
215  uint32_t newFullCode = fullCode ^ (i << (24 - 8 * depth));
216  uint32_t eosCodeDepth = (eosCodeBits - 1) / 8;
217 
218  if(eosCodeDepth == depth
219  && (newFullCode >> (32 - eosCodeBits)) == eosCode) {
220 
221  // this condition corresponds to an EOS code
222  // this should be a leaf that doesn't have supernode or bits set
223 
224  EXPECT_TRUE(node.isLeaf());
225  EXPECT_TRUE(node.metadata.bits == 0);
226  } else if (node.isLeaf()) {
227 
228  // this condition is a normal leaf
229  // this should have bits set
230 
231  EXPECT_TRUE(node.isLeaf());
232  EXPECT_TRUE(node.metadata.bits > 0);
233  EXPECT_TRUE(node.metadata.bits <= 8);
234 
235  // used to count unique leaves at this node
236  leaves.insert(node.data.ch);
237  } else {
238 
239  // this condition is a branching node
240  // this should have the superNodeIndex set but not bits should be set
241 
242  EXPECT_TRUE(!node.isLeaf());
243  EXPECT_TRUE(node.data.superNodeIndex > 0);
244  EXPECT_TRUE(node.metadata.bits == 0);
245  EXPECT_TRUE(node.data.superNodeIndex < 46);
246 
247  // keep track of leaf counts for this subtree
248  subtreeLeafCount += treeDfs(
249  allSnodes,
250  node.data.superNodeIndex,
251  depth + 1,
252  newFullCode,
253  eosCode,
254  eosCodeBits);
255  }
256  }
257  return subtreeLeafCount + leaves.size();
258 }
uint32_t treeDfs(const SuperHuffNode *allSnodes, const uint32_t &snodeIndex, const uint32_t &depth, const uint32_t &fullCode, const uint32_t &eosCode, const uint32_t &eosCodeBits)
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859