OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/spdy/hpack_huffman_table.h" | 5 #include "net/spdy/hpack_huffman_table.h" |
6 | 6 |
7 #include <bitset> | 7 #include <bitset> |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 i += j; | 79 i += j; |
80 } | 80 } |
81 } | 81 } |
82 | 82 |
83 private: | 83 private: |
84 const HpackHuffmanTable& table_; | 84 const HpackHuffmanTable& table_; |
85 }; | 85 }; |
86 | 86 |
87 namespace { | 87 namespace { |
88 | 88 |
| 89 class HpackHuffmanTableTest : public ::testing::Test { |
| 90 protected: |
| 91 HpackHuffmanTableTest() |
| 92 : table_(), |
| 93 peer_(table_) {} |
| 94 |
| 95 string EncodeString(StringPiece input) { |
| 96 string result; |
| 97 HpackOutputStream output_stream; |
| 98 table_.EncodeString(input, &output_stream); |
| 99 |
| 100 output_stream.TakeString(&result); |
| 101 // Verify EncodedSize() agrees with EncodeString(). |
| 102 EXPECT_EQ(result.size(), table_.EncodedSize(input)); |
| 103 return result; |
| 104 } |
| 105 |
| 106 HpackHuffmanTable table_; |
| 107 HpackHuffmanTablePeer peer_; |
| 108 }; |
| 109 |
89 MATCHER(DecodeEntryEq, "") { | 110 MATCHER(DecodeEntryEq, "") { |
90 const DecodeEntry& lhs = std::tr1::get<0>(arg); | 111 const DecodeEntry& lhs = std::tr1::get<0>(arg); |
91 const DecodeEntry& rhs = std::tr1::get<1>(arg); | 112 const DecodeEntry& rhs = std::tr1::get<1>(arg); |
92 return lhs.next_table_index == rhs.next_table_index && | 113 return lhs.next_table_index == rhs.next_table_index && |
93 lhs.length == rhs.length && | 114 lhs.length == rhs.length && |
94 lhs.symbol_id == rhs.symbol_id; | 115 lhs.symbol_id == rhs.symbol_id; |
95 } | 116 } |
96 | 117 |
97 uint32 bits32(const string& bitstring) { | 118 uint32 bits32(const string& bitstring) { |
98 return std::bitset<32>(bitstring).to_ulong(); | 119 return std::bitset<32>(bitstring).to_ulong(); |
99 } | 120 } |
100 char bits8(const string& bitstring) { | 121 char bits8(const string& bitstring) { |
101 return static_cast<char>(std::bitset<8>(bitstring).to_ulong()); | 122 return static_cast<char>(std::bitset<8>(bitstring).to_ulong()); |
102 } | 123 } |
103 | 124 |
104 TEST(HpackHuffmanTableTest, InitializeHpackCode) { | 125 TEST_F(HpackHuffmanTableTest, InitializeHpackCode) { |
105 HpackHuffmanTable table; | |
106 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); | 126 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); |
107 EXPECT_TRUE(table.Initialize(&code[0], code.size())); | 127 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); |
108 EXPECT_TRUE(table.IsInitialized()); | 128 EXPECT_TRUE(table_.IsInitialized()); |
109 EXPECT_EQ(HpackHuffmanTablePeer(table).pad_bits(), | 129 EXPECT_EQ(peer_.pad_bits(), bits8("11111111")); // First 8 bits of EOS. |
110 bits8("11111111")); // First 8 bits of EOS. | |
111 } | 130 } |
112 | 131 |
113 TEST(HpackHuffmanTableTest, InitializeEdgeCases) { | 132 TEST_F(HpackHuffmanTableTest, InitializeEdgeCases) { |
114 { | 133 { |
115 // Verify eight symbols can be encoded with 3 bits per symbol. | 134 // Verify eight symbols can be encoded with 3 bits per symbol. |
116 HpackHuffmanSymbol code[] = { | 135 HpackHuffmanSymbol code[] = { |
117 {bits32("00000000000000000000000000000000"), 3, 0}, | 136 {bits32("00000000000000000000000000000000"), 3, 0}, |
118 {bits32("00100000000000000000000000000000"), 3, 1}, | 137 {bits32("00100000000000000000000000000000"), 3, 1}, |
119 {bits32("01000000000000000000000000000000"), 3, 2}, | 138 {bits32("01000000000000000000000000000000"), 3, 2}, |
120 {bits32("01100000000000000000000000000000"), 3, 3}, | 139 {bits32("01100000000000000000000000000000"), 3, 3}, |
121 {bits32("10000000000000000000000000000000"), 3, 4}, | 140 {bits32("10000000000000000000000000000000"), 3, 4}, |
122 {bits32("10100000000000000000000000000000"), 3, 5}, | 141 {bits32("10100000000000000000000000000000"), 3, 5}, |
123 {bits32("11000000000000000000000000000000"), 3, 6}, | 142 {bits32("11000000000000000000000000000000"), 3, 6}, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 HpackHuffmanSymbol code[] = { | 218 HpackHuffmanSymbol code[] = { |
200 {bits32("00000000000000000000000000000000"), 1, 0}, | 219 {bits32("00000000000000000000000000000000"), 1, 0}, |
201 {bits32("10000000000000000000000000000000"), 2, 1}, | 220 {bits32("10000000000000000000000000000000"), 2, 1}, |
202 {bits32("11000000000000000000000000000000"), 3, 2}, | 221 {bits32("11000000000000000000000000000000"), 3, 2}, |
203 {bits32("11100000000000000000000000000000"), 7, 3}}; | 222 {bits32("11100000000000000000000000000000"), 7, 3}}; |
204 HpackHuffmanTable table; | 223 HpackHuffmanTable table; |
205 EXPECT_FALSE(table.Initialize(code, arraysize(code))); | 224 EXPECT_FALSE(table.Initialize(code, arraysize(code))); |
206 } | 225 } |
207 } | 226 } |
208 | 227 |
209 TEST(HpackHuffmanTableTest, ValidateInternalsWithSmallCode) { | 228 TEST_F(HpackHuffmanTableTest, ValidateInternalsWithSmallCode) { |
210 HpackHuffmanSymbol code[] = { | 229 HpackHuffmanSymbol code[] = { |
211 {bits32("01100000000000000000000000000000"), 4, 0}, // 3rd. | 230 {bits32("01100000000000000000000000000000"), 4, 0}, // 3rd. |
212 {bits32("01110000000000000000000000000000"), 4, 1}, // 4th. | 231 {bits32("01110000000000000000000000000000"), 4, 1}, // 4th. |
213 {bits32("00000000000000000000000000000000"), 2, 2}, // 1st assigned code. | 232 {bits32("00000000000000000000000000000000"), 2, 2}, // 1st assigned code. |
214 {bits32("01000000000000000000000000000000"), 3, 3}, // 2nd. | 233 {bits32("01000000000000000000000000000000"), 3, 3}, // 2nd. |
215 {bits32("10000000000000000000000000000000"), 5, 4}, // 5th. | 234 {bits32("10000000000000000000000000000000"), 5, 4}, // 5th. |
216 {bits32("10001000000000000000000000000000"), 5, 5}, // 6th. | 235 {bits32("10001000000000000000000000000000"), 5, 5}, // 6th. |
217 {bits32("10011000000000000000000000000000"), 8, 6}, // 8th. | 236 {bits32("10011000000000000000000000000000"), 8, 6}, // 8th. |
218 {bits32("10010000000000000000000000000000"), 5, 7}}; // 7th. | 237 {bits32("10010000000000000000000000000000"), 5, 7}}; // 7th. |
219 HpackHuffmanTable table; | 238 EXPECT_TRUE(table_.Initialize(code, arraysize(code))); |
220 EXPECT_TRUE(table.Initialize(code, arraysize(code))); | |
221 | 239 |
222 HpackHuffmanTablePeer peer(table); | 240 EXPECT_THAT(peer_.code_by_id(), ElementsAre( |
223 EXPECT_THAT(peer.code_by_id(), ElementsAre( | |
224 bits32("01100000000000000000000000000000"), | 241 bits32("01100000000000000000000000000000"), |
225 bits32("01110000000000000000000000000000"), | 242 bits32("01110000000000000000000000000000"), |
226 bits32("00000000000000000000000000000000"), | 243 bits32("00000000000000000000000000000000"), |
227 bits32("01000000000000000000000000000000"), | 244 bits32("01000000000000000000000000000000"), |
228 bits32("10000000000000000000000000000000"), | 245 bits32("10000000000000000000000000000000"), |
229 bits32("10001000000000000000000000000000"), | 246 bits32("10001000000000000000000000000000"), |
230 bits32("10011000000000000000000000000000"), | 247 bits32("10011000000000000000000000000000"), |
231 bits32("10010000000000000000000000000000"))); | 248 bits32("10010000000000000000000000000000"))); |
232 EXPECT_THAT(peer.length_by_id(), ElementsAre( | 249 EXPECT_THAT(peer_.length_by_id(), ElementsAre( |
233 4, 4, 2, 3, 5, 5, 8, 5)); | 250 4, 4, 2, 3, 5, 5, 8, 5)); |
234 | 251 |
235 EXPECT_EQ(peer.decode_tables().size(), 1u); | 252 EXPECT_EQ(1u, peer_.decode_tables().size()); |
236 { | 253 { |
237 std::vector<DecodeEntry> expected; | 254 std::vector<DecodeEntry> expected; |
238 expected.resize(128, DecodeEntry(0, 2, 2)); // Fills 128. | 255 expected.resize(128, DecodeEntry(0, 2, 2)); // Fills 128. |
239 expected.resize(192, DecodeEntry(0, 3, 3)); // Fills 64. | 256 expected.resize(192, DecodeEntry(0, 3, 3)); // Fills 64. |
240 expected.resize(224, DecodeEntry(0, 4, 0)); // Fills 32. | 257 expected.resize(224, DecodeEntry(0, 4, 0)); // Fills 32. |
241 expected.resize(256, DecodeEntry(0, 4, 1)); // Fills 32. | 258 expected.resize(256, DecodeEntry(0, 4, 1)); // Fills 32. |
242 expected.resize(272, DecodeEntry(0, 5, 4)); // Fills 16. | 259 expected.resize(272, DecodeEntry(0, 5, 4)); // Fills 16. |
243 expected.resize(288, DecodeEntry(0, 5, 5)); // Fills 16. | 260 expected.resize(288, DecodeEntry(0, 5, 5)); // Fills 16. |
244 expected.resize(304, DecodeEntry(0, 5, 7)); // Fills 16. | 261 expected.resize(304, DecodeEntry(0, 5, 7)); // Fills 16. |
245 expected.resize(306, DecodeEntry(0, 8, 6)); // Fills 2. | 262 expected.resize(306, DecodeEntry(0, 8, 6)); // Fills 2. |
246 expected.resize(512, DecodeEntry()); // Remainder is empty. | 263 expected.resize(512, DecodeEntry()); // Remainder is empty. |
247 | 264 |
248 EXPECT_THAT(peer.decode_entries(peer.decode_tables()[0]), | 265 EXPECT_THAT(peer_.decode_entries(peer_.decode_tables()[0]), |
249 Pointwise(DecodeEntryEq(), expected)); | 266 Pointwise(DecodeEntryEq(), expected)); |
250 } | 267 } |
251 EXPECT_EQ(peer.pad_bits(), bits8("10011000")); | 268 EXPECT_EQ(bits8("10011000"), peer_.pad_bits()); |
252 | 269 |
253 char input_storage[] = {2, 3, 2, 7, 4}; | 270 char input_storage[] = {2, 3, 2, 7, 4}; |
254 StringPiece input(input_storage, arraysize(input_storage)); | 271 StringPiece input(input_storage, arraysize(input_storage)); |
255 // By symbol: (2) 00 (3) 010 (2) 00 (7) 10010 (4) 10000 (6 as pad) 1001100. | 272 // By symbol: (2) 00 (3) 010 (2) 00 (7) 10010 (4) 10000 (6 as pad) 1001100. |
256 char expect_storage[] = { | 273 char expect_storage[] = { |
257 bits8("00010001"), | 274 bits8("00010001"), |
258 bits8("00101000"), | 275 bits8("00101000"), |
259 bits8("01001100")}; | 276 bits8("01001100")}; |
260 StringPiece expect(expect_storage, arraysize(expect_storage)); | 277 StringPiece expect(expect_storage, arraysize(expect_storage)); |
261 | 278 |
262 string buffer_in, buffer_out; | 279 string buffer_in = EncodeString(input); |
263 HpackOutputStream output_stream(kuint32max); | 280 EXPECT_EQ(expect, buffer_in); |
264 table.EncodeString(input, &output_stream); | |
265 output_stream.TakeString(&buffer_in); | |
266 EXPECT_EQ(buffer_in, expect); | |
267 | 281 |
| 282 string buffer_out; |
268 HpackInputStream input_stream(kuint32max, buffer_in); | 283 HpackInputStream input_stream(kuint32max, buffer_in); |
269 EXPECT_TRUE(table.DecodeString(&input_stream, input.size(), &buffer_out)); | 284 EXPECT_TRUE(table_.DecodeString(&input_stream, input.size(), &buffer_out)); |
270 EXPECT_EQ(buffer_out, input); | 285 EXPECT_EQ(buffer_out, input); |
271 } | 286 } |
272 | 287 |
273 TEST(HpackHuffmanTableTest, ValidateMultiLevelDecodeTables) { | 288 TEST_F(HpackHuffmanTableTest, ValidateMultiLevelDecodeTables) { |
274 HpackHuffmanSymbol code[] = { | 289 HpackHuffmanSymbol code[] = { |
275 {bits32("00000000000000000000000000000000"), 6, 0}, | 290 {bits32("00000000000000000000000000000000"), 6, 0}, |
276 {bits32("00000100000000000000000000000000"), 6, 1}, | 291 {bits32("00000100000000000000000000000000"), 6, 1}, |
277 {bits32("00001000000000000000000000000000"), 11, 2}, | 292 {bits32("00001000000000000000000000000000"), 11, 2}, |
278 {bits32("00001000001000000000000000000000"), 11, 3}, | 293 {bits32("00001000001000000000000000000000"), 11, 3}, |
279 {bits32("00001000010000000000000000000000"), 12, 4}, | 294 {bits32("00001000010000000000000000000000"), 12, 4}, |
280 }; | 295 }; |
281 HpackHuffmanTable table; | 296 EXPECT_TRUE(table_.Initialize(code, arraysize(code))); |
282 EXPECT_TRUE(table.Initialize(code, arraysize(code))); | |
283 | 297 |
284 HpackHuffmanTablePeer peer(table); | 298 EXPECT_EQ(2u, peer_.decode_tables().size()); |
285 EXPECT_EQ(peer.decode_tables().size(), 2u); | |
286 { | 299 { |
287 std::vector<DecodeEntry> expected; | 300 std::vector<DecodeEntry> expected; |
288 expected.resize(8, DecodeEntry(0, 6, 0)); // Fills 8. | 301 expected.resize(8, DecodeEntry(0, 6, 0)); // Fills 8. |
289 expected.resize(16, DecodeEntry(0, 6, 1)); // Fills 8. | 302 expected.resize(16, DecodeEntry(0, 6, 1)); // Fills 8. |
290 expected.resize(17, DecodeEntry(1, 12, 0)); // Pointer. Fills 1. | 303 expected.resize(17, DecodeEntry(1, 12, 0)); // Pointer. Fills 1. |
291 expected.resize(512, DecodeEntry()); // Remainder is empty. | 304 expected.resize(512, DecodeEntry()); // Remainder is empty. |
292 | 305 |
293 const DecodeTable& decode_table = peer.decode_tables()[0]; | 306 const DecodeTable& decode_table = peer_.decode_tables()[0]; |
294 EXPECT_EQ(decode_table.prefix_length, 0); | 307 EXPECT_EQ(decode_table.prefix_length, 0); |
295 EXPECT_EQ(decode_table.indexed_length, 9); | 308 EXPECT_EQ(decode_table.indexed_length, 9); |
296 EXPECT_THAT(peer.decode_entries(decode_table), | 309 EXPECT_THAT(peer_.decode_entries(decode_table), |
297 Pointwise(DecodeEntryEq(), expected)); | 310 Pointwise(DecodeEntryEq(), expected)); |
298 } | 311 } |
299 { | 312 { |
300 std::vector<DecodeEntry> expected; | 313 std::vector<DecodeEntry> expected; |
301 expected.resize(2, DecodeEntry(1, 11, 2)); // Fills 2. | 314 expected.resize(2, DecodeEntry(1, 11, 2)); // Fills 2. |
302 expected.resize(4, DecodeEntry(1, 11, 3)); // Fills 2. | 315 expected.resize(4, DecodeEntry(1, 11, 3)); // Fills 2. |
303 expected.resize(5, DecodeEntry(1, 12, 4)); // Fills 1. | 316 expected.resize(5, DecodeEntry(1, 12, 4)); // Fills 1. |
304 expected.resize(8, DecodeEntry()); // Remainder is empty. | 317 expected.resize(8, DecodeEntry()); // Remainder is empty. |
305 | 318 |
306 const DecodeTable& decode_table = peer.decode_tables()[1]; | 319 const DecodeTable& decode_table = peer_.decode_tables()[1]; |
307 EXPECT_EQ(decode_table.prefix_length, 9); | 320 EXPECT_EQ(decode_table.prefix_length, 9); |
308 EXPECT_EQ(decode_table.indexed_length, 3); | 321 EXPECT_EQ(decode_table.indexed_length, 3); |
309 EXPECT_THAT(peer.decode_entries(decode_table), | 322 EXPECT_THAT(peer_.decode_entries(decode_table), |
310 Pointwise(DecodeEntryEq(), expected)); | 323 Pointwise(DecodeEntryEq(), expected)); |
311 } | 324 } |
312 EXPECT_EQ(peer.pad_bits(), bits8("00001000")); | 325 EXPECT_EQ(bits8("00001000"), peer_.pad_bits()); |
313 } | 326 } |
314 | 327 |
315 TEST(HpackHuffmanTableTest, DecodeWithBadInput) { | 328 TEST_F(HpackHuffmanTableTest, DecodeWithBadInput) { |
316 HpackHuffmanSymbol code[] = { | 329 HpackHuffmanSymbol code[] = { |
317 {bits32("01100000000000000000000000000000"), 4, 0}, | 330 {bits32("01100000000000000000000000000000"), 4, 0}, |
318 {bits32("01110000000000000000000000000000"), 4, 1}, | 331 {bits32("01110000000000000000000000000000"), 4, 1}, |
319 {bits32("00000000000000000000000000000000"), 2, 2}, | 332 {bits32("00000000000000000000000000000000"), 2, 2}, |
320 {bits32("01000000000000000000000000000000"), 3, 3}, | 333 {bits32("01000000000000000000000000000000"), 3, 3}, |
321 {bits32("10000000000000000000000000000000"), 5, 4}, | 334 {bits32("10000000000000000000000000000000"), 5, 4}, |
322 {bits32("10001000000000000000000000000000"), 5, 5}, | 335 {bits32("10001000000000000000000000000000"), 5, 5}, |
323 {bits32("10011000000000000000000000000000"), 6, 6}, | 336 {bits32("10011000000000000000000000000000"), 6, 6}, |
324 {bits32("10010000000000000000000000000000"), 5, 7}, | 337 {bits32("10010000000000000000000000000000"), 5, 7}, |
325 {bits32("10011100000000000000000000000000"), 16, 8}}; | 338 {bits32("10011100000000000000000000000000"), 16, 8}}; |
326 HpackHuffmanTable table; | 339 EXPECT_TRUE(table_.Initialize(code, arraysize(code))); |
327 EXPECT_TRUE(table.Initialize(code, arraysize(code))); | |
328 | 340 |
329 string buffer; | 341 string buffer; |
330 const size_t capacity = 4; | 342 const size_t capacity = 4; |
331 { | 343 { |
332 // This example works: (2) 00 (3) 010 (2) 00 (6) 100110 (pad) 100. | 344 // This example works: (2) 00 (3) 010 (2) 00 (6) 100110 (pad) 100. |
333 char input_storage[] = {bits8("00010001"), bits8("00110100")}; | 345 char input_storage[] = {bits8("00010001"), bits8("00110100")}; |
334 StringPiece input(input_storage, arraysize(input_storage)); | 346 StringPiece input(input_storage, arraysize(input_storage)); |
335 | 347 |
336 HpackInputStream input_stream(kuint32max, input); | 348 HpackInputStream input_stream(kuint32max, input); |
337 EXPECT_TRUE(table.DecodeString(&input_stream, capacity, &buffer)); | 349 EXPECT_TRUE(table_.DecodeString(&input_stream, capacity, &buffer)); |
338 EXPECT_EQ(buffer, "\x02\x03\x02\x06"); | 350 EXPECT_EQ(buffer, "\x02\x03\x02\x06"); |
339 } | 351 } |
340 { | 352 { |
341 // Expect to fail on an invalid code prefix. | 353 // Expect to fail on an invalid code prefix. |
342 // (2) 00 (3) 010 (2) 00 (too-large) 101000 (pad) 100. | 354 // (2) 00 (3) 010 (2) 00 (too-large) 101000 (pad) 100. |
343 char input_storage[] = {bits8("00010001"), bits8("01000111")}; | 355 char input_storage[] = {bits8("00010001"), bits8("01000111")}; |
344 StringPiece input(input_storage, arraysize(input_storage)); | 356 StringPiece input(input_storage, arraysize(input_storage)); |
345 | 357 |
346 HpackInputStream input_stream(kuint32max, input); | 358 HpackInputStream input_stream(kuint32max, input); |
347 EXPECT_FALSE(table.DecodeString(&input_stream, capacity, &buffer)); | 359 EXPECT_FALSE(table_.DecodeString(&input_stream, capacity, &buffer)); |
348 EXPECT_EQ(buffer, "\x02\x03\x02"); | 360 EXPECT_EQ(buffer, "\x02\x03\x02"); |
349 } | 361 } |
350 { | 362 { |
351 // Repeat the shortest 00 code to overflow |buffer|. Expect to fail. | 363 // Repeat the shortest 0b00 code to overflow |buffer|. Expect to fail. |
352 std::vector<char> input_storage(1 + capacity / 4, '\0'); | 364 std::vector<char> input_storage(1 + capacity / 4, '\0'); |
353 StringPiece input(&input_storage[0], input_storage.size()); | 365 StringPiece input(&input_storage[0], input_storage.size()); |
354 | 366 |
355 HpackInputStream input_stream(kuint32max, input); | 367 HpackInputStream input_stream(kuint32max, input); |
356 EXPECT_FALSE(table.DecodeString(&input_stream, capacity, &buffer)); | 368 EXPECT_FALSE(table_.DecodeString(&input_stream, capacity, &buffer)); |
357 | 369 |
358 std::vector<char> expected(capacity, '\x02'); | 370 std::vector<char> expected(capacity, '\x02'); |
359 EXPECT_THAT(buffer, ElementsAreArray(expected)); | 371 EXPECT_THAT(buffer, ElementsAreArray(expected)); |
360 EXPECT_EQ(capacity, buffer.size()); | 372 EXPECT_EQ(capacity, buffer.size()); |
361 } | 373 } |
362 { | 374 { |
363 // Expect to fail if more than a byte of unconsumed input remains. | 375 // Expect to fail if more than a byte of unconsumed input remains. |
364 // (6) 100110 (8 truncated) 1001110000 | 376 // (6) 100110 (8 truncated) 1001110000 |
365 char input_storage[] = {bits8("10011010"), bits8("01110000")}; | 377 char input_storage[] = {bits8("10011010"), bits8("01110000")}; |
366 StringPiece input(input_storage, arraysize(input_storage)); | 378 StringPiece input(input_storage, arraysize(input_storage)); |
367 | 379 |
368 HpackInputStream input_stream(kuint32max, input); | 380 HpackInputStream input_stream(kuint32max, input); |
369 EXPECT_FALSE(table.DecodeString(&input_stream, 4, &buffer)); | 381 EXPECT_FALSE(table_.DecodeString(&input_stream, capacity, &buffer)); |
370 EXPECT_EQ(buffer, "\x06"); | 382 EXPECT_EQ(buffer, "\x06"); |
371 } | 383 } |
372 } | 384 } |
373 | 385 |
374 TEST(HpackHuffmanTableTest, SpecRequestExamples) { | 386 TEST_F(HpackHuffmanTableTest, SpecRequestExamples) { |
375 const HpackHuffmanTable& table(ObtainHpackHuffmanTable()); | 387 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); |
| 388 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); |
376 | 389 |
377 string buffer; | 390 string buffer; |
378 string test_table[] = { | 391 string test_table[] = { |
379 "\xdb\x6d\x88\x3e\x68\xd1\xcb\x12\x25\xba\x7f", | 392 "\xdb\x6d\x88\x3e\x68\xd1\xcb\x12\x25\xba\x7f", |
380 "www.example.com", | 393 "www.example.com", |
381 "\x63\x65\x4a\x13\x98\xff", | 394 "\x63\x65\x4a\x13\x98\xff", |
382 "no-cache", | 395 "no-cache", |
383 "\x4e\xb0\x8b\x74\x97\x90\xfa\x7f", | 396 "\x4e\xb0\x8b\x74\x97\x90\xfa\x7f", |
384 "custom-key", | 397 "custom-key", |
385 "\x4e\xb0\x8b\x74\x97\x9a\x17\xa8\xff", | 398 "\x4e\xb0\x8b\x74\x97\x9a\x17\xa8\xff", |
386 "custom-value", | 399 "custom-value", |
387 }; | 400 }; |
388 // Round-trip each test example. | 401 // Round-trip each test example. |
389 for (size_t i = 0; i != arraysize(test_table); i += 2) { | 402 for (size_t i = 0; i != arraysize(test_table); i += 2) { |
390 const string& encoded(test_table[i]); | 403 const string& encodedFixture(test_table[i]); |
391 const string& decoded(test_table[i+1]); | 404 const string& decodedFixture(test_table[i+1]); |
392 HpackInputStream input_stream(kuint32max, encoded); | 405 HpackInputStream input_stream(kuint32max, encodedFixture); |
393 HpackOutputStream output_stream(kuint32max); | |
394 | 406 |
395 buffer.reserve(decoded.size()); | 407 EXPECT_TRUE(table_.DecodeString(&input_stream, decodedFixture.size(), |
396 EXPECT_TRUE(table.DecodeString(&input_stream, decoded.size(), &buffer)); | 408 &buffer)); |
397 EXPECT_EQ(decoded, buffer); | 409 EXPECT_EQ(decodedFixture, buffer); |
398 table.EncodeString(decoded, &output_stream); | 410 buffer = EncodeString(decodedFixture); |
399 output_stream.TakeString(&buffer); | 411 EXPECT_EQ(encodedFixture, buffer); |
400 EXPECT_EQ(encoded, buffer); | |
401 } | 412 } |
402 } | 413 } |
403 | 414 |
404 TEST(HpackHuffmanTableTest, SpecResponseExamples) { | 415 TEST_F(HpackHuffmanTableTest, SpecResponseExamples) { |
405 const HpackHuffmanTable& table(ObtainHpackHuffmanTable()); | 416 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); |
| 417 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); |
406 | 418 |
407 string buffer; | 419 string buffer; |
408 string test_table[] = { | 420 string test_table[] = { |
409 "\x98\xa7", | 421 "\x98\xa7", |
410 "302", | 422 "302", |
411 "\x73\xd5\xcd\x11\x1f", | 423 "\x73\xd5\xcd\x11\x1f", |
412 "private", | 424 "private", |
413 "\xef\x6b\x3a\x7a\x0e\x6e\x8f\xa2\x63\xd0\x72\x9a\x6e\x83\x97\xd8" | 425 "\xef\x6b\x3a\x7a\x0e\x6e\x8f\xa2\x63\xd0\x72\x9a\x6e\x83\x97\xd8" |
414 "\x69\xbd\x87\x37\x47\xbb\xbf\xc7", | 426 "\x69\xbd\x87\x37\x47\xbb\xbf\xc7", |
415 "Mon, 21 Oct 2013 20:13:21 GMT", | 427 "Mon, 21 Oct 2013 20:13:21 GMT", |
416 "\xce\x31\x74\x3d\x80\x1b\x6d\xb1\x07\xcd\x1a\x39\x62\x44\xb7\x4f", | 428 "\xce\x31\x74\x3d\x80\x1b\x6d\xb1\x07\xcd\x1a\x39\x62\x44\xb7\x4f", |
417 "https://www.example.com", | 429 "https://www.example.com", |
418 "\xc5\xad\xb7\x7f\x87\x6f\xc7\xfb\xf7\xfd\xbf\xbe\xbf\xf3\xf7\xf4" | 430 "\xc5\xad\xb7\x7f\x87\x6f\xc7\xfb\xf7\xfd\xbf\xbe\xbf\xf3\xf7\xf4" |
419 "\xfb\x7e\xbb\xbe\x9f\x5f\x87\xe3\x7f\xef\xed\xfa\xee\xfa\x7c\x3f" | 431 "\xfb\x7e\xbb\xbe\x9f\x5f\x87\xe3\x7f\xef\xed\xfa\xee\xfa\x7c\x3f" |
420 "\x1d\x5d\x1a\x23\xce\x54\x64\x36\xcd\x49\x4b\xd5\xd1\xcc\x5f\x05" | 432 "\x1d\x5d\x1a\x23\xce\x54\x64\x36\xcd\x49\x4b\xd5\xd1\xcc\x5f\x05" |
421 "\x35\x96\x9b", | 433 "\x35\x96\x9b", |
422 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", | 434 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", |
423 }; | 435 }; |
424 // Round-trip each test example. | 436 // Round-trip each test example. |
425 for (size_t i = 0; i != arraysize(test_table); i += 2) { | 437 for (size_t i = 0; i != arraysize(test_table); i += 2) { |
426 const string& encoded(test_table[i]); | 438 const string& encodedFixture(test_table[i]); |
427 const string& decoded(test_table[i+1]); | 439 const string& decodedFixture(test_table[i+1]); |
428 HpackInputStream input_stream(kuint32max, encoded); | 440 HpackInputStream input_stream(kuint32max, encodedFixture); |
429 HpackOutputStream output_stream(kuint32max); | |
430 | 441 |
431 buffer.reserve(decoded.size()); | 442 EXPECT_TRUE(table_.DecodeString(&input_stream, decodedFixture.size(), |
432 EXPECT_TRUE(table.DecodeString(&input_stream, decoded.size(), &buffer)); | 443 &buffer)); |
433 EXPECT_EQ(decoded, buffer); | 444 EXPECT_EQ(decodedFixture, buffer); |
434 table.EncodeString(decoded, &output_stream); | 445 buffer = EncodeString(decodedFixture); |
435 output_stream.TakeString(&buffer); | 446 EXPECT_EQ(encodedFixture, buffer); |
436 EXPECT_EQ(encoded, buffer); | |
437 } | 447 } |
438 } | 448 } |
439 | 449 |
440 TEST(HpackHuffmanTableTest, RoundTripIndvidualSymbols) { | 450 TEST_F(HpackHuffmanTableTest, RoundTripIndvidualSymbols) { |
441 const HpackHuffmanTable& table(ObtainHpackHuffmanTable()); | 451 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); |
| 452 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); |
442 | 453 |
443 for (size_t i = 0; i != 256; i++) { | 454 for (size_t i = 0; i != 256; i++) { |
444 char c = static_cast<char>(i); | 455 char c = static_cast<char>(i); |
445 char storage[3] = {c, c, c}; | 456 char storage[3] = {c, c, c}; |
446 StringPiece input(storage, arraysize(storage)); | 457 StringPiece input(storage, arraysize(storage)); |
447 | 458 |
448 string buffer_in, buffer_out(input.size(), '\0'); | 459 string buffer_in = EncodeString(input); |
449 HpackOutputStream output_stream(kuint32max); | 460 string buffer_out; |
450 table.EncodeString(input, &output_stream); | |
451 output_stream.TakeString(&buffer_in); | |
452 | 461 |
453 HpackInputStream input_stream(kuint32max, buffer_in); | 462 HpackInputStream input_stream(kuint32max, buffer_in); |
454 EXPECT_TRUE(table.DecodeString(&input_stream, input.size(), &buffer_out)); | 463 EXPECT_TRUE(table_.DecodeString(&input_stream, input.size(), &buffer_out)); |
455 EXPECT_EQ(input, buffer_out); | 464 EXPECT_EQ(input, buffer_out); |
456 } | 465 } |
457 } | 466 } |
458 | 467 |
459 TEST(HpackHuffmanTableTest, RoundTripSymbolSequence) { | 468 TEST_F(HpackHuffmanTableTest, RoundTripSymbolSequence) { |
460 const HpackHuffmanTable& table(ObtainHpackHuffmanTable()); | 469 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); |
| 470 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); |
| 471 |
461 | 472 |
462 char storage[512]; | 473 char storage[512]; |
463 for (size_t i = 0; i != 256; i++) { | 474 for (size_t i = 0; i != 256; i++) { |
464 storage[i] = static_cast<char>(i); | 475 storage[i] = static_cast<char>(i); |
465 storage[511 - i] = static_cast<char>(i); | 476 storage[511 - i] = static_cast<char>(i); |
466 } | 477 } |
467 StringPiece input(storage, arraysize(storage)); | 478 StringPiece input(storage, arraysize(storage)); |
468 | 479 |
469 string buffer_in, buffer_out(input.size(), '\0'); | 480 string buffer_in = EncodeString(input); |
470 HpackOutputStream output_stream(kuint32max); | 481 string buffer_out; |
471 table.EncodeString(input, &output_stream); | |
472 output_stream.TakeString(&buffer_in); | |
473 | 482 |
474 HpackInputStream input_stream(kuint32max, buffer_in); | 483 HpackInputStream input_stream(kuint32max, buffer_in); |
475 EXPECT_TRUE(table.DecodeString(&input_stream, input.size(), &buffer_out)); | 484 EXPECT_TRUE(table_.DecodeString(&input_stream, input.size(), &buffer_out)); |
476 EXPECT_EQ(input, buffer_out); | 485 EXPECT_EQ(input, buffer_out); |
477 } | 486 } |
478 | 487 |
| 488 TEST_F(HpackHuffmanTableTest, EncodedSizeAgreesWithEncodeString) { |
| 489 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); |
| 490 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); |
| 491 |
| 492 string test_table[] = { |
| 493 "", |
| 494 "Mon, 21 Oct 2013 20:13:21 GMT", |
| 495 "https://www.example.com", |
| 496 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", |
| 497 string(1, '\0'), |
| 498 string("foo\0bar", 7), |
| 499 string(256, '\0'), |
| 500 }; |
| 501 for (size_t i = 0; i != 256; ++i) { |
| 502 // Expand last |test_table| entry to cover all codes. |
| 503 test_table[arraysize(test_table)-1][i] = static_cast<char>(i); |
| 504 } |
| 505 |
| 506 HpackOutputStream output_stream; |
| 507 string encoding; |
| 508 for (size_t i = 0; i != arraysize(test_table); ++i) { |
| 509 table_.EncodeString(test_table[i], &output_stream); |
| 510 output_stream.TakeString(&encoding); |
| 511 EXPECT_EQ(encoding.size(), table_.EncodedSize(test_table[i])); |
| 512 } |
| 513 } |
| 514 |
479 } // namespace | 515 } // namespace |
480 | 516 |
481 } // namespace test | 517 } // namespace test |
482 | 518 |
483 } // namespace net | 519 } // namespace net |
OLD | NEW |