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/hpack_huffman_table.h" | 5 #include "net/spdy/hpack/hpack_huffman_table.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <bitset> | 9 #include <bitset> |
10 #include <limits> | 10 #include <limits> |
11 #include <string> | 11 #include <string> |
| 12 #include <utility> |
12 | 13 |
13 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/macros.h" |
14 #include "net/spdy/hpack/hpack_constants.h" | 16 #include "net/spdy/hpack/hpack_constants.h" |
| 17 #include "net/spdy/hpack/hpack_huffman_decoder.h" |
15 #include "net/spdy/hpack/hpack_input_stream.h" | 18 #include "net/spdy/hpack/hpack_input_stream.h" |
16 #include "net/spdy/hpack/hpack_output_stream.h" | 19 #include "net/spdy/hpack/hpack_output_stream.h" |
17 #include "net/spdy/spdy_test_utils.h" | 20 #include "net/spdy/spdy_test_utils.h" |
18 #include "testing/gmock/include/gmock/gmock.h" | 21 #include "testing/gmock/include/gmock/gmock.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
20 | 23 |
21 using base::StringPiece; | 24 using base::StringPiece; |
22 using std::string; | 25 using std::string; |
23 using testing::ElementsAreArray; | 26 using testing::ElementsAreArray; |
24 using testing::Pointwise; | 27 using testing::Pointwise; |
(...skipping 27 matching lines...) Expand all Loading... |
52 table_.decode_entries_.begin() + decode_table.entries_offset; | 55 table_.decode_entries_.begin() + decode_table.entries_offset; |
53 return std::vector<DecodeEntry>(begin, begin + decode_table.size()); | 56 return std::vector<DecodeEntry>(begin, begin + decode_table.size()); |
54 } | 57 } |
55 | 58 |
56 private: | 59 private: |
57 const HpackHuffmanTable& table_; | 60 const HpackHuffmanTable& table_; |
58 }; | 61 }; |
59 | 62 |
60 namespace { | 63 namespace { |
61 | 64 |
62 class HpackHuffmanTableTest : public ::testing::Test { | 65 // Tests of the ability to decode some canonical Huffman code, |
| 66 // not just the one defined in the RFC 7541. |
| 67 class GenericHuffmanTableTest : public ::testing::TestWithParam<bool> { |
63 protected: | 68 protected: |
64 HpackHuffmanTableTest() : table_(), peer_(table_) {} | 69 GenericHuffmanTableTest() : table_(), peer_(table_) {} |
65 | 70 |
66 string EncodeString(StringPiece input) { | 71 string EncodeString(StringPiece input) { |
67 string result; | 72 string result; |
68 HpackOutputStream output_stream; | 73 HpackOutputStream output_stream; |
69 table_.EncodeString(input, &output_stream); | 74 table_.EncodeString(input, &output_stream); |
70 | 75 |
71 output_stream.TakeString(&result); | 76 output_stream.TakeString(&result); |
72 // Verify EncodedSize() agrees with EncodeString(). | 77 // Verify EncodedSize() agrees with EncodeString(). |
73 EXPECT_EQ(result.size(), table_.EncodedSize(input)); | 78 EXPECT_EQ(result.size(), table_.EncodedSize(input)); |
74 return result; | 79 return result; |
(...skipping 10 matching lines...) Expand all Loading... |
85 lhs.length == rhs.length && lhs.symbol_id == rhs.symbol_id; | 90 lhs.length == rhs.length && lhs.symbol_id == rhs.symbol_id; |
86 } | 91 } |
87 | 92 |
88 uint32_t bits32(const string& bitstring) { | 93 uint32_t bits32(const string& bitstring) { |
89 return std::bitset<32>(bitstring).to_ulong(); | 94 return std::bitset<32>(bitstring).to_ulong(); |
90 } | 95 } |
91 char bits8(const string& bitstring) { | 96 char bits8(const string& bitstring) { |
92 return static_cast<char>(std::bitset<8>(bitstring).to_ulong()); | 97 return static_cast<char>(std::bitset<8>(bitstring).to_ulong()); |
93 } | 98 } |
94 | 99 |
95 TEST_F(HpackHuffmanTableTest, InitializeHpackCode) { | 100 TEST_F(GenericHuffmanTableTest, InitializeEdgeCases) { |
96 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); | |
97 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); | |
98 EXPECT_TRUE(table_.IsInitialized()); | |
99 EXPECT_EQ(peer_.pad_bits(), bits8("11111111")); // First 8 bits of EOS. | |
100 } | |
101 | |
102 TEST_F(HpackHuffmanTableTest, InitializeEdgeCases) { | |
103 { | 101 { |
104 // Verify eight symbols can be encoded with 3 bits per symbol. | 102 // Verify eight symbols can be encoded with 3 bits per symbol. |
105 HpackHuffmanSymbol code[] = { | 103 HpackHuffmanSymbol code[] = { |
106 {bits32("00000000000000000000000000000000"), 3, 0}, | 104 {bits32("00000000000000000000000000000000"), 3, 0}, |
107 {bits32("00100000000000000000000000000000"), 3, 1}, | 105 {bits32("00100000000000000000000000000000"), 3, 1}, |
108 {bits32("01000000000000000000000000000000"), 3, 2}, | 106 {bits32("01000000000000000000000000000000"), 3, 2}, |
109 {bits32("01100000000000000000000000000000"), 3, 3}, | 107 {bits32("01100000000000000000000000000000"), 3, 3}, |
110 {bits32("10000000000000000000000000000000"), 3, 4}, | 108 {bits32("10000000000000000000000000000000"), 3, 4}, |
111 {bits32("10100000000000000000000000000000"), 3, 5}, | 109 {bits32("10100000000000000000000000000000"), 3, 5}, |
112 {bits32("11000000000000000000000000000000"), 3, 6}, | 110 {bits32("11000000000000000000000000000000"), 3, 6}, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 HpackHuffmanSymbol code[] = { | 186 HpackHuffmanSymbol code[] = { |
189 {bits32("00000000000000000000000000000000"), 1, 0}, | 187 {bits32("00000000000000000000000000000000"), 1, 0}, |
190 {bits32("10000000000000000000000000000000"), 2, 1}, | 188 {bits32("10000000000000000000000000000000"), 2, 1}, |
191 {bits32("11000000000000000000000000000000"), 3, 2}, | 189 {bits32("11000000000000000000000000000000"), 3, 2}, |
192 {bits32("11100000000000000000000000000000"), 7, 3}}; | 190 {bits32("11100000000000000000000000000000"), 7, 3}}; |
193 HpackHuffmanTable table; | 191 HpackHuffmanTable table; |
194 EXPECT_FALSE(table.Initialize(code, arraysize(code))); | 192 EXPECT_FALSE(table.Initialize(code, arraysize(code))); |
195 } | 193 } |
196 } | 194 } |
197 | 195 |
198 TEST_F(HpackHuffmanTableTest, ValidateInternalsWithSmallCode) { | 196 TEST_F(GenericHuffmanTableTest, ValidateInternalsWithSmallCode) { |
199 HpackHuffmanSymbol code[] = { | 197 HpackHuffmanSymbol code[] = { |
200 {bits32("01100000000000000000000000000000"), 4, 0}, // 3rd. | 198 {bits32("01100000000000000000000000000000"), 4, 0}, // 3rd. |
201 {bits32("01110000000000000000000000000000"), 4, 1}, // 4th. | 199 {bits32("01110000000000000000000000000000"), 4, 1}, // 4th. |
202 {bits32("00000000000000000000000000000000"), 2, 2}, // 1st assigned code. | 200 {bits32("00000000000000000000000000000000"), 2, 2}, // 1st assigned code. |
203 {bits32("01000000000000000000000000000000"), 3, 3}, // 2nd. | 201 {bits32("01000000000000000000000000000000"), 3, 3}, // 2nd. |
204 {bits32("10000000000000000000000000000000"), 5, 4}, // 5th. | 202 {bits32("10000000000000000000000000000000"), 5, 4}, // 5th. |
205 {bits32("10001000000000000000000000000000"), 5, 5}, // 6th. | 203 {bits32("10001000000000000000000000000000"), 5, 5}, // 6th. |
206 {bits32("10011000000000000000000000000000"), 8, 6}, // 8th. | 204 {bits32("10011000000000000000000000000000"), 8, 6}, // 8th. |
207 {bits32("10010000000000000000000000000000"), 5, 7}}; // 7th. | 205 {bits32("10010000000000000000000000000000"), 5, 7}}; // 7th. |
208 EXPECT_TRUE(table_.Initialize(code, arraysize(code))); | 206 EXPECT_TRUE(table_.Initialize(code, arraysize(code))); |
(...skipping 28 matching lines...) Expand all Loading... |
237 char expect_storage[] = {bits8("00010001"), bits8("00101000"), | 235 char expect_storage[] = {bits8("00010001"), bits8("00101000"), |
238 bits8("01001100")}; | 236 bits8("01001100")}; |
239 StringPiece expect(expect_storage, arraysize(expect_storage)); | 237 StringPiece expect(expect_storage, arraysize(expect_storage)); |
240 | 238 |
241 string buffer_in = EncodeString(input); | 239 string buffer_in = EncodeString(input); |
242 EXPECT_EQ(expect, buffer_in); | 240 EXPECT_EQ(expect, buffer_in); |
243 | 241 |
244 string buffer_out; | 242 string buffer_out; |
245 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), | 243 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), |
246 buffer_in); | 244 buffer_in); |
247 EXPECT_TRUE(table_.DecodeString(&input_stream, input.size(), &buffer_out)); | 245 EXPECT_TRUE( |
| 246 table_.GenericDecodeString(&input_stream, input.size(), &buffer_out)); |
248 EXPECT_EQ(buffer_out, input); | 247 EXPECT_EQ(buffer_out, input); |
249 } | 248 } |
250 | 249 |
251 TEST_F(HpackHuffmanTableTest, ValidateMultiLevelDecodeTables) { | 250 TEST_F(GenericHuffmanTableTest, ValidateMultiLevelDecodeTables) { |
252 HpackHuffmanSymbol code[] = { | 251 HpackHuffmanSymbol code[] = { |
253 {bits32("00000000000000000000000000000000"), 6, 0}, | 252 {bits32("00000000000000000000000000000000"), 6, 0}, |
254 {bits32("00000100000000000000000000000000"), 6, 1}, | 253 {bits32("00000100000000000000000000000000"), 6, 1}, |
255 {bits32("00001000000000000000000000000000"), 11, 2}, | 254 {bits32("00001000000000000000000000000000"), 11, 2}, |
256 {bits32("00001000001000000000000000000000"), 11, 3}, | 255 {bits32("00001000001000000000000000000000"), 11, 3}, |
257 {bits32("00001000010000000000000000000000"), 12, 4}, | 256 {bits32("00001000010000000000000000000000"), 12, 4}, |
258 }; | 257 }; |
259 EXPECT_TRUE(table_.Initialize(code, arraysize(code))); | 258 EXPECT_TRUE(table_.Initialize(code, arraysize(code))); |
260 | 259 |
261 EXPECT_EQ(2u, peer_.decode_tables().size()); | 260 EXPECT_EQ(2u, peer_.decode_tables().size()); |
(...skipping 19 matching lines...) Expand all Loading... |
281 | 280 |
282 const DecodeTable& decode_table = peer_.decode_tables()[1]; | 281 const DecodeTable& decode_table = peer_.decode_tables()[1]; |
283 EXPECT_EQ(decode_table.prefix_length, 9); | 282 EXPECT_EQ(decode_table.prefix_length, 9); |
284 EXPECT_EQ(decode_table.indexed_length, 3); | 283 EXPECT_EQ(decode_table.indexed_length, 3); |
285 EXPECT_THAT(peer_.decode_entries(decode_table), | 284 EXPECT_THAT(peer_.decode_entries(decode_table), |
286 Pointwise(DecodeEntryEq(), expected)); | 285 Pointwise(DecodeEntryEq(), expected)); |
287 } | 286 } |
288 EXPECT_EQ(bits8("00001000"), peer_.pad_bits()); | 287 EXPECT_EQ(bits8("00001000"), peer_.pad_bits()); |
289 } | 288 } |
290 | 289 |
291 TEST_F(HpackHuffmanTableTest, DecodeWithBadInput) { | 290 TEST_F(GenericHuffmanTableTest, DecodeWithBadInput) { |
292 HpackHuffmanSymbol code[] = { | 291 HpackHuffmanSymbol code[] = { |
293 {bits32("01100000000000000000000000000000"), 4, 0}, | 292 {bits32("01100000000000000000000000000000"), 4, 0}, |
294 {bits32("01110000000000000000000000000000"), 4, 1}, | 293 {bits32("01110000000000000000000000000000"), 4, 1}, |
295 {bits32("00000000000000000000000000000000"), 2, 2}, | 294 {bits32("00000000000000000000000000000000"), 2, 2}, |
296 {bits32("01000000000000000000000000000000"), 3, 3}, | 295 {bits32("01000000000000000000000000000000"), 3, 3}, |
297 {bits32("10000000000000000000000000000000"), 5, 4}, | 296 {bits32("10000000000000000000000000000000"), 5, 4}, |
298 {bits32("10001000000000000000000000000000"), 5, 5}, | 297 {bits32("10001000000000000000000000000000"), 5, 5}, |
299 {bits32("10011000000000000000000000000000"), 6, 6}, | 298 {bits32("10011000000000000000000000000000"), 6, 6}, |
300 {bits32("10010000000000000000000000000000"), 5, 7}, | 299 {bits32("10010000000000000000000000000000"), 5, 7}, |
301 {bits32("10011100000000000000000000000000"), 16, 8}}; | 300 {bits32("10011100000000000000000000000000"), 16, 8}}; |
302 EXPECT_TRUE(table_.Initialize(code, arraysize(code))); | 301 EXPECT_TRUE(table_.Initialize(code, arraysize(code))); |
303 | 302 |
304 string buffer; | 303 string buffer; |
305 const size_t capacity = 4; | 304 const size_t capacity = 4; |
306 { | 305 { |
307 // This example works: (2) 00 (3) 010 (2) 00 (6) 100110 (pad) 100. | 306 // This example works: (2) 00 (3) 010 (2) 00 (6) 100110 (pad) 100. |
308 char input_storage[] = {bits8("00010001"), bits8("00110100")}; | 307 char input_storage[] = {bits8("00010001"), bits8("00110100")}; |
309 StringPiece input(input_storage, arraysize(input_storage)); | 308 StringPiece input(input_storage, arraysize(input_storage)); |
310 | 309 |
311 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), input); | 310 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), input); |
312 EXPECT_TRUE(table_.DecodeString(&input_stream, capacity, &buffer)); | 311 EXPECT_TRUE(table_.GenericDecodeString(&input_stream, capacity, &buffer)); |
313 EXPECT_EQ(buffer, "\x02\x03\x02\x06"); | 312 EXPECT_EQ(buffer, "\x02\x03\x02\x06"); |
314 } | 313 } |
315 { | 314 { |
316 // Expect to fail on an invalid code prefix. | 315 // Expect to fail on an invalid code prefix. |
317 // (2) 00 (3) 010 (2) 00 (too-large) 101000 (pad) 100. | 316 // (2) 00 (3) 010 (2) 00 (too-large) 101000 (pad) 100. |
318 char input_storage[] = {bits8("00010001"), bits8("01000111")}; | 317 char input_storage[] = {bits8("00010001"), bits8("01000111")}; |
319 StringPiece input(input_storage, arraysize(input_storage)); | 318 StringPiece input(input_storage, arraysize(input_storage)); |
320 | 319 |
321 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), input); | 320 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), input); |
322 EXPECT_FALSE(table_.DecodeString(&input_stream, capacity, &buffer)); | 321 EXPECT_FALSE(table_.GenericDecodeString(&input_stream, capacity, &buffer)); |
323 EXPECT_EQ(buffer, "\x02\x03\x02"); | 322 EXPECT_EQ(buffer, "\x02\x03\x02"); |
324 } | 323 } |
325 { | 324 { |
326 // Repeat the shortest 0b00 code to overflow |buffer|. Expect to fail. | 325 // Repeat the shortest 0b00 code to overflow |buffer|. Expect to fail. |
327 std::vector<char> input_storage(1 + capacity / 4, '\0'); | 326 std::vector<char> input_storage(1 + capacity / 4, '\0'); |
328 StringPiece input(&input_storage[0], input_storage.size()); | 327 StringPiece input(&input_storage[0], input_storage.size()); |
329 | 328 |
330 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), input); | 329 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), input); |
331 EXPECT_FALSE(table_.DecodeString(&input_stream, capacity, &buffer)); | 330 EXPECT_FALSE(table_.GenericDecodeString(&input_stream, capacity, &buffer)); |
332 | 331 |
333 std::vector<char> expected(capacity, '\x02'); | 332 std::vector<char> expected(capacity, '\x02'); |
334 EXPECT_THAT(buffer, ElementsAreArray(expected)); | 333 EXPECT_THAT(buffer, ElementsAreArray(expected)); |
335 EXPECT_EQ(capacity, buffer.size()); | 334 EXPECT_EQ(capacity, buffer.size()); |
336 } | 335 } |
337 { | 336 { |
338 // Expect to fail if more than a byte of unconsumed input remains. | 337 // Expect to fail if more than a byte of unconsumed input remains. |
339 // (6) 100110 (8 truncated) 1001110000 | 338 // (6) 100110 (8 truncated) 1001110000 |
340 char input_storage[] = {bits8("10011010"), bits8("01110000")}; | 339 char input_storage[] = {bits8("10011010"), bits8("01110000")}; |
341 StringPiece input(input_storage, arraysize(input_storage)); | 340 StringPiece input(input_storage, arraysize(input_storage)); |
342 | 341 |
343 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), input); | 342 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), input); |
344 EXPECT_FALSE(table_.DecodeString(&input_stream, capacity, &buffer)); | 343 EXPECT_FALSE(table_.GenericDecodeString(&input_stream, capacity, &buffer)); |
345 EXPECT_EQ(buffer, "\x06"); | 344 EXPECT_EQ(buffer, "\x06"); |
346 } | 345 } |
347 } | 346 } |
348 | 347 |
| 348 // Tests of the ability to decode the HPACK Huffman Code, defined in: |
| 349 // https://httpwg.github.io/specs/rfc7541.html#huffman.code |
| 350 class HpackHuffmanTableTest : public GenericHuffmanTableTest { |
| 351 protected: |
| 352 void SetUp() override { |
| 353 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); |
| 354 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); |
| 355 EXPECT_TRUE(table_.IsInitialized()); |
| 356 } |
| 357 |
| 358 void DecodeStringTwice(const string& encoded, |
| 359 size_t out_capacity, |
| 360 string* out) { |
| 361 // First decode with HpackHuffmanTable. |
| 362 { |
| 363 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), |
| 364 encoded); |
| 365 EXPECT_TRUE(table_.GenericDecodeString(&input_stream, out_capacity, out)); |
| 366 } |
| 367 // And decode again with the fixed decoder, confirming that the result is |
| 368 // the same. |
| 369 { |
| 370 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), |
| 371 encoded); |
| 372 string buf; |
| 373 EXPECT_TRUE( |
| 374 HpackHuffmanDecoder::DecodeString(&input_stream, out_capacity, &buf)); |
| 375 EXPECT_EQ(*out, buf); |
| 376 } |
| 377 } |
| 378 }; |
| 379 |
| 380 TEST_F(HpackHuffmanTableTest, InitializeHpackCode) { |
| 381 EXPECT_EQ(peer_.pad_bits(), '\xFF'); // First 8 bits of EOS. |
| 382 } |
| 383 |
349 TEST_F(HpackHuffmanTableTest, SpecRequestExamples) { | 384 TEST_F(HpackHuffmanTableTest, SpecRequestExamples) { |
350 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); | |
351 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); | |
352 | |
353 string buffer; | 385 string buffer; |
354 string test_table[] = { | 386 string test_table[] = { |
355 a2b_hex("f1e3c2e5f23a6ba0ab90f4ff"), | 387 a2b_hex("f1e3c2e5f23a6ba0ab90f4ff"), |
356 "www.example.com", | 388 "www.example.com", |
357 a2b_hex("a8eb10649cbf"), | 389 a2b_hex("a8eb10649cbf"), |
358 "no-cache", | 390 "no-cache", |
359 a2b_hex("25a849e95ba97d7f"), | 391 a2b_hex("25a849e95ba97d7f"), |
360 "custom-key", | 392 "custom-key", |
361 a2b_hex("25a849e95bb8e8b4bf"), | 393 a2b_hex("25a849e95bb8e8b4bf"), |
362 "custom-value", | 394 "custom-value", |
363 }; | 395 }; |
364 // Round-trip each test example. | 396 // Round-trip each test example. |
365 for (size_t i = 0; i != arraysize(test_table); i += 2) { | 397 for (size_t i = 0; i != arraysize(test_table); i += 2) { |
366 const string& encodedFixture(test_table[i]); | 398 const string& encodedFixture(test_table[i]); |
367 const string& decodedFixture(test_table[i + 1]); | 399 const string& decodedFixture(test_table[i + 1]); |
368 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), | 400 DecodeStringTwice(encodedFixture, decodedFixture.size(), &buffer); |
369 encodedFixture); | |
370 | |
371 EXPECT_TRUE( | |
372 table_.DecodeString(&input_stream, decodedFixture.size(), &buffer)); | |
373 EXPECT_EQ(decodedFixture, buffer); | 401 EXPECT_EQ(decodedFixture, buffer); |
374 buffer = EncodeString(decodedFixture); | 402 buffer = EncodeString(decodedFixture); |
375 EXPECT_EQ(encodedFixture, buffer); | 403 EXPECT_EQ(encodedFixture, buffer); |
376 } | 404 } |
377 } | 405 } |
378 | 406 |
379 TEST_F(HpackHuffmanTableTest, SpecResponseExamples) { | 407 TEST_F(HpackHuffmanTableTest, SpecResponseExamples) { |
380 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); | |
381 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); | |
382 | |
383 string buffer; | 408 string buffer; |
384 string test_table[] = { | 409 string test_table[] = { |
385 a2b_hex("6402"), "302", a2b_hex("aec3771a4b"), "private", | 410 a2b_hex("6402"), "302", a2b_hex("aec3771a4b"), "private", |
386 a2b_hex("d07abe941054d444a8200595040b8166" | 411 a2b_hex("d07abe941054d444a8200595040b8166" |
387 "e082a62d1bff"), | 412 "e082a62d1bff"), |
388 "Mon, 21 Oct 2013 20:13:21 GMT", | 413 "Mon, 21 Oct 2013 20:13:21 GMT", |
389 a2b_hex("9d29ad171863c78f0b97c8e9ae82ae43" | 414 a2b_hex("9d29ad171863c78f0b97c8e9ae82ae43" |
390 "d3"), | 415 "d3"), |
391 "https://www.example.com", a2b_hex("94e7821dd7f2e6c7b335dfdfcd5b3960" | 416 "https://www.example.com", a2b_hex("94e7821dd7f2e6c7b335dfdfcd5b3960" |
392 "d5af27087f3672c1ab270fb5291f9587" | 417 "d5af27087f3672c1ab270fb5291f9587" |
393 "316065c003ed4ee5b1063d5007"), | 418 "316065c003ed4ee5b1063d5007"), |
394 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", | 419 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", |
395 }; | 420 }; |
396 // Round-trip each test example. | 421 // Round-trip each test example. |
397 for (size_t i = 0; i != arraysize(test_table); i += 2) { | 422 for (size_t i = 0; i != arraysize(test_table); i += 2) { |
398 const string& encodedFixture(test_table[i]); | 423 const string& encodedFixture(test_table[i]); |
399 const string& decodedFixture(test_table[i + 1]); | 424 const string& decodedFixture(test_table[i + 1]); |
400 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), | 425 DecodeStringTwice(encodedFixture, decodedFixture.size(), &buffer); |
401 encodedFixture); | |
402 | |
403 EXPECT_TRUE( | |
404 table_.DecodeString(&input_stream, decodedFixture.size(), &buffer)); | |
405 EXPECT_EQ(decodedFixture, buffer); | 426 EXPECT_EQ(decodedFixture, buffer); |
406 buffer = EncodeString(decodedFixture); | 427 buffer = EncodeString(decodedFixture); |
407 EXPECT_EQ(encodedFixture, buffer); | 428 EXPECT_EQ(encodedFixture, buffer); |
408 } | 429 } |
409 } | 430 } |
410 | 431 |
411 TEST_F(HpackHuffmanTableTest, RoundTripIndvidualSymbols) { | 432 TEST_F(HpackHuffmanTableTest, RoundTripIndividualSymbols) { |
412 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); | |
413 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); | |
414 | |
415 for (size_t i = 0; i != 256; i++) { | 433 for (size_t i = 0; i != 256; i++) { |
416 char c = static_cast<char>(i); | 434 char c = static_cast<char>(i); |
417 char storage[3] = {c, c, c}; | 435 char storage[3] = {c, c, c}; |
418 StringPiece input(storage, arraysize(storage)); | 436 StringPiece input(storage, arraysize(storage)); |
419 | |
420 string buffer_in = EncodeString(input); | 437 string buffer_in = EncodeString(input); |
421 string buffer_out; | 438 string buffer_out; |
422 | 439 |
423 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), | 440 DecodeStringTwice(buffer_in, input.size(), &buffer_out); |
424 buffer_in); | |
425 EXPECT_TRUE(table_.DecodeString(&input_stream, input.size(), &buffer_out)); | |
426 EXPECT_EQ(input, buffer_out); | 441 EXPECT_EQ(input, buffer_out); |
427 } | 442 } |
428 } | 443 } |
429 | 444 |
430 TEST_F(HpackHuffmanTableTest, RoundTripSymbolSequence) { | 445 TEST_F(HpackHuffmanTableTest, RoundTripSymbolSequence) { |
431 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); | |
432 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); | |
433 | |
434 char storage[512]; | 446 char storage[512]; |
435 for (size_t i = 0; i != 256; i++) { | 447 for (size_t i = 0; i != 256; i++) { |
436 storage[i] = static_cast<char>(i); | 448 storage[i] = static_cast<char>(i); |
437 storage[511 - i] = static_cast<char>(i); | 449 storage[511 - i] = static_cast<char>(i); |
438 } | 450 } |
439 StringPiece input(storage, arraysize(storage)); | 451 StringPiece input(storage, arraysize(storage)); |
440 | 452 |
441 string buffer_in = EncodeString(input); | 453 string buffer_in = EncodeString(input); |
442 string buffer_out; | 454 string buffer_out; |
443 | 455 DecodeStringTwice(buffer_in, input.size(), &buffer_out); |
444 HpackInputStream input_stream(std::numeric_limits<uint32_t>::max(), | |
445 buffer_in); | |
446 EXPECT_TRUE(table_.DecodeString(&input_stream, input.size(), &buffer_out)); | |
447 EXPECT_EQ(input, buffer_out); | 456 EXPECT_EQ(input, buffer_out); |
448 } | 457 } |
449 | 458 |
450 TEST_F(HpackHuffmanTableTest, EncodedSizeAgreesWithEncodeString) { | 459 TEST_F(HpackHuffmanTableTest, EncodedSizeAgreesWithEncodeString) { |
451 std::vector<HpackHuffmanSymbol> code = HpackHuffmanCode(); | |
452 EXPECT_TRUE(table_.Initialize(&code[0], code.size())); | |
453 | |
454 string test_table[] = { | 460 string test_table[] = { |
455 "", | 461 "", |
456 "Mon, 21 Oct 2013 20:13:21 GMT", | 462 "Mon, 21 Oct 2013 20:13:21 GMT", |
457 "https://www.example.com", | 463 "https://www.example.com", |
458 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", | 464 "foo=ASDJKHQKBZXOQWEOPIUAXQWEOIU; max-age=3600; version=1", |
459 string(1, '\0'), | 465 string(1, '\0'), |
460 string("foo\0bar", 7), | 466 string("foo\0bar", 7), |
461 string(256, '\0'), | 467 string(256, '\0'), |
462 }; | 468 }; |
463 for (size_t i = 0; i != 256; ++i) { | 469 for (size_t i = 0; i != 256; ++i) { |
464 // Expand last |test_table| entry to cover all codes. | 470 // Expand last |test_table| entry to cover all codes. |
465 test_table[arraysize(test_table) - 1][i] = static_cast<char>(i); | 471 test_table[arraysize(test_table) - 1][i] = static_cast<char>(i); |
466 } | 472 } |
467 | 473 |
468 HpackOutputStream output_stream; | 474 HpackOutputStream output_stream; |
469 string encoding; | 475 string encoding; |
470 for (size_t i = 0; i != arraysize(test_table); ++i) { | 476 for (size_t i = 0; i != arraysize(test_table); ++i) { |
471 table_.EncodeString(test_table[i], &output_stream); | 477 table_.EncodeString(test_table[i], &output_stream); |
472 output_stream.TakeString(&encoding); | 478 output_stream.TakeString(&encoding); |
473 EXPECT_EQ(encoding.size(), table_.EncodedSize(test_table[i])); | 479 EXPECT_EQ(encoding.size(), table_.EncodedSize(test_table[i])); |
474 } | 480 } |
475 } | 481 } |
476 | 482 |
477 } // namespace | 483 } // namespace |
478 | 484 |
479 } // namespace test | 485 } // namespace test |
480 | 486 |
481 } // namespace net | 487 } // namespace net |
OLD | NEW |