| 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_encoder.h" | 5 #include "net/spdy/hpack_encoder.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "testing/gmock/include/gmock/gmock.h" | 10 #include "testing/gmock/include/gmock/gmock.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 | 12 |
| 13 namespace net { | 13 namespace net { |
| 14 | 14 |
| 15 using base::StringPiece; | 15 using base::StringPiece; |
| 16 using std::string; | 16 using std::string; |
| 17 using testing::ElementsAre; | 17 using testing::ElementsAre; |
| 18 | 18 |
| 19 namespace test { | 19 namespace test { |
| 20 | 20 |
| 21 class HpackHeaderTablePeer { | 21 class HpackHeaderTablePeer { |
| 22 public: | 22 public: |
| 23 explicit HpackHeaderTablePeer(HpackHeaderTable* table) | 23 explicit HpackHeaderTablePeer(HpackHeaderTable* table) : table_(table) {} |
| 24 : table_(table) {} | |
| 25 | 24 |
| 26 HpackHeaderTable::EntryTable* dynamic_entries() { | 25 HpackHeaderTable::EntryTable* dynamic_entries() { |
| 27 return &table_->dynamic_entries_; | 26 return &table_->dynamic_entries_; |
| 28 } | 27 } |
| 29 | 28 |
| 30 private: | 29 private: |
| 31 HpackHeaderTable* table_; | 30 HpackHeaderTable* table_; |
| 32 }; | 31 }; |
| 33 | 32 |
| 34 class HpackEncoderPeer { | 33 class HpackEncoderPeer { |
| 35 public: | 34 public: |
| 36 typedef HpackEncoder::Representation Representation; | 35 typedef HpackEncoder::Representation Representation; |
| 37 typedef HpackEncoder::Representations Representations; | 36 typedef HpackEncoder::Representations Representations; |
| 38 | 37 |
| 39 explicit HpackEncoderPeer(HpackEncoder* encoder) | 38 explicit HpackEncoderPeer(HpackEncoder* encoder) : encoder_(encoder) {} |
| 40 : encoder_(encoder) {} | |
| 41 | 39 |
| 42 HpackHeaderTable* table() { | 40 HpackHeaderTable* table() { return &encoder_->header_table_; } |
| 43 return &encoder_->header_table_; | 41 HpackHeaderTablePeer table_peer() { return HpackHeaderTablePeer(table()); } |
| 44 } | |
| 45 HpackHeaderTablePeer table_peer() { | |
| 46 return HpackHeaderTablePeer(table()); | |
| 47 } | |
| 48 bool allow_huffman_compression() { | 42 bool allow_huffman_compression() { |
| 49 return encoder_->allow_huffman_compression_; | 43 return encoder_->allow_huffman_compression_; |
| 50 } | 44 } |
| 51 void set_allow_huffman_compression(bool allow) { | 45 void set_allow_huffman_compression(bool allow) { |
| 52 encoder_->allow_huffman_compression_ = allow; | 46 encoder_->allow_huffman_compression_ = allow; |
| 53 } | 47 } |
| 54 void EmitString(StringPiece str) { | 48 void EmitString(StringPiece str) { encoder_->EmitString(str); } |
| 55 encoder_->EmitString(str); | 49 void TakeString(string* out) { encoder_->output_stream_.TakeString(out); } |
| 56 } | |
| 57 void TakeString(string* out) { | |
| 58 encoder_->output_stream_.TakeString(out); | |
| 59 } | |
| 60 void UpdateCharacterCounts(StringPiece str) { | 50 void UpdateCharacterCounts(StringPiece str) { |
| 61 encoder_->UpdateCharacterCounts(str); | 51 encoder_->UpdateCharacterCounts(str); |
| 62 } | 52 } |
| 63 static void CookieToCrumbs(StringPiece cookie, | 53 static void CookieToCrumbs(StringPiece cookie, |
| 64 std::vector<StringPiece>* out) { | 54 std::vector<StringPiece>* out) { |
| 65 Representations tmp; | 55 Representations tmp; |
| 66 HpackEncoder::CookieToCrumbs(make_pair("", cookie), &tmp); | 56 HpackEncoder::CookieToCrumbs(make_pair("", cookie), &tmp); |
| 67 | 57 |
| 68 out->clear(); | 58 out->clear(); |
| 69 for (size_t i = 0; i != tmp.size(); ++i) { | 59 for (size_t i = 0; i != tmp.size(); ++i) { |
| 70 out->push_back(tmp[i].second); | 60 out->push_back(tmp[i].second); |
| 71 } | 61 } |
| 72 } | 62 } |
| 73 | 63 |
| 74 private: | 64 private: |
| 75 HpackEncoder* encoder_; | 65 HpackEncoder* encoder_; |
| 76 }; | 66 }; |
| 77 | 67 |
| 78 } // namespace test | 68 } // namespace test |
| 79 | 69 |
| 80 namespace { | 70 namespace { |
| 81 | 71 |
| 82 using std::map; | 72 using std::map; |
| 83 using testing::ElementsAre; | 73 using testing::ElementsAre; |
| 84 | 74 |
| 85 class HpackEncoderTest : public ::testing::Test { | 75 class HpackEncoderTest : public ::testing::Test { |
| 86 protected: | 76 protected: |
| 87 typedef test::HpackEncoderPeer::Representations Representations; | 77 typedef test::HpackEncoderPeer::Representations Representations; |
| 88 | 78 |
| 89 HpackEncoderTest() | 79 HpackEncoderTest() : encoder_(ObtainHpackHuffmanTable()), peer_(&encoder_) {} |
| 90 : encoder_(ObtainHpackHuffmanTable()), | |
| 91 peer_(&encoder_) {} | |
| 92 | 80 |
| 93 virtual void SetUp() { | 81 virtual void SetUp() { |
| 94 static_ = peer_.table()->GetByIndex(1); | 82 static_ = peer_.table()->GetByIndex(1); |
| 95 // Populate dynamic entries into the table fixture. For simplicity each | 83 // Populate dynamic entries into the table fixture. For simplicity each |
| 96 // entry has name.size() + value.size() == 10. | 84 // entry has name.size() + value.size() == 10. |
| 97 key_1_ = peer_.table()->TryAddEntry("key1", "value1"); | 85 key_1_ = peer_.table()->TryAddEntry("key1", "value1"); |
| 98 key_2_ = peer_.table()->TryAddEntry("key2", "value2"); | 86 key_2_ = peer_.table()->TryAddEntry("key2", "value2"); |
| 99 cookie_a_ = peer_.table()->TryAddEntry("cookie", "a=bb"); | 87 cookie_a_ = peer_.table()->TryAddEntry("cookie", "a=bb"); |
| 100 cookie_c_ = peer_.table()->TryAddEntry("cookie", "c=dd"); | 88 cookie_c_ = peer_.table()->TryAddEntry("cookie", "c=dd"); |
| 101 | 89 |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 // |key_2_| & |cookie_c_| are toggled on. | 353 // |key_2_| & |cookie_c_| are toggled on. |
| 366 // |cookie_a_| is toggled off. | 354 // |cookie_a_| is toggled off. |
| 367 // A new cookie entry is added. | 355 // A new cookie entry is added. |
| 368 { | 356 { |
| 369 map<string, string> headers; | 357 map<string, string> headers; |
| 370 headers["key1"] = "value1"; | 358 headers["key1"] = "value1"; |
| 371 headers["key2"] = "value2"; | 359 headers["key2"] = "value2"; |
| 372 headers["cookie"] = "c=dd; e=ff"; | 360 headers["cookie"] = "c=dd; e=ff"; |
| 373 | 361 |
| 374 ExpectIndex(cookie_c_->Index()); // Toggle on. | 362 ExpectIndex(cookie_c_->Index()); // Toggle on. |
| 375 ExpectIndex(key_1_->Index()); // Double-toggle before eviction. | 363 ExpectIndex(key_1_->Index()); // Double-toggle before eviction. |
| 376 ExpectIndex(key_1_->Index()); | 364 ExpectIndex(key_1_->Index()); |
| 377 ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff"); | 365 ExpectIndexedLiteral(peer_.table()->GetByName("cookie"), "e=ff"); |
| 378 ExpectIndex(key_2_->Index() + 1); // Toggle on. Add 1 to reflect insertion. | 366 ExpectIndex(key_2_->Index() + 1); // Toggle on. Add 1 to reflect insertion. |
| 379 ExpectIndex(cookie_a_->Index() + 1); // Toggle off. | 367 ExpectIndex(cookie_a_->Index() + 1); // Toggle off. |
| 380 CompareWithExpectedEncoding(headers); | 368 CompareWithExpectedEncoding(headers); |
| 381 } | 369 } |
| 382 // Pass 3: |key_2_| is evicted and implicitly toggled off. | 370 // Pass 3: |key_2_| is evicted and implicitly toggled off. |
| 383 // |cookie_c_| is explicitly toggled off. | 371 // |cookie_c_| is explicitly toggled off. |
| 384 // "key1" is re-inserted. | 372 // "key1" is re-inserted. |
| 385 { | 373 { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 | 409 |
| 422 peer.CookieToCrumbs("foo;bar; baz;baz;bing;", &out); | 410 peer.CookieToCrumbs("foo;bar; baz;baz;bing;", &out); |
| 423 EXPECT_THAT(out, ElementsAre("", "bar", "baz", "bing", "foo")); | 411 EXPECT_THAT(out, ElementsAre("", "bar", "baz", "bing", "foo")); |
| 424 } | 412 } |
| 425 | 413 |
| 426 TEST_F(HpackEncoderTest, UpdateCharacterCounts) { | 414 TEST_F(HpackEncoderTest, UpdateCharacterCounts) { |
| 427 std::vector<size_t> counts(256, 0); | 415 std::vector<size_t> counts(256, 0); |
| 428 size_t total_counts = 0; | 416 size_t total_counts = 0; |
| 429 encoder_.SetCharCountsStorage(&counts, &total_counts); | 417 encoder_.SetCharCountsStorage(&counts, &total_counts); |
| 430 | 418 |
| 431 char kTestString[] = "foo\0\1\xff""boo"; | 419 char kTestString[] = |
| 420 "foo\0\1\xff" |
| 421 "boo"; |
| 432 peer_.UpdateCharacterCounts( | 422 peer_.UpdateCharacterCounts( |
| 433 StringPiece(kTestString, arraysize(kTestString) - 1)); | 423 StringPiece(kTestString, arraysize(kTestString) - 1)); |
| 434 | 424 |
| 435 std::vector<size_t> expect(256, 0); | 425 std::vector<size_t> expect(256, 0); |
| 436 expect[static_cast<uint8>('f')] = 1; | 426 expect[static_cast<uint8>('f')] = 1; |
| 437 expect[static_cast<uint8>('o')] = 4; | 427 expect[static_cast<uint8>('o')] = 4; |
| 438 expect[static_cast<uint8>('\0')] = 1; | 428 expect[static_cast<uint8>('\0')] = 1; |
| 439 expect[static_cast<uint8>('\1')] = 1; | 429 expect[static_cast<uint8>('\1')] = 1; |
| 440 expect[static_cast<uint8>('\xff')] = 1; | 430 expect[static_cast<uint8>('\xff')] = 1; |
| 441 expect[static_cast<uint8>('b')] = 1; | 431 expect[static_cast<uint8>('b')] = 1; |
| 442 | 432 |
| 443 EXPECT_EQ(expect, counts); | 433 EXPECT_EQ(expect, counts); |
| 444 EXPECT_EQ(9u, total_counts); | 434 EXPECT_EQ(9u, total_counts); |
| 445 } | 435 } |
| 446 | 436 |
| 447 } // namespace | 437 } // namespace |
| 448 | 438 |
| 449 } // namespace net | 439 } // namespace net |
| OLD | NEW |