OLD | NEW |
(Empty) | |
| 1 #include "net/spdy/hpack_header_table.h" |
| 2 |
| 3 #include <algorithm> |
| 4 #include <set> |
| 5 #include <string> |
| 6 #include <vector> |
| 7 |
| 8 #include "base/basictypes.h" |
| 9 #include "base/macros.h" |
| 10 #include "net/spdy/hpack_entry.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" |
| 12 |
| 13 namespace net { |
| 14 |
| 15 namespace { |
| 16 |
| 17 using std::string; |
| 18 |
| 19 typedef std::vector<HpackEntry> HpackEntryVector; |
| 20 |
| 21 // Returns an entry whose Size() is equal to the given one. |
| 22 HpackEntry MakeEntryOfSize(uint32 size) { |
| 23 EXPECT_GE(size, HpackEntry::kSizeOverhead); |
| 24 string name((size - HpackEntry::kSizeOverhead) / 2, 'n'); |
| 25 string value(size - HpackEntry::kSizeOverhead - name.size(), 'v'); |
| 26 HpackEntry entry(name, value); |
| 27 EXPECT_EQ(size, entry.Size()); |
| 28 return entry; |
| 29 } |
| 30 |
| 31 // Returns a vector of entries whose total size is equal to the given |
| 32 // one. |
| 33 HpackEntryVector MakeEntriesOfTotalSize(uint32 total_size) { |
| 34 EXPECT_GE(total_size, HpackEntry::kSizeOverhead); |
| 35 uint32 entry_size = HpackEntry::kSizeOverhead; |
| 36 uint32 remaining_size = total_size; |
| 37 HpackEntryVector entries; |
| 38 while (remaining_size > 0) { |
| 39 EXPECT_LE(entry_size, remaining_size); |
| 40 entries.push_back(MakeEntryOfSize(entry_size)); |
| 41 remaining_size -= entry_size; |
| 42 entry_size = std::min(remaining_size, entry_size + 32); |
| 43 } |
| 44 return entries; |
| 45 } |
| 46 |
| 47 // Adds the given vector of entries to the given header table, |
| 48 // expecting no eviction to happen. |
| 49 void AddEntriesExpectNoEviction(const HpackEntryVector& entries, |
| 50 HpackHeaderTable* header_table) { |
| 51 int start_entry_count = header_table->GetEntryCount(); |
| 52 for (HpackEntryVector::const_iterator it = entries.begin(); |
| 53 it != entries.end(); ++it) { |
| 54 int32 index = -1; |
| 55 std::vector<uint32> removed_referenced_indices; |
| 56 header_table->TryAddEntry(*it, &index, &removed_referenced_indices); |
| 57 EXPECT_EQ(0, index); |
| 58 EXPECT_TRUE(removed_referenced_indices.empty()); |
| 59 EXPECT_EQ(start_entry_count + (it - entries.begin()) + 1, |
| 60 header_table->GetEntryCount()); |
| 61 } |
| 62 |
| 63 for (HpackEntryVector::const_iterator it = entries.begin(); |
| 64 it != entries.end(); ++it) { |
| 65 uint32 index = header_table->GetEntryCount() - (it - entries.begin()) - 1; |
| 66 HpackEntry entry = header_table->GetEntry(index); |
| 67 EXPECT_TRUE(it->Equals(entry)) |
| 68 << "it = " << it->GetDebugString() << " != entry = " |
| 69 << entry.GetDebugString(); |
| 70 } |
| 71 } |
| 72 |
| 73 // Returns the set of all indices in header_table that are in that |
| 74 // table's reference set. |
| 75 std::set<uint32> GetReferenceSet(const HpackHeaderTable& header_table) { |
| 76 std::set<uint32> reference_set; |
| 77 for (uint32 i = 0; i < header_table.GetEntryCount(); ++i) { |
| 78 if (header_table.GetEntry(i).IsReferenced()) { |
| 79 reference_set.insert(i); |
| 80 } |
| 81 } |
| 82 return reference_set; |
| 83 } |
| 84 |
| 85 // Fill a header table with entries. Make sure the entries are in |
| 86 // reverse order in the header table. |
| 87 TEST(HpackHeaderTableTest, TryAddEntryBasic) { |
| 88 HpackHeaderTable header_table; |
| 89 EXPECT_EQ(0u, header_table.size()); |
| 90 |
| 91 HpackEntryVector entries = MakeEntriesOfTotalSize(header_table.max_size()); |
| 92 |
| 93 // Most of the checks are in AddEntriesExpectNoEviction(). |
| 94 AddEntriesExpectNoEviction(entries, &header_table); |
| 95 EXPECT_EQ(header_table.max_size(), header_table.size()); |
| 96 } |
| 97 |
| 98 // Fill a header table with entries, and then ramp the table's max |
| 99 // size down to evict an entry one at a time. Make sure the eviction |
| 100 // happens as expected. |
| 101 TEST(HpackHeaderTableTest, SetMaxSize) { |
| 102 HpackHeaderTable header_table; |
| 103 |
| 104 HpackEntryVector entries = MakeEntriesOfTotalSize(header_table.max_size()); |
| 105 AddEntriesExpectNoEviction(entries, &header_table); |
| 106 |
| 107 for (HpackEntryVector::const_iterator it = entries.begin(); |
| 108 it != entries.end(); ++it) { |
| 109 uint32 expected_count = entries.end() - it; |
| 110 EXPECT_EQ(expected_count, header_table.GetEntryCount()); |
| 111 |
| 112 header_table.SetMaxSize(header_table.size() + 1); |
| 113 EXPECT_EQ(expected_count, header_table.GetEntryCount()); |
| 114 |
| 115 header_table.SetMaxSize(header_table.size()); |
| 116 EXPECT_EQ(expected_count, header_table.GetEntryCount()); |
| 117 |
| 118 --expected_count; |
| 119 header_table.SetMaxSize(header_table.size() - 1); |
| 120 EXPECT_EQ(expected_count, header_table.GetEntryCount()); |
| 121 } |
| 122 |
| 123 EXPECT_EQ(0u, header_table.size()); |
| 124 } |
| 125 |
| 126 // Setting the max size of a header table to zero should clear its |
| 127 // reference set. |
| 128 TEST(HpackHeaderTableTest, SetMaxSizeZeroClearsReferenceSet) { |
| 129 HpackHeaderTable header_table; |
| 130 |
| 131 HpackEntryVector entries = MakeEntriesOfTotalSize(header_table.max_size()); |
| 132 AddEntriesExpectNoEviction(entries, &header_table); |
| 133 |
| 134 std::set<uint32> expected_reference_set; |
| 135 for (uint32 i = 0; i < header_table.GetEntryCount(); ++i) { |
| 136 header_table.GetMutableEntry(i)->SetReferenced(true); |
| 137 expected_reference_set.insert(i); |
| 138 } |
| 139 EXPECT_EQ(expected_reference_set, GetReferenceSet(header_table)); |
| 140 |
| 141 header_table.SetMaxSize(0); |
| 142 EXPECT_TRUE(GetReferenceSet(header_table).empty()); |
| 143 } |
| 144 |
| 145 // Fill a header table with entries, and then add an entry just big |
| 146 // enough to cause eviction of all but one entry. Make sure the |
| 147 // eviction happens as expected and the long entry is inserted into |
| 148 // the table. |
| 149 TEST(HpackHeaderTableTest, TryAddEntryEviction) { |
| 150 HpackHeaderTable header_table; |
| 151 |
| 152 HpackEntryVector entries = MakeEntriesOfTotalSize(header_table.max_size()); |
| 153 AddEntriesExpectNoEviction(entries, &header_table); |
| 154 |
| 155 EXPECT_EQ(entries.size(), header_table.GetEntryCount()); |
| 156 HpackEntry first_entry = header_table.GetEntry(0); |
| 157 HpackEntry long_entry = |
| 158 MakeEntryOfSize(header_table.size() - first_entry.Size()); |
| 159 |
| 160 header_table.SetMaxSize(header_table.size()); |
| 161 EXPECT_EQ(entries.size(), header_table.GetEntryCount()); |
| 162 |
| 163 std::set<uint32> expected_reference_set; |
| 164 for (uint32 i = 1; i < header_table.GetEntryCount(); ++i) { |
| 165 header_table.GetMutableEntry(i)->SetReferenced(true); |
| 166 expected_reference_set.insert(i); |
| 167 } |
| 168 EXPECT_EQ(expected_reference_set, GetReferenceSet(header_table)); |
| 169 |
| 170 int32 index = -1; |
| 171 std::vector<uint32> removed_referenced_indices; |
| 172 header_table.TryAddEntry(long_entry, &index, &removed_referenced_indices); |
| 173 |
| 174 EXPECT_EQ(0, index); |
| 175 EXPECT_EQ(expected_reference_set, |
| 176 std::set<uint32>(removed_referenced_indices.begin(), |
| 177 removed_referenced_indices.end())); |
| 178 EXPECT_TRUE(GetReferenceSet(header_table).empty()); |
| 179 EXPECT_EQ(2u, header_table.GetEntryCount()); |
| 180 EXPECT_TRUE(header_table.GetEntry(0).Equals(long_entry)); |
| 181 EXPECT_TRUE(header_table.GetEntry(1).Equals(first_entry)); |
| 182 } |
| 183 |
| 184 // Fill a header table with entries, and then add an entry bigger than |
| 185 // the entire table. Make sure no entry remains in the table. |
| 186 TEST(HpackHeaderTableTest, TryAddTooLargeEntry) { |
| 187 HpackHeaderTable header_table; |
| 188 |
| 189 HpackEntryVector entries = MakeEntriesOfTotalSize(header_table.max_size()); |
| 190 AddEntriesExpectNoEviction(entries, &header_table); |
| 191 |
| 192 header_table.SetMaxSize(header_table.size()); |
| 193 EXPECT_EQ(entries.size(), header_table.GetEntryCount()); |
| 194 |
| 195 std::set<uint32> expected_removed_referenced_indices; |
| 196 for (uint32 i = 0; i < header_table.GetEntryCount(); ++i) { |
| 197 header_table.GetMutableEntry(i)->SetReferenced(true); |
| 198 expected_removed_referenced_indices.insert(i); |
| 199 } |
| 200 |
| 201 HpackEntry long_entry = MakeEntryOfSize(header_table.size() + 1); |
| 202 int32 index = -1; |
| 203 std::vector<uint32> removed_referenced_indices; |
| 204 header_table.TryAddEntry(long_entry, &index, &removed_referenced_indices); |
| 205 |
| 206 EXPECT_EQ(-1, index); |
| 207 EXPECT_EQ(expected_removed_referenced_indices, |
| 208 std::set<uint32>(removed_referenced_indices.begin(), |
| 209 removed_referenced_indices.end())); |
| 210 EXPECT_EQ(0u, header_table.GetEntryCount()); |
| 211 } |
| 212 |
| 213 } // namespace |
| 214 |
| 215 } // namespace net |
OLD | NEW |