| 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 |