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 |