| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/spdy/http2_priority_dependencies.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "testing/gmock/include/gmock/gmock.h" | |
| 10 #include "testing/platform_test.h" | |
| 11 | |
| 12 using ::testing::ContainerEq; | |
| 13 | |
| 14 namespace net { | |
| 15 | |
| 16 bool operator==(const Http2PriorityDependencies::DependencyUpdate& a, | |
| 17 const Http2PriorityDependencies::DependencyUpdate& b) { | |
| 18 return a.id == b.id && a.dependent_stream_id == b.dependent_stream_id && | |
| 19 a.exclusive == b.exclusive; | |
| 20 } | |
| 21 | |
| 22 std::ostream& operator<<( | |
| 23 std::ostream& os, | |
| 24 const std::vector<Http2PriorityDependencies::DependencyUpdate>& v) { | |
| 25 for (auto e : v) { | |
| 26 os << "{" << e.id << "," << e.dependent_stream_id << "," | |
| 27 << (e.exclusive ? "true" : "false") << "}"; | |
| 28 } | |
| 29 return os; | |
| 30 } | |
| 31 | |
| 32 class HttpPriorityDependencyTest : public PlatformTest { | |
| 33 public: | |
| 34 HttpPriorityDependencyTest() : next_id_(0u) {} | |
| 35 | |
| 36 // Fixed priority values to use for testing. | |
| 37 enum { | |
| 38 HIGHEST = kV3HighestPriority, | |
| 39 MEDIUM = HIGHEST + 1, | |
| 40 LOW = MEDIUM + 1, | |
| 41 LOWEST = kV3LowestPriority, | |
| 42 }; | |
| 43 | |
| 44 SpdyStreamId GetId() { return ++next_id_; } | |
| 45 | |
| 46 void TestStreamCreation(SpdyStreamId new_id, | |
| 47 SpdyPriority priority, | |
| 48 SpdyStreamId expected_dependent_id) { | |
| 49 SpdyStreamId dependent_id = 999u; | |
| 50 bool exclusive = false; | |
| 51 dependency_state_.OnStreamCreation(new_id, priority, &dependent_id, | |
| 52 &exclusive); | |
| 53 if (expected_dependent_id != dependent_id || !exclusive) { | |
| 54 ADD_FAILURE() << "OnStreamCreation(" << new_id << ", " << int(priority) | |
| 55 << ")\n" | |
| 56 << " Got: (" << dependent_id << ", " << exclusive << ")\n" | |
| 57 << " Want: (" << expected_dependent_id << ", true)\n"; | |
| 58 } | |
| 59 } | |
| 60 | |
| 61 struct ExpectedDependencyUpdate { | |
| 62 SpdyStreamId id; | |
| 63 SpdyStreamId parent_id; | |
| 64 }; | |
| 65 | |
| 66 void TestStreamUpdate(SpdyStreamId id, | |
| 67 SpdyPriority new_priority, | |
| 68 std::vector<ExpectedDependencyUpdate> expected) { | |
| 69 auto value = dependency_state_.OnStreamUpdate(id, new_priority); | |
| 70 std::vector<Http2PriorityDependencies::DependencyUpdate> expected_value; | |
| 71 for (auto e : expected) { | |
| 72 expected_value.push_back({e.id, e.parent_id, true /* exclusive */}); | |
| 73 } | |
| 74 if (value != expected_value) { | |
| 75 ADD_FAILURE() << "OnStreamUpdate(" << id << ", " << int(new_priority) | |
| 76 << ")\n" | |
| 77 << " Value: " << value << "\n" | |
| 78 << " Expected: " << expected_value << "\n"; | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 void OnStreamDestruction(SpdyStreamId id) { | |
| 83 dependency_state_.OnStreamDestruction(id); | |
| 84 } | |
| 85 | |
| 86 private: | |
| 87 SpdyStreamId next_id_; | |
| 88 Http2PriorityDependencies dependency_state_; | |
| 89 }; | |
| 90 | |
| 91 // Confirm dependencies correct for entries at the same priority. | |
| 92 TEST_F(HttpPriorityDependencyTest, SamePriority) { | |
| 93 const SpdyStreamId first_id = GetId(); | |
| 94 const SpdyStreamId second_id = GetId(); | |
| 95 const SpdyStreamId third_id = GetId(); | |
| 96 | |
| 97 TestStreamCreation(first_id, MEDIUM, 0u); | |
| 98 TestStreamCreation(second_id, MEDIUM, first_id); | |
| 99 TestStreamCreation(third_id, MEDIUM, second_id); | |
| 100 } | |
| 101 | |
| 102 // Confirm dependencies correct for entries at different priorities, increasing. | |
| 103 TEST_F(HttpPriorityDependencyTest, DifferentPriorityIncreasing) { | |
| 104 const SpdyStreamId first_id = GetId(); | |
| 105 const SpdyStreamId second_id = GetId(); | |
| 106 const SpdyStreamId third_id = GetId(); | |
| 107 | |
| 108 TestStreamCreation(first_id, LOWEST, 0u); | |
| 109 TestStreamCreation(second_id, MEDIUM, 0u); | |
| 110 TestStreamCreation(third_id, HIGHEST, 0u); | |
| 111 } | |
| 112 | |
| 113 // Confirm dependencies correct for entries at different priorities, increasing. | |
| 114 TEST_F(HttpPriorityDependencyTest, DifferentPriorityDecreasing) { | |
| 115 const SpdyStreamId first_id = GetId(); | |
| 116 const SpdyStreamId second_id = GetId(); | |
| 117 const SpdyStreamId third_id = GetId(); | |
| 118 | |
| 119 TestStreamCreation(first_id, HIGHEST, 0u); | |
| 120 TestStreamCreation(second_id, MEDIUM, first_id); | |
| 121 TestStreamCreation(third_id, LOWEST, second_id); | |
| 122 } | |
| 123 | |
| 124 // Confirm dependencies correct if requests are completed between before | |
| 125 // next creation. | |
| 126 TEST_F(HttpPriorityDependencyTest, CompletionBeforeIssue) { | |
| 127 const SpdyStreamId first_id = GetId(); | |
| 128 const SpdyStreamId second_id = GetId(); | |
| 129 const SpdyStreamId third_id = GetId(); | |
| 130 | |
| 131 TestStreamCreation(first_id, HIGHEST, 0u); | |
| 132 OnStreamDestruction(first_id); | |
| 133 TestStreamCreation(second_id, MEDIUM, 0u); | |
| 134 OnStreamDestruction(second_id); | |
| 135 TestStreamCreation(third_id, LOWEST, 0u); | |
| 136 } | |
| 137 | |
| 138 // Confirm dependencies correct if some requests are completed between before | |
| 139 // next creation. | |
| 140 TEST_F(HttpPriorityDependencyTest, SomeCompletions) { | |
| 141 const SpdyStreamId first_id = GetId(); | |
| 142 const SpdyStreamId second_id = GetId(); | |
| 143 const SpdyStreamId third_id = GetId(); | |
| 144 | |
| 145 TestStreamCreation(first_id, HIGHEST, 0u); | |
| 146 TestStreamCreation(second_id, MEDIUM, first_id); | |
| 147 OnStreamDestruction(second_id); | |
| 148 TestStreamCreation(third_id, LOWEST, first_id); | |
| 149 } | |
| 150 | |
| 151 // A more complex example parallel to a simple web page. | |
| 152 TEST_F(HttpPriorityDependencyTest, Complex) { | |
| 153 const SpdyStreamId first_id = GetId(); | |
| 154 const SpdyStreamId second_id = GetId(); | |
| 155 const SpdyStreamId third_id = GetId(); | |
| 156 const SpdyStreamId fourth_id = GetId(); | |
| 157 const SpdyStreamId fifth_id = GetId(); | |
| 158 const SpdyStreamId sixth_id = GetId(); | |
| 159 const SpdyStreamId seventh_id = GetId(); | |
| 160 const SpdyStreamId eighth_id = GetId(); | |
| 161 const SpdyStreamId nineth_id = GetId(); | |
| 162 const SpdyStreamId tenth_id = GetId(); | |
| 163 | |
| 164 TestStreamCreation(first_id, HIGHEST, 0u); | |
| 165 TestStreamCreation(second_id, MEDIUM, first_id); | |
| 166 TestStreamCreation(third_id, MEDIUM, second_id); | |
| 167 OnStreamDestruction(first_id); | |
| 168 TestStreamCreation(fourth_id, MEDIUM, third_id); | |
| 169 TestStreamCreation(fifth_id, LOWEST, fourth_id); | |
| 170 TestStreamCreation(sixth_id, MEDIUM, fourth_id); | |
| 171 OnStreamDestruction(third_id); | |
| 172 TestStreamCreation(seventh_id, MEDIUM, sixth_id); | |
| 173 TestStreamCreation(eighth_id, LOW, seventh_id); | |
| 174 OnStreamDestruction(second_id); | |
| 175 OnStreamDestruction(fourth_id); | |
| 176 OnStreamDestruction(fifth_id); | |
| 177 OnStreamDestruction(sixth_id); | |
| 178 OnStreamDestruction(seventh_id); | |
| 179 TestStreamCreation(nineth_id, MEDIUM, 0u); | |
| 180 TestStreamCreation(tenth_id, HIGHEST, 0u); | |
| 181 } | |
| 182 | |
| 183 // Confirm dependencies correct after updates with just one stream. | |
| 184 // All updates are no-ops. | |
| 185 TEST_F(HttpPriorityDependencyTest, UpdateSingleStream) { | |
| 186 const SpdyStreamId id = GetId(); | |
| 187 | |
| 188 TestStreamCreation(id, HIGHEST, 0); | |
| 189 | |
| 190 std::vector<ExpectedDependencyUpdate> empty; | |
| 191 TestStreamUpdate(id, HIGHEST, empty); | |
| 192 TestStreamUpdate(id, MEDIUM, empty); | |
| 193 TestStreamUpdate(id, LOWEST, empty); | |
| 194 TestStreamUpdate(id, HIGHEST, empty); | |
| 195 } | |
| 196 | |
| 197 // Confirm dependencies correct after updates with three streams. | |
| 198 TEST_F(HttpPriorityDependencyTest, UpdateThreeStreams) { | |
| 199 const SpdyStreamId first_id = GetId(); | |
| 200 const SpdyStreamId second_id = GetId(); | |
| 201 const SpdyStreamId third_id = GetId(); | |
| 202 | |
| 203 TestStreamCreation(first_id, HIGHEST, 0); | |
| 204 TestStreamCreation(second_id, MEDIUM, first_id); | |
| 205 TestStreamCreation(third_id, LOWEST, second_id); | |
| 206 | |
| 207 std::vector<ExpectedDependencyUpdate> empty; | |
| 208 | |
| 209 // no-op: still at top. | |
| 210 TestStreamUpdate(first_id, HIGHEST, empty); | |
| 211 | |
| 212 // no-op: still below first. | |
| 213 TestStreamUpdate(second_id, MEDIUM, empty); | |
| 214 | |
| 215 // no-op: still below second. | |
| 216 TestStreamUpdate(third_id, LOWEST, empty); | |
| 217 | |
| 218 // second moves to top, first moves below second. | |
| 219 TestStreamUpdate(first_id, MEDIUM, {{second_id, 0}, {first_id, second_id}}); | |
| 220 | |
| 221 // third moves to top. | |
| 222 TestStreamUpdate(third_id, HIGHEST, {{third_id, 0}}); | |
| 223 | |
| 224 // third moves to bottom. | |
| 225 TestStreamUpdate(third_id, LOWEST, {{second_id, 0}, {third_id, first_id}}); | |
| 226 | |
| 227 // first moves to top. | |
| 228 TestStreamUpdate(first_id, HIGHEST, {{third_id, second_id}, {first_id, 0}}); | |
| 229 } | |
| 230 | |
| 231 // A more complex example parallel to a simple web page with pushed responses. | |
| 232 TEST_F(HttpPriorityDependencyTest, UpdateComplex) { | |
| 233 const SpdyStreamId first_id = GetId(); | |
| 234 const SpdyStreamId second_id = GetId(); // pushed | |
| 235 const SpdyStreamId third_id = GetId(); // pushed | |
| 236 const SpdyStreamId fourth_id = GetId(); | |
| 237 const SpdyStreamId fifth_id = GetId(); | |
| 238 const SpdyStreamId sixth_id = GetId(); | |
| 239 const SpdyStreamId seventh_id = GetId(); | |
| 240 | |
| 241 TestStreamCreation(first_id, HIGHEST, 0u); | |
| 242 TestStreamCreation(second_id, LOWEST, first_id); | |
| 243 TestStreamCreation(third_id, LOWEST, second_id); | |
| 244 TestStreamCreation(fourth_id, HIGHEST, first_id); | |
| 245 TestStreamCreation(fifth_id, MEDIUM, fourth_id); | |
| 246 TestStreamCreation(sixth_id, MEDIUM, fifth_id); | |
| 247 TestStreamCreation(seventh_id, LOW, sixth_id); | |
| 248 | |
| 249 // second matches a HIGHEST priority response. | |
| 250 // 3 moves under 7 | |
| 251 // 2 moves under 4 | |
| 252 TestStreamUpdate(second_id, HIGHEST, | |
| 253 {{third_id, seventh_id}, {second_id, fourth_id}}); | |
| 254 | |
| 255 // third matches a MEDIUM priority response. | |
| 256 // 3 moves under 6 | |
| 257 TestStreamUpdate(third_id, MEDIUM, {{third_id, sixth_id}}); | |
| 258 } | |
| 259 | |
| 260 } // namespace net | |
| OLD | NEW |