| 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_header_table.h" | 5 #include "net/spdy/hpack/hpack_header_table.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <string> | |
| 10 #include <vector> | 9 #include <vector> |
| 11 | 10 |
| 12 #include "base/macros.h" | 11 #include "base/macros.h" |
| 13 #include "net/spdy/hpack/hpack_constants.h" | 12 #include "net/spdy/hpack/hpack_constants.h" |
| 14 #include "net/spdy/hpack/hpack_entry.h" | 13 #include "net/spdy/hpack/hpack_entry.h" |
| 14 #include "net/spdy/platform/api/spdy_string.h" |
| 15 #include "net/spdy/spdy_flags.h" | 15 #include "net/spdy/spdy_flags.h" |
| 16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 | 17 |
| 18 namespace net { | 18 namespace net { |
| 19 | 19 |
| 20 using std::distance; | 20 using std::distance; |
| 21 using std::string; | |
| 22 | 21 |
| 23 namespace test { | 22 namespace test { |
| 24 | 23 |
| 25 class HpackHeaderTablePeer { | 24 class HpackHeaderTablePeer { |
| 26 public: | 25 public: |
| 27 explicit HpackHeaderTablePeer(HpackHeaderTable* table) : table_(table) {} | 26 explicit HpackHeaderTablePeer(HpackHeaderTable* table) : table_(table) {} |
| 28 | 27 |
| 29 const HpackHeaderTable::EntryTable& dynamic_entries() { | 28 const HpackHeaderTable::EntryTable& dynamic_entries() { |
| 30 return table_->dynamic_entries_; | 29 return table_->dynamic_entries_; |
| 31 } | 30 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 | 69 |
| 71 class HpackHeaderTableTest : public ::testing::Test { | 70 class HpackHeaderTableTest : public ::testing::Test { |
| 72 protected: | 71 protected: |
| 73 typedef std::vector<HpackEntry> HpackEntryVector; | 72 typedef std::vector<HpackEntry> HpackEntryVector; |
| 74 | 73 |
| 75 HpackHeaderTableTest() : table_(), peer_(&table_) {} | 74 HpackHeaderTableTest() : table_(), peer_(&table_) {} |
| 76 | 75 |
| 77 // Returns an entry whose Size() is equal to the given one. | 76 // Returns an entry whose Size() is equal to the given one. |
| 78 static HpackEntry MakeEntryOfSize(uint32_t size) { | 77 static HpackEntry MakeEntryOfSize(uint32_t size) { |
| 79 EXPECT_GE(size, HpackEntry::kSizeOverhead); | 78 EXPECT_GE(size, HpackEntry::kSizeOverhead); |
| 80 string name((size - HpackEntry::kSizeOverhead) / 2, 'n'); | 79 SpdyString name((size - HpackEntry::kSizeOverhead) / 2, 'n'); |
| 81 string value(size - HpackEntry::kSizeOverhead - name.size(), 'v'); | 80 SpdyString value(size - HpackEntry::kSizeOverhead - name.size(), 'v'); |
| 82 HpackEntry entry(name, value, false, 0); | 81 HpackEntry entry(name, value, false, 0); |
| 83 EXPECT_EQ(size, entry.Size()); | 82 EXPECT_EQ(size, entry.Size()); |
| 84 return entry; | 83 return entry; |
| 85 } | 84 } |
| 86 | 85 |
| 87 // Returns a vector of entries whose total size is equal to the given | 86 // Returns a vector of entries whose total size is equal to the given |
| 88 // one. | 87 // one. |
| 89 static HpackEntryVector MakeEntriesOfTotalSize(uint32_t total_size) { | 88 static HpackEntryVector MakeEntriesOfTotalSize(uint32_t total_size) { |
| 90 EXPECT_GE(total_size, HpackEntry::kSizeOverhead); | 89 EXPECT_GE(total_size, HpackEntry::kSizeOverhead); |
| 91 uint32_t entry_size = HpackEntry::kSizeOverhead; | 90 uint32_t entry_size = HpackEntry::kSizeOverhead; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 117 for (size_t i = 0; i != entries.size(); ++i) { | 116 for (size_t i = 0; i != entries.size(); ++i) { |
| 118 // Static table has 61 entries, dynamic entries follow those. | 117 // Static table has 61 entries, dynamic entries follow those. |
| 119 size_t index = 61 + entries.size() - i; | 118 size_t index = 61 + entries.size() - i; |
| 120 const HpackEntry* entry = table_.GetByIndex(index); | 119 const HpackEntry* entry = table_.GetByIndex(index); |
| 121 EXPECT_EQ(entries[i].name(), entry->name()); | 120 EXPECT_EQ(entries[i].name(), entry->name()); |
| 122 EXPECT_EQ(entries[i].value(), entry->value()); | 121 EXPECT_EQ(entries[i].value(), entry->value()); |
| 123 EXPECT_EQ(index, table_.IndexOf(entry)); | 122 EXPECT_EQ(index, table_.IndexOf(entry)); |
| 124 } | 123 } |
| 125 } | 124 } |
| 126 | 125 |
| 127 HpackEntry DynamicEntry(const string& name, const string& value) { | 126 HpackEntry DynamicEntry(const SpdyString& name, const SpdyString& value) { |
| 128 peer_.AddDynamicEntry(name, value); | 127 peer_.AddDynamicEntry(name, value); |
| 129 return peer_.dynamic_entries().back(); | 128 return peer_.dynamic_entries().back(); |
| 130 } | 129 } |
| 131 | 130 |
| 132 HpackHeaderTable table_; | 131 HpackHeaderTable table_; |
| 133 test::HpackHeaderTablePeer peer_; | 132 test::HpackHeaderTablePeer peer_; |
| 134 }; | 133 }; |
| 135 | 134 |
| 136 TEST_F(HpackHeaderTableTest, StaticTableInitialization) { | 135 TEST_F(HpackHeaderTableTest, StaticTableInitialization) { |
| 137 EXPECT_EQ(0u, table_.size()); | 136 EXPECT_EQ(0u, table_.size()); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 EXPECT_EQ(entry2, | 251 EXPECT_EQ(entry2, |
| 253 table_.GetByNameAndValue(first_static_entry->name(), "Value Four")); | 252 table_.GetByNameAndValue(first_static_entry->name(), "Value Four")); |
| 254 | 253 |
| 255 // Evict |entry2|. Queries by its name & value are not found. | 254 // Evict |entry2|. Queries by its name & value are not found. |
| 256 peer_.Evict(1); | 255 peer_.Evict(1); |
| 257 EXPECT_EQ(NULL, | 256 EXPECT_EQ(NULL, |
| 258 table_.GetByNameAndValue(first_static_entry->name(), "Value Four")); | 257 table_.GetByNameAndValue(first_static_entry->name(), "Value Four")); |
| 259 } | 258 } |
| 260 | 259 |
| 261 TEST_F(HpackHeaderTableTest, SetSizes) { | 260 TEST_F(HpackHeaderTableTest, SetSizes) { |
| 262 string key = "key", value = "value"; | 261 SpdyString key = "key", value = "value"; |
| 263 const HpackEntry* entry1 = table_.TryAddEntry(key, value); | 262 const HpackEntry* entry1 = table_.TryAddEntry(key, value); |
| 264 const HpackEntry* entry2 = table_.TryAddEntry(key, value); | 263 const HpackEntry* entry2 = table_.TryAddEntry(key, value); |
| 265 const HpackEntry* entry3 = table_.TryAddEntry(key, value); | 264 const HpackEntry* entry3 = table_.TryAddEntry(key, value); |
| 266 | 265 |
| 267 // Set exactly large enough. No Evictions. | 266 // Set exactly large enough. No Evictions. |
| 268 size_t max_size = entry1->Size() + entry2->Size() + entry3->Size(); | 267 size_t max_size = entry1->Size() + entry2->Size() + entry3->Size(); |
| 269 table_.SetMaxSize(max_size); | 268 table_.SetMaxSize(max_size); |
| 270 EXPECT_EQ(3u, peer_.dynamic_entries().size()); | 269 EXPECT_EQ(3u, peer_.dynamic_entries().size()); |
| 271 | 270 |
| 272 // Set just too small. One eviction. | 271 // Set just too small. One eviction. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 284 // SETTINGS_HEADER_TABLE_SIZE upper-bounds |table_.max_size()|, | 283 // SETTINGS_HEADER_TABLE_SIZE upper-bounds |table_.max_size()|, |
| 285 // and will force evictions. | 284 // and will force evictions. |
| 286 max_size = entry3->Size() - 1; | 285 max_size = entry3->Size() - 1; |
| 287 table_.SetSettingsHeaderTableSize(max_size); | 286 table_.SetSettingsHeaderTableSize(max_size); |
| 288 EXPECT_EQ(max_size, table_.max_size()); | 287 EXPECT_EQ(max_size, table_.max_size()); |
| 289 EXPECT_EQ(max_size, table_.settings_size_bound()); | 288 EXPECT_EQ(max_size, table_.settings_size_bound()); |
| 290 EXPECT_EQ(0u, peer_.dynamic_entries().size()); | 289 EXPECT_EQ(0u, peer_.dynamic_entries().size()); |
| 291 } | 290 } |
| 292 | 291 |
| 293 TEST_F(HpackHeaderTableTest, EvictionCountForEntry) { | 292 TEST_F(HpackHeaderTableTest, EvictionCountForEntry) { |
| 294 string key = "key", value = "value"; | 293 SpdyString key = "key", value = "value"; |
| 295 const HpackEntry* entry1 = table_.TryAddEntry(key, value); | 294 const HpackEntry* entry1 = table_.TryAddEntry(key, value); |
| 296 const HpackEntry* entry2 = table_.TryAddEntry(key, value); | 295 const HpackEntry* entry2 = table_.TryAddEntry(key, value); |
| 297 size_t entry3_size = HpackEntry::Size(key, value); | 296 size_t entry3_size = HpackEntry::Size(key, value); |
| 298 | 297 |
| 299 // Just enough capacity for third entry. | 298 // Just enough capacity for third entry. |
| 300 table_.SetMaxSize(entry1->Size() + entry2->Size() + entry3_size); | 299 table_.SetMaxSize(entry1->Size() + entry2->Size() + entry3_size); |
| 301 EXPECT_EQ(0u, peer_.EvictionCountForEntry(key, value)); | 300 EXPECT_EQ(0u, peer_.EvictionCountForEntry(key, value)); |
| 302 EXPECT_EQ(1u, peer_.EvictionCountForEntry(key, value + "x")); | 301 EXPECT_EQ(1u, peer_.EvictionCountForEntry(key, value + "x")); |
| 303 | 302 |
| 304 // No extra capacity. Third entry would force evictions. | 303 // No extra capacity. Third entry would force evictions. |
| 305 table_.SetMaxSize(entry1->Size() + entry2->Size()); | 304 table_.SetMaxSize(entry1->Size() + entry2->Size()); |
| 306 EXPECT_EQ(1u, peer_.EvictionCountForEntry(key, value)); | 305 EXPECT_EQ(1u, peer_.EvictionCountForEntry(key, value)); |
| 307 EXPECT_EQ(2u, peer_.EvictionCountForEntry(key, value + "x")); | 306 EXPECT_EQ(2u, peer_.EvictionCountForEntry(key, value + "x")); |
| 308 } | 307 } |
| 309 | 308 |
| 310 TEST_F(HpackHeaderTableTest, EvictionCountToReclaim) { | 309 TEST_F(HpackHeaderTableTest, EvictionCountToReclaim) { |
| 311 string key = "key", value = "value"; | 310 SpdyString key = "key", value = "value"; |
| 312 const HpackEntry* entry1 = table_.TryAddEntry(key, value); | 311 const HpackEntry* entry1 = table_.TryAddEntry(key, value); |
| 313 const HpackEntry* entry2 = table_.TryAddEntry(key, value); | 312 const HpackEntry* entry2 = table_.TryAddEntry(key, value); |
| 314 | 313 |
| 315 EXPECT_EQ(1u, peer_.EvictionCountToReclaim(1)); | 314 EXPECT_EQ(1u, peer_.EvictionCountToReclaim(1)); |
| 316 EXPECT_EQ(1u, peer_.EvictionCountToReclaim(entry1->Size())); | 315 EXPECT_EQ(1u, peer_.EvictionCountToReclaim(entry1->Size())); |
| 317 EXPECT_EQ(2u, peer_.EvictionCountToReclaim(entry1->Size() + 1)); | 316 EXPECT_EQ(2u, peer_.EvictionCountToReclaim(entry1->Size() + 1)); |
| 318 EXPECT_EQ(2u, peer_.EvictionCountToReclaim(entry1->Size() + entry2->Size())); | 317 EXPECT_EQ(2u, peer_.EvictionCountToReclaim(entry1->Size() + entry2->Size())); |
| 319 } | 318 } |
| 320 | 319 |
| 321 // Fill a header table with entries. Make sure the entries are in | 320 // Fill a header table with entries. Make sure the entries are in |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 HpackHeaderTable::EntryHasher hasher; | 439 HpackHeaderTable::EntryHasher hasher; |
| 441 EXPECT_EQ(hasher(&entry1), hasher(&entry2)); | 440 EXPECT_EQ(hasher(&entry1), hasher(&entry2)); |
| 442 | 441 |
| 443 HpackHeaderTable::EntriesEq eq; | 442 HpackHeaderTable::EntriesEq eq; |
| 444 EXPECT_TRUE(eq(&entry1, &entry2)); | 443 EXPECT_TRUE(eq(&entry1, &entry2)); |
| 445 } | 444 } |
| 446 | 445 |
| 447 } // namespace | 446 } // namespace |
| 448 | 447 |
| 449 } // namespace net | 448 } // namespace net |
| OLD | NEW |