Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(402)

Side by Side Diff: net/spdy/http2_write_scheduler_test.cc

Issue 1660283002: Rename and modify SpdyPriorityTree. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase on https://crrev.com/1668773003. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/http2_write_scheduler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/http2_write_scheduler.h" 5 #include "net/spdy/http2_write_scheduler.h"
6 6
7 #include "net/test/gtest_util.h"
7 #include "testing/gmock/include/gmock/gmock.h" 8 #include "testing/gmock/include/gmock/gmock.h"
8 #include "testing/gtest/include/gtest/gtest.h" 9 #include "testing/gtest/include/gtest/gtest.h"
9 10
10 namespace net { 11 namespace net {
11 12
13 using ::testing::AssertionFailure;
14 using ::testing::AssertionResult;
15 using ::testing::AssertionSuccess;
12 using ::testing::ElementsAre; 16 using ::testing::ElementsAre;
13 using ::testing::IsEmpty; 17 using ::testing::IsEmpty;
14 using ::testing::UnorderedElementsAre; 18 using ::testing::UnorderedElementsAre;
15 19
16 namespace test { 20 namespace test {
17 21
18 template <typename NodeId> 22 template <typename StreamIdType>
19 class SpdyPriorityTreePeer { 23 class Http2PriorityWriteSchedulerPeer {
20 public: 24 public:
21 explicit SpdyPriorityTreePeer(SpdyPriorityTree<NodeId>* tree) : tree_(tree) {} 25 explicit Http2PriorityWriteSchedulerPeer(
26 Http2PriorityWriteScheduler<StreamIdType>* scheduler)
27 : scheduler_(scheduler) {}
22 28
23 void PropagateNodeState(NodeId node_id) { 29 int TotalChildWeights(StreamIdType stream_id) const {
24 auto node = tree_->FindNode(node_id); 30 return scheduler_->FindStream(stream_id)->total_child_weights;
25 tree_->PropagateNodeState(node);
26 }
27
28 int TotalChildWeights(NodeId node_id) const {
29 return tree_->FindNode(node_id)->total_child_weights;
30 }
31
32 int TotalWriteableChildWeights(NodeId node_id) const {
33 return tree_->FindNode(node_id)->total_writeable_child_weights;
34 } 31 }
35 32
36 bool ValidateInvariants() const { 33 bool ValidateInvariants() const {
37 return tree_->ValidateInvariantsForTests(); 34 return scheduler_->ValidateInvariantsForTests();
38 } 35 }
39 36
40 private: 37 private:
41 SpdyPriorityTree<NodeId>* tree_; 38 Http2PriorityWriteScheduler<StreamIdType>* scheduler_;
42 }; 39 };
43 40
44 class SpdyPriorityTreeTest : public ::testing::Test { 41 class Http2PriorityWriteSchedulerTest : public ::testing::Test {
45 protected: 42 protected:
46 typedef uint32_t SpdyStreamId; 43 using SpdyStreamId = uint32_t;
47 typedef std::pair<SpdyStreamId, float> PriorityNode;
48 typedef std::vector<PriorityNode> PriorityList;
49 44
50 SpdyPriorityTreeTest() : peer(&tree) {} 45 Http2PriorityWriteSchedulerTest() : peer_(&scheduler_) {}
51 46
52 SpdyPriorityTree<SpdyStreamId> tree; 47 Http2PriorityWriteScheduler<SpdyStreamId> scheduler_;
53 SpdyPriorityTreePeer<SpdyStreamId> peer; 48 Http2PriorityWriteSchedulerPeer<SpdyStreamId> peer_;
54 }; 49 };
55 50
56 TEST_F(SpdyPriorityTreeTest, AddAndRemoveNodes) { 51 TEST_F(Http2PriorityWriteSchedulerTest, RegisterAndUnregisterStreams) {
57 EXPECT_EQ(1, tree.num_nodes()); 52 EXPECT_EQ(1, scheduler_.num_streams());
58 EXPECT_TRUE(tree.NodeExists(0)); 53 EXPECT_TRUE(scheduler_.StreamRegistered(0));
59 EXPECT_FALSE(tree.NodeExists(1)); 54 EXPECT_FALSE(scheduler_.StreamRegistered(1));
60 55
61 EXPECT_TRUE(tree.AddNode(1, 0, 100, false)); 56 scheduler_.RegisterStream(1, 0, 100, false);
62 EXPECT_EQ(2, tree.num_nodes()); 57 EXPECT_EQ(2, scheduler_.num_streams());
63 ASSERT_TRUE(tree.NodeExists(1)); 58 ASSERT_TRUE(scheduler_.StreamRegistered(1));
64 EXPECT_EQ(100, tree.GetWeight(1)); 59 EXPECT_EQ(100, scheduler_.GetStreamWeight(1));
65 EXPECT_FALSE(tree.NodeExists(5)); 60 EXPECT_FALSE(scheduler_.StreamRegistered(5));
66 EXPECT_THAT(tree.GetChildren(0), ElementsAre(1)); 61 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
67 62
68 EXPECT_TRUE(tree.AddNode(5, 0, 50, false)); 63 scheduler_.RegisterStream(5, 0, 50, false);
69 // Should not be able to add a node with an id that already exists. 64 // Should not be able to add a stream with an id that already exists.
70 EXPECT_FALSE(tree.AddNode(5, 1, 50, false)); 65 EXPECT_DFATAL(scheduler_.RegisterStream(5, 1, 50, false),
71 EXPECT_EQ(3, tree.num_nodes()); 66 "Stream 5 already registered");
72 EXPECT_TRUE(tree.NodeExists(1)); 67 EXPECT_EQ(3, scheduler_.num_streams());
73 ASSERT_TRUE(tree.NodeExists(5)); 68 EXPECT_TRUE(scheduler_.StreamRegistered(1));
74 EXPECT_EQ(50, tree.GetWeight(5)); 69 ASSERT_TRUE(scheduler_.StreamRegistered(5));
75 EXPECT_FALSE(tree.NodeExists(13)); 70 EXPECT_EQ(50, scheduler_.GetStreamWeight(5));
71 EXPECT_FALSE(scheduler_.StreamRegistered(13));
76 72
77 EXPECT_TRUE(tree.AddNode(13, 5, 130, true)); 73 scheduler_.RegisterStream(13, 5, 130, true);
78 EXPECT_EQ(4, tree.num_nodes()); 74 EXPECT_EQ(4, scheduler_.num_streams());
79 EXPECT_TRUE(tree.NodeExists(1)); 75 EXPECT_TRUE(scheduler_.StreamRegistered(1));
80 EXPECT_TRUE(tree.NodeExists(5)); 76 EXPECT_TRUE(scheduler_.StreamRegistered(5));
81 ASSERT_TRUE(tree.NodeExists(13)); 77 ASSERT_TRUE(scheduler_.StreamRegistered(13));
82 EXPECT_EQ(130, tree.GetWeight(13)); 78 EXPECT_EQ(130, scheduler_.GetStreamWeight(13));
83 EXPECT_EQ(5u, tree.GetParent(13)); 79 EXPECT_EQ(5u, scheduler_.GetStreamParent(13));
84 80
85 EXPECT_TRUE(tree.RemoveNode(5)); 81 scheduler_.UnregisterStream(5);
86 // Cannot remove a node that has already been removed. 82 // Cannot remove a stream that has already been removed.
87 EXPECT_FALSE(tree.RemoveNode(5)); 83 EXPECT_DFATAL(scheduler_.UnregisterStream(5), "Stream 5 not registered");
88 EXPECT_EQ(3, tree.num_nodes()); 84 EXPECT_EQ(3, scheduler_.num_streams());
89 EXPECT_TRUE(tree.NodeExists(1)); 85 EXPECT_TRUE(scheduler_.StreamRegistered(1));
90 EXPECT_FALSE(tree.NodeExists(5)); 86 EXPECT_FALSE(scheduler_.StreamRegistered(5));
91 EXPECT_TRUE(tree.NodeExists(13)); 87 EXPECT_TRUE(scheduler_.StreamRegistered(13));
92 EXPECT_EQ(0u, tree.GetParent(13)); 88 EXPECT_EQ(kHttp2RootStreamId, scheduler_.GetStreamParent(13));
93 89
94 // The parent node 19 doesn't exist, so this should fail: 90 // The parent stream 19 doesn't exist, so this should use 0 as parent stream:
95 EXPECT_FALSE(tree.AddNode(7, 19, 70, false)); 91 EXPECT_DFATAL(scheduler_.RegisterStream(7, 19, 70, false),
96 // This should succeed, creating node 7: 92 "Parent stream 19 not registered");
97 EXPECT_TRUE(tree.AddNode(7, 13, 70, false)); 93 EXPECT_TRUE(scheduler_.StreamRegistered(7));
98 // Now node 7 already exists, so this should fail: 94 EXPECT_EQ(0u, scheduler_.GetStreamParent(7));
99 EXPECT_FALSE(tree.AddNode(7, 1, 70, false)); 95 // Now stream 7 already exists, so this should fail:
100 // Try adding a second child to node 13: 96 EXPECT_DFATAL(scheduler_.RegisterStream(7, 1, 70, false),
101 EXPECT_TRUE(tree.AddNode(17, 13, 170, false)); 97 "Stream 7 already registered");
98 // Try adding a second child to stream 13:
99 scheduler_.RegisterStream(17, 13, 170, false);
102 100
103 // TODO(birenroy): Add a separate test that verifies weight invariants when 101 // TODO(birenroy): Add a separate test that verifies weight invariants when
104 // SetWeight is called. 102 // SetStreamWeight is called.
105 EXPECT_TRUE(tree.SetWeight(17, 150)); 103 scheduler_.SetStreamWeight(17, 150);
106 EXPECT_EQ(150, tree.GetWeight(17)); 104 EXPECT_EQ(150, scheduler_.GetStreamWeight(17));
107 105
108 ASSERT_TRUE(peer.ValidateInvariants()); 106 ASSERT_TRUE(peer_.ValidateInvariants());
107 }
108
109 TEST_F(Http2PriorityWriteSchedulerTest, GetStreamWeight) {
110 EXPECT_DFATAL(EXPECT_EQ(kHttp2MinStreamWeight, scheduler_.GetStreamWeight(3)),
111 "Stream 3 not registered");
112 scheduler_.RegisterStream(3, 0, 130, true);
113 EXPECT_EQ(130, scheduler_.GetStreamWeight(3));
114 scheduler_.SetStreamWeight(3, 50);
115 EXPECT_EQ(50, scheduler_.GetStreamWeight(3));
116 scheduler_.UnregisterStream(3);
117 EXPECT_DFATAL(EXPECT_EQ(kHttp2MinStreamWeight, scheduler_.GetStreamWeight(3)),
118 "Stream 3 not registered");
119 }
120
121 TEST_F(Http2PriorityWriteSchedulerTest, GetStreamParent) {
122 EXPECT_DFATAL(EXPECT_EQ(kHttp2RootStreamId, scheduler_.GetStreamParent(3)),
123 "Stream 3 not registered");
124 scheduler_.RegisterStream(2, 0, 20, false);
125 scheduler_.RegisterStream(3, 2, 30, false);
126 EXPECT_EQ(2u, scheduler_.GetStreamParent(3));
127 scheduler_.UnregisterStream(3);
128 EXPECT_DFATAL(EXPECT_EQ(kHttp2RootStreamId, scheduler_.GetStreamParent(3)),
129 "Stream 3 not registered");
130 }
131
132 TEST_F(Http2PriorityWriteSchedulerTest, GetStreamChildren) {
133 EXPECT_DFATAL(EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty()),
134 "Stream 7 not registered");
135 scheduler_.RegisterStream(7, 0, 70, false);
136 EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty());
137 scheduler_.RegisterStream(9, 7, 90, false);
138 scheduler_.RegisterStream(15, 7, 150, false);
139 EXPECT_THAT(scheduler_.GetStreamChildren(7), UnorderedElementsAre(9, 15));
140 scheduler_.UnregisterStream(7);
141 EXPECT_DFATAL(EXPECT_THAT(scheduler_.GetStreamChildren(7), IsEmpty()),
142 "Stream 7 not registered");
143 }
144
145 TEST_F(Http2PriorityWriteSchedulerTest, SetStreamWeight) {
146 EXPECT_DFATAL(scheduler_.SetStreamWeight(0, 10),
147 "Cannot set weight of root stream");
148 EXPECT_DFATAL(scheduler_.SetStreamWeight(3, 10), "Stream 3 not registered");
149 scheduler_.RegisterStream(3, 0, 10, false);
150 scheduler_.SetStreamWeight(3, 20);
151 EXPECT_EQ(20, scheduler_.GetStreamWeight(3));
152 EXPECT_DFATAL(scheduler_.SetStreamWeight(3, 500), "Invalid weight: 500");
153 EXPECT_EQ(kHttp2MaxStreamWeight, scheduler_.GetStreamWeight(3));
154 EXPECT_DFATAL(scheduler_.SetStreamWeight(3, 0), "Invalid weight: 0");
155 EXPECT_EQ(kHttp2MinStreamWeight, scheduler_.GetStreamWeight(3));
156 scheduler_.UnregisterStream(3);
157 EXPECT_DFATAL(scheduler_.SetStreamWeight(3, 10), "Stream 3 not registered");
109 } 158 }
110 159
111 // Basic case of reparenting a subtree. 160 // Basic case of reparenting a subtree.
112 TEST_F(SpdyPriorityTreeTest, SetParentBasicNonExclusive) { 161 TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentBasicNonExclusive) {
113 /* Tree: 162 /* Tree:
114 0 163 0
115 / \ 164 / \
116 1 2 165 1 2
117 / \ 166 / \
118 3 4 167 3 4
119 */ 168 */
120 tree.AddNode(1, 0, 100, false); 169 scheduler_.RegisterStream(1, 0, 100, false);
121 tree.AddNode(2, 0, 100, false); 170 scheduler_.RegisterStream(2, 0, 100, false);
122 tree.AddNode(3, 1, 100, false); 171 scheduler_.RegisterStream(3, 1, 100, false);
123 tree.AddNode(4, 1, 100, false); 172 scheduler_.RegisterStream(4, 1, 100, false);
124 EXPECT_TRUE(tree.SetParent(1, 2, false)); 173 scheduler_.SetStreamParent(1, 2, false);
125 EXPECT_THAT(tree.GetChildren(0), ElementsAre(2)); 174 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(2));
126 EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(3, 4)); 175 EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(3, 4));
127 EXPECT_THAT(tree.GetChildren(2), ElementsAre(1)); 176 EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(1));
128 EXPECT_THAT(tree.GetChildren(3), IsEmpty()); 177 EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
129 EXPECT_THAT(tree.GetChildren(4), IsEmpty()); 178 EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
130 ASSERT_TRUE(peer.ValidateInvariants()); 179 ASSERT_TRUE(peer_.ValidateInvariants());
131 } 180 }
132 181
133 // Basic case of reparenting a subtree. Result here is the same as the 182 // Basic case of reparenting a subtree. Result here is the same as the
134 // non-exclusive case. 183 // non-exclusive case.
135 TEST_F(SpdyPriorityTreeTest, SetParentBasicExclusive) { 184 TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentBasicExclusive) {
136 /* Tree: 185 /* Tree:
137 0 186 0
138 / \ 187 / \
139 1 2 188 1 2
140 / \ 189 / \
141 3 4 190 3 4
142 */ 191 */
143 tree.AddNode(1, 0, 100, false); 192 scheduler_.RegisterStream(1, 0, 100, false);
144 tree.AddNode(2, 0, 100, false); 193 scheduler_.RegisterStream(2, 0, 100, false);
145 tree.AddNode(3, 1, 100, false); 194 scheduler_.RegisterStream(3, 1, 100, false);
146 tree.AddNode(4, 1, 100, false); 195 scheduler_.RegisterStream(4, 1, 100, false);
147 EXPECT_TRUE(tree.SetParent(1, 2, true)); 196 scheduler_.SetStreamParent(1, 2, true);
148 EXPECT_THAT(tree.GetChildren(0), ElementsAre(2)); 197 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(2));
149 EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(3, 4)); 198 EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(3, 4));
150 EXPECT_THAT(tree.GetChildren(2), ElementsAre(1)); 199 EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(1));
151 EXPECT_THAT(tree.GetChildren(3), IsEmpty()); 200 EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
152 EXPECT_THAT(tree.GetChildren(4), IsEmpty()); 201 EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
153 ASSERT_TRUE(peer.ValidateInvariants()); 202 ASSERT_TRUE(peer_.ValidateInvariants());
154 } 203 }
155 204
156 // We can't set the parent of a nonexistent node, or set the parent to a 205 // We can't set the parent of a nonexistent stream, or set the parent to a
157 // nonexistent node. 206 // nonexistent stream.
158 TEST_F(SpdyPriorityTreeTest, SetParentNonexistent) { 207 TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentNonexistent) {
159 tree.AddNode(1, 0, 100, false); 208 scheduler_.RegisterStream(1, 0, 100, false);
160 tree.AddNode(2, 0, 100, false); 209 scheduler_.RegisterStream(2, 0, 100, false);
161 bool test_bool_values[] = {true, false}; 210 for (bool exclusive : {true, false}) {
162 for (bool exclusive : test_bool_values) { 211 EXPECT_DFATAL(scheduler_.SetStreamParent(1, 3, exclusive),
163 EXPECT_FALSE(tree.SetParent(1, 3, exclusive)); 212 "Parent stream 3 not registered");
164 EXPECT_FALSE(tree.SetParent(4, 2, exclusive)); 213 EXPECT_DFATAL(scheduler_.SetStreamParent(4, 2, exclusive),
165 EXPECT_FALSE(tree.SetParent(3, 4, exclusive)); 214 "Stream 4 not registered");
166 EXPECT_THAT(tree.GetChildren(0), UnorderedElementsAre(1, 2)); 215 EXPECT_DFATAL(scheduler_.SetStreamParent(3, 4, exclusive),
167 EXPECT_THAT(tree.GetChildren(1), IsEmpty()); 216 "Stream 3 not registered");
168 EXPECT_THAT(tree.GetChildren(2), IsEmpty()); 217 EXPECT_THAT(scheduler_.GetStreamChildren(0), UnorderedElementsAre(1, 2));
218 EXPECT_THAT(scheduler_.GetStreamChildren(1), IsEmpty());
219 EXPECT_THAT(scheduler_.GetStreamChildren(2), IsEmpty());
169 } 220 }
170 ASSERT_TRUE(peer.ValidateInvariants()); 221 ASSERT_TRUE(peer_.ValidateInvariants());
171 } 222 }
172 223
173 // We should be able to add multiple children to nodes. 224 // We should be able to add multiple children to streams.
174 TEST_F(SpdyPriorityTreeTest, SetParentMultipleChildrenNonExclusive) { 225 TEST_F(Http2PriorityWriteSchedulerTest,
226 SetStreamParentMultipleChildrenNonExclusive) {
175 /* Tree: 227 /* Tree:
176 0 228 0
177 / \ 229 / \
178 1 2 230 1 2
179 / \ \ 231 / \ \
180 3 4 5 232 3 4 5
181 */ 233 */
182 tree.AddNode(1, 0, 100, false); 234 scheduler_.RegisterStream(1, 0, 100, false);
183 tree.AddNode(2, 0, 100, false); 235 scheduler_.RegisterStream(2, 0, 100, false);
184 tree.AddNode(3, 1, 100, false); 236 scheduler_.RegisterStream(3, 1, 100, false);
185 tree.AddNode(4, 1, 100, false); 237 scheduler_.RegisterStream(4, 1, 100, false);
186 tree.AddNode(5, 2, 100, false); 238 scheduler_.RegisterStream(5, 2, 100, false);
187 EXPECT_TRUE(tree.SetParent(2, 1, false)); 239 scheduler_.SetStreamParent(2, 1, false);
188 EXPECT_THAT(tree.GetChildren(0), ElementsAre(1)); 240 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
189 EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(2, 3, 4)); 241 EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(2, 3, 4));
190 EXPECT_THAT(tree.GetChildren(2), ElementsAre(5)); 242 EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(5));
191 EXPECT_THAT(tree.GetChildren(3), IsEmpty()); 243 EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
192 EXPECT_THAT(tree.GetChildren(4), IsEmpty()); 244 EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
193 EXPECT_THAT(tree.GetChildren(5), IsEmpty()); 245 EXPECT_THAT(scheduler_.GetStreamChildren(5), IsEmpty());
194 ASSERT_TRUE(peer.ValidateInvariants()); 246 ASSERT_TRUE(peer_.ValidateInvariants());
195 } 247 }
196 248
197 TEST_F(SpdyPriorityTreeTest, SetParentMultipleChildrenExclusive) { 249 TEST_F(Http2PriorityWriteSchedulerTest,
250 SetStreamParentMultipleChildrenExclusive) {
198 /* Tree: 251 /* Tree:
199 0 252 0
200 / \ 253 / \
201 1 2 254 1 2
202 / \ \ 255 / \ \
203 3 4 5 256 3 4 5
204 */ 257 */
205 tree.AddNode(1, 0, 100, false); 258 scheduler_.RegisterStream(1, 0, 100, false);
206 tree.AddNode(2, 0, 100, false); 259 scheduler_.RegisterStream(2, 0, 100, false);
207 tree.AddNode(3, 1, 100, false); 260 scheduler_.RegisterStream(3, 1, 100, false);
208 tree.AddNode(4, 1, 100, false); 261 scheduler_.RegisterStream(4, 1, 100, false);
209 tree.AddNode(5, 2, 100, false); 262 scheduler_.RegisterStream(5, 2, 100, false);
210 EXPECT_TRUE(tree.SetParent(2, 1, true)); 263 scheduler_.SetStreamParent(2, 1, true);
211 EXPECT_THAT(tree.GetChildren(0), ElementsAre(1)); 264 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
212 EXPECT_THAT(tree.GetChildren(1), ElementsAre(2)); 265 EXPECT_THAT(scheduler_.GetStreamChildren(1), ElementsAre(2));
213 EXPECT_THAT(tree.GetChildren(2), UnorderedElementsAre(3, 4, 5)); 266 EXPECT_THAT(scheduler_.GetStreamChildren(2), UnorderedElementsAre(3, 4, 5));
214 EXPECT_THAT(tree.GetChildren(3), IsEmpty()); 267 EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
215 EXPECT_THAT(tree.GetChildren(4), IsEmpty()); 268 EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
216 EXPECT_THAT(tree.GetChildren(5), IsEmpty()); 269 EXPECT_THAT(scheduler_.GetStreamChildren(5), IsEmpty());
217 ASSERT_TRUE(peer.ValidateInvariants()); 270 ASSERT_TRUE(peer_.ValidateInvariants());
218 } 271 }
219 272
220 TEST_F(SpdyPriorityTreeTest, SetParentToChildNonExclusive) { 273 TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentToChildNonExclusive) {
221 /* Tree: 274 /* Tree:
222 0 275 0
223 | 276 |
224 1 277 1
225 / \ 278 / \
226 2 3 279 2 3
227 | 280 |
228 4 281 4
229 */ 282 */
230 tree.AddNode(1, 0, 100, false); 283 scheduler_.RegisterStream(1, 0, 100, false);
231 tree.AddNode(2, 1, 100, false); 284 scheduler_.RegisterStream(2, 1, 100, false);
232 tree.AddNode(3, 1, 100, false); 285 scheduler_.RegisterStream(3, 1, 100, false);
233 tree.AddNode(4, 2, 100, false); 286 scheduler_.RegisterStream(4, 2, 100, false);
234 EXPECT_TRUE(tree.SetParent(1, 2, false)); 287 scheduler_.SetStreamParent(1, 2, false);
235 EXPECT_THAT(tree.GetChildren(0), ElementsAre(2)); 288 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(2));
236 EXPECT_THAT(tree.GetChildren(1), ElementsAre(3)); 289 EXPECT_THAT(scheduler_.GetStreamChildren(1), ElementsAre(3));
237 EXPECT_THAT(tree.GetChildren(2), UnorderedElementsAre(1, 4)); 290 EXPECT_THAT(scheduler_.GetStreamChildren(2), UnorderedElementsAre(1, 4));
238 EXPECT_THAT(tree.GetChildren(3), IsEmpty()); 291 EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
239 EXPECT_THAT(tree.GetChildren(4), IsEmpty()); 292 EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
240 ASSERT_TRUE(peer.ValidateInvariants()); 293 ASSERT_TRUE(peer_.ValidateInvariants());
241 } 294 }
242 295
243 TEST_F(SpdyPriorityTreeTest, SetParentToChildExclusive) { 296 TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentToChildExclusive) {
244 /* Tree: 297 /* Tree:
245 0 298 0
246 | 299 |
247 1 300 1
248 / \ 301 / \
249 2 3 302 2 3
250 | 303 |
251 4 304 4
252 */ 305 */
253 tree.AddNode(1, 0, 100, false); 306 scheduler_.RegisterStream(1, 0, 100, false);
254 tree.AddNode(2, 1, 100, false); 307 scheduler_.RegisterStream(2, 1, 100, false);
255 tree.AddNode(3, 1, 100, false); 308 scheduler_.RegisterStream(3, 1, 100, false);
256 tree.AddNode(4, 2, 100, false); 309 scheduler_.RegisterStream(4, 2, 100, false);
257 EXPECT_TRUE(tree.SetParent(1, 2, true)); 310 scheduler_.SetStreamParent(1, 2, true);
258 EXPECT_THAT(tree.GetChildren(0), ElementsAre(2)); 311 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(2));
259 EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(3, 4)); 312 EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(3, 4));
260 EXPECT_THAT(tree.GetChildren(2), ElementsAre(1)); 313 EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(1));
261 EXPECT_THAT(tree.GetChildren(3), IsEmpty()); 314 EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
262 EXPECT_THAT(tree.GetChildren(4), IsEmpty()); 315 EXPECT_THAT(scheduler_.GetStreamChildren(4), IsEmpty());
263 ASSERT_TRUE(peer.ValidateInvariants()); 316 ASSERT_TRUE(peer_.ValidateInvariants());
264 } 317 }
265 318
266 TEST_F(SpdyPriorityTreeTest, SetParentToGrandchildNonExclusive) { 319 TEST_F(Http2PriorityWriteSchedulerTest,
320 SetStreamParentToGrandchildNonExclusive) {
267 /* Tree: 321 /* Tree:
268 0 322 0
269 | 323 |
270 1 324 1
271 / \ 325 / \
272 2 3 326 2 3
273 / \ 327 / \
274 4 5 328 4 5
275 | 329 |
276 6 330 6
277 */ 331 */
278 tree.AddNode(1, 0, 100, false); 332 scheduler_.RegisterStream(1, 0, 100, false);
279 tree.AddNode(2, 1, 100, false); 333 scheduler_.RegisterStream(2, 1, 100, false);
280 tree.AddNode(3, 1, 100, false); 334 scheduler_.RegisterStream(3, 1, 100, false);
281 tree.AddNode(4, 2, 100, false); 335 scheduler_.RegisterStream(4, 2, 100, false);
282 tree.AddNode(5, 2, 100, false); 336 scheduler_.RegisterStream(5, 2, 100, false);
283 tree.AddNode(6, 4, 100, false); 337 scheduler_.RegisterStream(6, 4, 100, false);
284 EXPECT_TRUE(tree.SetParent(1, 4, false)); 338 scheduler_.SetStreamParent(1, 4, false);
285 EXPECT_THAT(tree.GetChildren(0), ElementsAre(4)); 339 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(4));
286 EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(2, 3)); 340 EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(2, 3));
287 EXPECT_THAT(tree.GetChildren(2), ElementsAre(5)); 341 EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(5));
288 EXPECT_THAT(tree.GetChildren(3), IsEmpty()); 342 EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
289 EXPECT_THAT(tree.GetChildren(4), UnorderedElementsAre(1, 6)); 343 EXPECT_THAT(scheduler_.GetStreamChildren(4), UnorderedElementsAre(1, 6));
290 EXPECT_THAT(tree.GetChildren(5), IsEmpty()); 344 EXPECT_THAT(scheduler_.GetStreamChildren(5), IsEmpty());
291 EXPECT_THAT(tree.GetChildren(6), IsEmpty()); 345 EXPECT_THAT(scheduler_.GetStreamChildren(6), IsEmpty());
292 ASSERT_TRUE(peer.ValidateInvariants()); 346 ASSERT_TRUE(peer_.ValidateInvariants());
293 } 347 }
294 348
295 TEST_F(SpdyPriorityTreeTest, SetParentToGrandchildExclusive) { 349 TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentToGrandchildExclusive) {
296 /* Tree: 350 /* Tree:
297 0 351 0
298 | 352 |
299 1 353 1
300 / \ 354 / \
301 2 3 355 2 3
302 / \ 356 / \
303 4 5 357 4 5
304 | 358 |
305 6 359 6
306 */ 360 */
307 tree.AddNode(1, 0, 100, false); 361 scheduler_.RegisterStream(1, 0, 100, false);
308 tree.AddNode(2, 1, 100, false); 362 scheduler_.RegisterStream(2, 1, 100, false);
309 tree.AddNode(3, 1, 100, false); 363 scheduler_.RegisterStream(3, 1, 100, false);
310 tree.AddNode(4, 2, 100, false); 364 scheduler_.RegisterStream(4, 2, 100, false);
311 tree.AddNode(5, 2, 100, false); 365 scheduler_.RegisterStream(5, 2, 100, false);
312 tree.AddNode(6, 4, 100, false); 366 scheduler_.RegisterStream(6, 4, 100, false);
313 EXPECT_TRUE(tree.SetParent(1, 4, true)); 367 scheduler_.SetStreamParent(1, 4, true);
314 EXPECT_THAT(tree.GetChildren(0), ElementsAre(4)); 368 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(4));
315 EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(2, 3, 6)); 369 EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(2, 3, 6));
316 EXPECT_THAT(tree.GetChildren(2), ElementsAre(5)); 370 EXPECT_THAT(scheduler_.GetStreamChildren(2), ElementsAre(5));
317 EXPECT_THAT(tree.GetChildren(3), IsEmpty()); 371 EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
318 EXPECT_THAT(tree.GetChildren(4), ElementsAre(1)); 372 EXPECT_THAT(scheduler_.GetStreamChildren(4), ElementsAre(1));
319 EXPECT_THAT(tree.GetChildren(5), IsEmpty()); 373 EXPECT_THAT(scheduler_.GetStreamChildren(5), IsEmpty());
320 EXPECT_THAT(tree.GetChildren(6), IsEmpty()); 374 EXPECT_THAT(scheduler_.GetStreamChildren(6), IsEmpty());
321 ASSERT_TRUE(peer.ValidateInvariants()); 375 ASSERT_TRUE(peer_.ValidateInvariants());
322 } 376 }
323 377
324 TEST_F(SpdyPriorityTreeTest, SetParentToParent) { 378 TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentToParent) {
325 tree.AddNode(1, 0, 100, false); 379 scheduler_.RegisterStream(1, 0, 100, false);
326 tree.AddNode(2, 1, 100, false); 380 scheduler_.RegisterStream(2, 1, 100, false);
327 tree.AddNode(3, 1, 100, false); 381 scheduler_.RegisterStream(3, 1, 100, false);
328 bool test_bool_values[] = {true, false}; 382 for (bool exclusive : {true, false}) {
329 for (bool exclusive : test_bool_values) { 383 scheduler_.SetStreamParent(2, 1, exclusive);
330 EXPECT_TRUE(tree.SetParent(2, 1, exclusive)); 384 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
331 EXPECT_THAT(tree.GetChildren(0), ElementsAre(1)); 385 EXPECT_THAT(scheduler_.GetStreamChildren(1), UnorderedElementsAre(2, 3));
332 EXPECT_THAT(tree.GetChildren(1), UnorderedElementsAre(2, 3)); 386 EXPECT_THAT(scheduler_.GetStreamChildren(2), IsEmpty());
333 EXPECT_THAT(tree.GetChildren(2), IsEmpty()); 387 EXPECT_THAT(scheduler_.GetStreamChildren(3), IsEmpty());
334 EXPECT_THAT(tree.GetChildren(3), IsEmpty());
335 } 388 }
336 ASSERT_TRUE(peer.ValidateInvariants()); 389 ASSERT_TRUE(peer_.ValidateInvariants());
337 } 390 }
338 391
339 TEST_F(SpdyPriorityTreeTest, SetParentToSelf) { 392 TEST_F(Http2PriorityWriteSchedulerTest, SetStreamParentToSelf) {
340 tree.AddNode(1, 0, 100, false); 393 scheduler_.RegisterStream(1, 0, 100, false);
341 EXPECT_FALSE(tree.SetParent(1, 1, false)); 394 EXPECT_DFATAL(scheduler_.SetStreamParent(1, 1, false),
342 EXPECT_FALSE(tree.SetParent(1, 1, true)); 395 "Cannot set stream to be its own parent");
343 EXPECT_THAT(tree.GetChildren(0), ElementsAre(1)); 396 EXPECT_DFATAL(scheduler_.SetStreamParent(1, 1, true),
344 EXPECT_THAT(tree.GetChildren(1), IsEmpty()); 397 "Cannot set stream to be its own parent");
345 ASSERT_TRUE(peer.ValidateInvariants()); 398 EXPECT_THAT(scheduler_.GetStreamChildren(0), ElementsAre(1));
399 EXPECT_THAT(scheduler_.GetStreamChildren(1), IsEmpty());
400 ASSERT_TRUE(peer_.ValidateInvariants());
346 } 401 }
347 402
348 TEST_F(SpdyPriorityTreeTest, BlockAndUnblock) { 403 TEST_F(Http2PriorityWriteSchedulerTest, StreamHasChild) {
404 scheduler_.RegisterStream(1, 0, 10, false);
405 scheduler_.RegisterStream(2, 1, 20, false);
406 scheduler_.RegisterStream(3, 1, 30, false);
407 EXPECT_DFATAL(EXPECT_FALSE(scheduler_.StreamHasChild(4, 1)),
408 "Parent stream 4 not registered");
409 EXPECT_DFATAL(EXPECT_FALSE(scheduler_.StreamHasChild(3, 7)),
410 "Child stream 7 not registered");
411 EXPECT_FALSE(scheduler_.StreamHasChild(3, 1));
412 EXPECT_TRUE(scheduler_.StreamHasChild(1, 3));
413 EXPECT_TRUE(scheduler_.StreamHasChild(1, 2));
414 ASSERT_TRUE(peer_.ValidateInvariants());
415 }
416
417 TEST_F(Http2PriorityWriteSchedulerTest, BlockAndUnblock) {
349 /* Create the tree. 418 /* Create the tree.
350 419
351 0 420 0
352 / | \ 421 / | \
353 / | \ 422 / | \
354 1 2 3 423 1 2 3
355 / \ \ \ 424 / \ \ \
356 4 5 6 7 425 4 5 6 7
357 /| / \ | |\ 426 /| / \ | |\
358 8 9 10 11 12 13 14 427 8 9 10 11 12 13 14
359 / \ 428 / \
360 15 16 429 15 16
361 430
362 */ 431 */
363 tree.AddNode(1, 0, 100, false); 432 scheduler_.RegisterStream(1, 0, 100, false);
364 tree.AddNode(2, 0, 100, false); 433 scheduler_.RegisterStream(2, 0, 100, false);
365 tree.AddNode(3, 0, 100, false); 434 scheduler_.RegisterStream(3, 0, 100, false);
366 tree.AddNode(4, 1, 100, false); 435 scheduler_.RegisterStream(4, 1, 100, false);
367 tree.AddNode(5, 1, 100, false); 436 scheduler_.RegisterStream(5, 1, 100, false);
368 tree.AddNode(8, 4, 100, false); 437 scheduler_.RegisterStream(8, 4, 100, false);
369 tree.AddNode(9, 4, 100, false); 438 scheduler_.RegisterStream(9, 4, 100, false);
370 tree.AddNode(10, 5, 100, false); 439 scheduler_.RegisterStream(10, 5, 100, false);
371 tree.AddNode(11, 5, 100, false); 440 scheduler_.RegisterStream(11, 5, 100, false);
372 tree.AddNode(15, 8, 100, false); 441 scheduler_.RegisterStream(15, 8, 100, false);
373 tree.AddNode(16, 8, 100, false); 442 scheduler_.RegisterStream(16, 8, 100, false);
374 tree.AddNode(12, 2, 100, false); 443 scheduler_.RegisterStream(12, 2, 100, false);
375 tree.AddNode(6, 2, 100, true); 444 scheduler_.RegisterStream(6, 2, 100, true);
376 tree.AddNode(7, 0, 100, false); 445 scheduler_.RegisterStream(7, 0, 100, false);
377 tree.AddNode(13, 7, 100, true); 446 scheduler_.RegisterStream(13, 7, 100, true);
378 tree.AddNode(14, 7, 100, false); 447 scheduler_.RegisterStream(14, 7, 100, false);
379 tree.SetParent(7, 3, false); 448 scheduler_.SetStreamParent(7, 3, false);
380 EXPECT_EQ(0u, tree.GetParent(1)); 449 EXPECT_EQ(0u, scheduler_.GetStreamParent(1));
381 EXPECT_EQ(0u, tree.GetParent(2)); 450 EXPECT_EQ(0u, scheduler_.GetStreamParent(2));
382 EXPECT_EQ(0u, tree.GetParent(3)); 451 EXPECT_EQ(0u, scheduler_.GetStreamParent(3));
383 EXPECT_EQ(1u, tree.GetParent(4)); 452 EXPECT_EQ(1u, scheduler_.GetStreamParent(4));
384 EXPECT_EQ(1u, tree.GetParent(5)); 453 EXPECT_EQ(1u, scheduler_.GetStreamParent(5));
385 EXPECT_EQ(2u, tree.GetParent(6)); 454 EXPECT_EQ(2u, scheduler_.GetStreamParent(6));
386 EXPECT_EQ(3u, tree.GetParent(7)); 455 EXPECT_EQ(3u, scheduler_.GetStreamParent(7));
387 EXPECT_EQ(4u, tree.GetParent(8)); 456 EXPECT_EQ(4u, scheduler_.GetStreamParent(8));
388 EXPECT_EQ(4u, tree.GetParent(9)); 457 EXPECT_EQ(4u, scheduler_.GetStreamParent(9));
389 EXPECT_EQ(5u, tree.GetParent(10)); 458 EXPECT_EQ(5u, scheduler_.GetStreamParent(10));
390 EXPECT_EQ(5u, tree.GetParent(11)); 459 EXPECT_EQ(5u, scheduler_.GetStreamParent(11));
391 EXPECT_EQ(6u, tree.GetParent(12)); 460 EXPECT_EQ(6u, scheduler_.GetStreamParent(12));
392 EXPECT_EQ(7u, tree.GetParent(13)); 461 EXPECT_EQ(7u, scheduler_.GetStreamParent(13));
393 EXPECT_EQ(7u, tree.GetParent(14)); 462 EXPECT_EQ(7u, scheduler_.GetStreamParent(14));
394 EXPECT_EQ(8u, tree.GetParent(15)); 463 EXPECT_EQ(8u, scheduler_.GetStreamParent(15));
395 EXPECT_EQ(8u, tree.GetParent(16)); 464 EXPECT_EQ(8u, scheduler_.GetStreamParent(16));
396 ASSERT_TRUE(peer.ValidateInvariants()); 465 ASSERT_TRUE(peer_.ValidateInvariants());
397 466
398 EXPECT_EQ(peer.TotalChildWeights(0), 467 EXPECT_EQ(peer_.TotalChildWeights(0), scheduler_.GetStreamWeight(1) +
399 tree.GetWeight(1) + tree.GetWeight(2) + tree.GetWeight(3)); 468 scheduler_.GetStreamWeight(2) +
400 EXPECT_EQ(peer.TotalChildWeights(3), tree.GetWeight(7)); 469 scheduler_.GetStreamWeight(3));
401 EXPECT_EQ(peer.TotalChildWeights(7), tree.GetWeight(13) + tree.GetWeight(14)); 470 EXPECT_EQ(peer_.TotalChildWeights(3), scheduler_.GetStreamWeight(7));
402 EXPECT_EQ(peer.TotalChildWeights(13), 0); 471 EXPECT_EQ(peer_.TotalChildWeights(7),
403 EXPECT_EQ(peer.TotalChildWeights(14), 0); 472 scheduler_.GetStreamWeight(13) + scheduler_.GetStreamWeight(14));
473 EXPECT_EQ(peer_.TotalChildWeights(13), 0);
474 EXPECT_EQ(peer_.TotalChildWeights(14), 0);
404 475
405 // Set all nodes ready to write. 476 ASSERT_TRUE(peer_.ValidateInvariants());
406 EXPECT_TRUE(tree.SetReady(1, true));
407 EXPECT_TRUE(tree.SetReady(2, true));
408 EXPECT_TRUE(tree.SetReady(3, true));
409 EXPECT_TRUE(tree.SetReady(4, true));
410 EXPECT_TRUE(tree.SetReady(5, true));
411 EXPECT_TRUE(tree.SetReady(6, true));
412 EXPECT_TRUE(tree.SetReady(7, true));
413 EXPECT_TRUE(tree.SetReady(8, true));
414 EXPECT_TRUE(tree.SetReady(9, true));
415 EXPECT_TRUE(tree.SetReady(10, true));
416 EXPECT_TRUE(tree.SetReady(11, true));
417 EXPECT_TRUE(tree.SetReady(12, true));
418 EXPECT_TRUE(tree.SetReady(13, true));
419 EXPECT_TRUE(tree.SetReady(14, true));
420 EXPECT_TRUE(tree.SetReady(15, true));
421 EXPECT_TRUE(tree.SetReady(16, true));
422
423 // Number of readable child weights should not change because
424 // 7 has unblocked children.
425 tree.SetBlocked(7, true);
426 peer.PropagateNodeState(kRootNodeId);
427 EXPECT_EQ(peer.TotalChildWeights(3), peer.TotalWriteableChildWeights(3));
428
429 // Readable children for 7 should decrement.
430 // Number of readable child weights for 3 still should not change.
431 tree.SetBlocked(13, true);
432 peer.PropagateNodeState(kRootNodeId);
433 EXPECT_EQ(peer.TotalChildWeights(3), peer.TotalWriteableChildWeights(3));
434 EXPECT_EQ(tree.GetWeight(14), peer.TotalWriteableChildWeights(7));
435
436 // Once 14 becomes blocked, readable children for 7 and 3 should both be
437 // decremented. Total readable weights at the root should still be the same
438 // because 3 is still writeable.
439 tree.SetBlocked(14, true);
440 peer.PropagateNodeState(kRootNodeId);
441 EXPECT_EQ(0, peer.TotalWriteableChildWeights(3));
442 EXPECT_EQ(0, peer.TotalWriteableChildWeights(7));
443 EXPECT_EQ(peer.TotalChildWeights(0),
444 tree.GetWeight(1) + tree.GetWeight(2) + tree.GetWeight(3));
445
446 // And now the root should be decremented as well.
447 tree.SetBlocked(3, true);
448 peer.PropagateNodeState(kRootNodeId);
449 EXPECT_EQ(tree.GetWeight(1) + tree.GetWeight(2),
450 peer.TotalWriteableChildWeights(0));
451
452 // Unblocking 7 should propagate all the way up to the root.
453 tree.SetBlocked(7, false);
454 peer.PropagateNodeState(kRootNodeId);
455 EXPECT_EQ(peer.TotalWriteableChildWeights(0),
456 tree.GetWeight(1) + tree.GetWeight(2) + tree.GetWeight(3));
457 EXPECT_EQ(peer.TotalWriteableChildWeights(3), tree.GetWeight(7));
458 EXPECT_EQ(0, peer.TotalWriteableChildWeights(7));
459
460 // Ditto for reblocking 7.
461 tree.SetBlocked(7, true);
462 peer.PropagateNodeState(kRootNodeId);
463 EXPECT_EQ(peer.TotalWriteableChildWeights(0),
464 tree.GetWeight(1) + tree.GetWeight(2));
465 EXPECT_EQ(0, peer.TotalWriteableChildWeights(3));
466 EXPECT_EQ(0, peer.TotalWriteableChildWeights(7));
467 ASSERT_TRUE(peer.ValidateInvariants());
468 } 477 }
469 478
470 TEST_F(SpdyPriorityTreeTest, GetPriorityList) { 479 TEST_F(Http2PriorityWriteSchedulerTest, HasUsableStreams) {
471 PriorityList expected_list; 480 EXPECT_FALSE(scheduler_.HasUsableStreams());
472 PriorityList priority_list; 481 scheduler_.RegisterStream(1, 0, 10, false);
482 EXPECT_FALSE(scheduler_.HasUsableStreams());
483 scheduler_.MarkStreamReady(1, true);
484 EXPECT_TRUE(scheduler_.HasUsableStreams());
485 scheduler_.MarkStreamBlocked(1, true);
486 EXPECT_FALSE(scheduler_.HasUsableStreams());
487 scheduler_.MarkStreamReady(1, false);
488 EXPECT_FALSE(scheduler_.HasUsableStreams());
489 scheduler_.MarkStreamBlocked(1, false);
490 EXPECT_FALSE(scheduler_.HasUsableStreams());
491 scheduler_.MarkStreamReady(1, true);
492 EXPECT_TRUE(scheduler_.HasUsableStreams());
493 scheduler_.UnregisterStream(1);
494 EXPECT_FALSE(scheduler_.HasUsableStreams());
495 ASSERT_TRUE(peer_.ValidateInvariants());
496 }
473 497
498 TEST_F(Http2PriorityWriteSchedulerTest, CalculateRoundedWeights) {
474 /* Create the tree. 499 /* Create the tree.
475 500
476 0 501 0
477 /|\
478 1 2 3
479 /| |\
480 4 5 6 7
481 /
482 8
483
484 */
485 tree.AddNode(1, 0, 10, false);
486 tree.AddNode(2, 0, 20, false);
487 tree.AddNode(3, 0, 30, false);
488 tree.AddNode(4, 1, 10, false);
489 tree.AddNode(5, 1, 90, false);
490 tree.AddNode(6, 2, 10, false);
491 tree.AddNode(7, 2, 10, false);
492 tree.AddNode(8, 4, 256, false);
493
494 // Set all nodes ready to write.
495 EXPECT_TRUE(tree.SetReady(1, true));
496 EXPECT_TRUE(tree.SetReady(2, true));
497 EXPECT_TRUE(tree.SetReady(3, true));
498 EXPECT_TRUE(tree.SetReady(4, true));
499 EXPECT_TRUE(tree.SetReady(5, true));
500 EXPECT_TRUE(tree.SetReady(6, true));
501 EXPECT_TRUE(tree.SetReady(7, true));
502 EXPECT_TRUE(tree.SetReady(8, true));
503
504 expected_list.push_back(PriorityNode(3, 1.0/2.0));
505 expected_list.push_back(PriorityNode(2, 1.0/3.0));
506 expected_list.push_back(PriorityNode(1, 1.0/6.0));
507 priority_list = tree.GetPriorityList();
508 EXPECT_EQ(expected_list, priority_list);
509
510 // Check that the list updates as expected when a node gets blocked.
511 EXPECT_TRUE(tree.SetReady(1, false));
512 expected_list.clear();
513 expected_list.push_back(PriorityNode(3, 1.0/2.0));
514 expected_list.push_back(PriorityNode(2, 1.0/3.0));
515 expected_list.push_back(PriorityNode(5, 0.9*1.0/6.0));
516 expected_list.push_back(PriorityNode(4, 0.1*1.0/6.0));
517 priority_list = tree.GetPriorityList();
518 EXPECT_EQ(expected_list, priority_list);
519
520 // Block multiple levels of nodes.
521 EXPECT_TRUE(tree.SetReady(4, false));
522 EXPECT_TRUE(tree.SetReady(5, false));
523 expected_list.clear();
524 expected_list.push_back(PriorityNode(3, 1.0/2.0));
525 expected_list.push_back(PriorityNode(2, 1.0/3.0));
526 expected_list.push_back(PriorityNode(8, 1.0/6.0));
527 priority_list = tree.GetPriorityList();
528 EXPECT_EQ(expected_list, priority_list);
529
530 // Remove a node from the tree to make sure priorities
531 // get redistributed accordingly.
532 EXPECT_TRUE(tree.RemoveNode(1));
533 expected_list.clear();
534 expected_list.push_back(PriorityNode(3, 30.0/51.0));
535 expected_list.push_back(PriorityNode(2, 20.0/51.0));
536 expected_list.push_back(PriorityNode(8, 1.0/51.0));
537 priority_list = tree.GetPriorityList();
538 EXPECT_EQ(expected_list, priority_list);
539
540 // Block an entire subtree.
541 EXPECT_TRUE(tree.SetReady(8, false));
542 expected_list.clear();
543 expected_list.push_back(PriorityNode(3, 0.6));
544 expected_list.push_back(PriorityNode(2, 0.4));
545 priority_list = tree.GetPriorityList();
546 EXPECT_EQ(expected_list, priority_list);
547
548 // Unblock previously blocked nodes.
549 EXPECT_TRUE(tree.SetReady(4, true));
550 EXPECT_TRUE(tree.SetReady(5, true));
551 expected_list.clear();
552 expected_list.push_back(PriorityNode(3, 1.0/2.0));
553 expected_list.push_back(PriorityNode(2, 1.0/3.0));
554 expected_list.push_back(PriorityNode(5, 9.0/60.0));
555 expected_list.push_back(PriorityNode(4, 1.0/60.0));
556 priority_list = tree.GetPriorityList();
557 EXPECT_EQ(expected_list, priority_list);
558
559 // Blocked nodes in multiple subtrees.
560 EXPECT_TRUE(tree.SetReady(2, false));
561 EXPECT_TRUE(tree.SetReady(6, false));
562 EXPECT_TRUE(tree.SetReady(7, false));
563 expected_list.clear();
564 expected_list.push_back(PriorityNode(3, 3.0/4.0));
565 expected_list.push_back(PriorityNode(5, 9.0/40.0));
566 expected_list.push_back(PriorityNode(4, 1.0/40.0));
567 priority_list = tree.GetPriorityList();
568 EXPECT_EQ(expected_list, priority_list);
569 }
570
571 TEST_F(SpdyPriorityTreeTest, CalculateRoundedWeights) {
572 PriorityList expected_list;
573 PriorityList priority_list;
574
575 /* Create the tree.
576
577 0
578 / \ 502 / \
579 1 2 503 1 2
580 /| |\ |\ 504 /| |\ |\
581 8 3 4 5 6 7 505 8 3 4 5 6 7
582 */ 506 */
583 tree.AddNode(3, 0, 100, false); 507 scheduler_.RegisterStream(3, 0, 100, false);
584 tree.AddNode(4, 0, 100, false); 508 scheduler_.RegisterStream(4, 0, 100, false);
585 tree.AddNode(5, 0, 100, false); 509 scheduler_.RegisterStream(5, 0, 100, false);
586 tree.AddNode(1, 0, 10, true); 510 scheduler_.RegisterStream(1, 0, 10, true);
587 tree.AddNode(2, 0, 5, false); 511 scheduler_.RegisterStream(2, 0, 5, false);
588 tree.AddNode(6, 2, 1, false); 512 scheduler_.RegisterStream(6, 2, 1, false);
589 tree.AddNode(7, 2, 1, false); 513 scheduler_.RegisterStream(7, 2, 1, false);
590 tree.AddNode(8, 1, 1, false); 514 scheduler_.RegisterStream(8, 1, 1, false);
591 515
592 // Remove higher-level nodes. 516 // Remove higher-level streams.
593 tree.RemoveNode(1); 517 scheduler_.UnregisterStream(1);
594 tree.RemoveNode(2); 518 scheduler_.UnregisterStream(2);
595 519
596 // 3.3 rounded down = 3. 520 // 3.3 rounded down = 3.
597 EXPECT_EQ(3, tree.GetWeight(3)); 521 EXPECT_EQ(3, scheduler_.GetStreamWeight(3));
598 EXPECT_EQ(3, tree.GetWeight(4)); 522 EXPECT_EQ(3, scheduler_.GetStreamWeight(4));
599 EXPECT_EQ(3, tree.GetWeight(5)); 523 EXPECT_EQ(3, scheduler_.GetStreamWeight(5));
600 // 2.5 rounded up = 3. 524 // 2.5 rounded up = 3.
601 EXPECT_EQ(3, tree.GetWeight(6)); 525 EXPECT_EQ(3, scheduler_.GetStreamWeight(6));
602 EXPECT_EQ(3, tree.GetWeight(7)); 526 EXPECT_EQ(3, scheduler_.GetStreamWeight(7));
603 // 0 is not a valid weight, so round up to 1. 527 // 0 is not a valid weight, so round up to 1.
604 EXPECT_EQ(1, tree.GetWeight(8)); 528 EXPECT_EQ(1, scheduler_.GetStreamWeight(8));
529 ASSERT_TRUE(peer_.ValidateInvariants());
605 } 530 }
531
532 class PopNextUsableStreamTest : public Http2PriorityWriteSchedulerTest {
533 protected:
534 void SetUp() override {
535 /* Create the tree.
536
537 0
538 /|\
539 1 2 3
540 /| |\
541 4 5 6 7
542 /
543 8
544
545 */
546 scheduler_.RegisterStream(1, 0, 100, false);
547 scheduler_.RegisterStream(2, 0, 100, false);
548 scheduler_.RegisterStream(3, 0, 100, false);
549 scheduler_.RegisterStream(4, 1, 100, false);
550 scheduler_.RegisterStream(5, 1, 100, false);
551 scheduler_.RegisterStream(6, 2, 100, false);
552 scheduler_.RegisterStream(7, 2, 100, false);
553 scheduler_.RegisterStream(8, 4, 100, false);
554
555 // Set all nodes ready to write.
556 for (SpdyStreamId id = 1; id <= 8; ++id) {
557 scheduler_.MarkStreamReady(id, true);
558 }
559 }
560
561 AssertionResult PopNextReturnsCycle(
562 std::initializer_list<SpdyStreamId> stream_ids) {
563 int count = 0;
564 const int kNumCyclesToCheck = 2;
565 for (int i = 0; i < kNumCyclesToCheck; i++) {
566 for (SpdyStreamId expected_id : stream_ids) {
567 SpdyStreamId next_id = scheduler_.PopNextUsableStream();
568 scheduler_.MarkStreamReady(next_id, true);
569 if (next_id != expected_id) {
570 return AssertionFailure() << "Pick " << count << ": expected stream "
571 << expected_id << " instead of " << next_id;
572 }
573 if (!peer_.ValidateInvariants()) {
574 return AssertionFailure() << "ValidateInvariants failed";
575 }
576 ++count;
577 }
578 }
579 return AssertionSuccess();
580 }
581 };
582
583 // When all streams are schedulable, only top-level streams should be returned.
584 TEST_F(PopNextUsableStreamTest, NoneBlocked) {
585 EXPECT_TRUE(PopNextReturnsCycle({1, 2, 3}));
586 }
587
588 // When a parent stream is blocked, its children should be scheduled, if
589 // priorities allow.
590 TEST_F(PopNextUsableStreamTest, SingleStreamBlocked) {
591 scheduler_.MarkStreamReady(1, false);
592
593 // Round-robin only across 2 and 3, since children of 1 have lower priority.
594 EXPECT_TRUE(PopNextReturnsCycle({2, 3}));
595
596 // Make children of 1 have equal priority as 2 and 3, after which they should
597 // be returned as well.
598 scheduler_.SetStreamWeight(1, 200);
599 EXPECT_TRUE(PopNextReturnsCycle({4, 5, 2, 3}));
600 }
601
602 // Block multiple levels of streams.
603 TEST_F(PopNextUsableStreamTest, MultiLevelBlocked) {
604 for (SpdyStreamId stream_id : {1, 4, 5}) {
605 scheduler_.MarkStreamReady(stream_id, false);
606 }
607 // Round-robin only across 2 and 3, since children of 1 have lower priority.
608 EXPECT_TRUE(PopNextReturnsCycle({2, 3}));
609
610 // Make 8 have equal priority as 2 and 3.
611 scheduler_.SetStreamWeight(1, 200);
612 EXPECT_TRUE(PopNextReturnsCycle({8, 2, 3}));
613 }
614
615 // A removed stream shouldn't be scheduled.
616 TEST_F(PopNextUsableStreamTest, RemoveStream) {
617 scheduler_.UnregisterStream(1);
618
619 // Round-robin only across 2 and 3, since previous children of 1 have lower
620 // priority (the weight of 4 and 5 is scaled down when they are elevated to
621 // siblings of 2 and 3).
622 EXPECT_TRUE(PopNextReturnsCycle({2, 3}));
623
624 // Make previous children of 1 have equal priority as 2 and 3.
625 scheduler_.SetStreamWeight(4, 100);
626 scheduler_.SetStreamWeight(5, 100);
627 EXPECT_TRUE(PopNextReturnsCycle({4, 5, 2, 3}));
628 }
629
630 // Block an entire subtree.
631 TEST_F(PopNextUsableStreamTest, SubtreeBlocked) {
632 for (SpdyStreamId stream_id : {1, 4, 5, 8}) {
633 scheduler_.MarkStreamReady(stream_id, false);
634 }
635 EXPECT_TRUE(PopNextReturnsCycle({2, 3}));
636 }
637
638 // If all parent streams are blocked, children should be returned.
639 TEST_F(PopNextUsableStreamTest, ParentsBlocked) {
640 for (SpdyStreamId stream_id : {1, 2, 3}) {
641 scheduler_.MarkStreamReady(stream_id, false);
642 }
643 EXPECT_TRUE(PopNextReturnsCycle({4, 5, 6, 7}));
644 }
645
646 // Unblocking streams should make them schedulable.
647 TEST_F(PopNextUsableStreamTest, BlockAndUnblock) {
648 EXPECT_TRUE(PopNextReturnsCycle({1, 2, 3}));
649 scheduler_.MarkStreamReady(2, false);
650 EXPECT_TRUE(PopNextReturnsCycle({1, 3}));
651 scheduler_.MarkStreamReady(2, true);
652 // Cycle order permuted since 2 effectively appended at tail.
653 EXPECT_TRUE(PopNextReturnsCycle({1, 3, 2}));
654 }
655
656 // Block nodes in multiple subtrees.
657 TEST_F(PopNextUsableStreamTest, ScatteredBlocked) {
658 for (SpdyStreamId stream_id : {1, 2, 6, 7}) {
659 scheduler_.MarkStreamReady(stream_id, false);
660 }
661 // Only 3 returned, since of remaining streams it has highest priority.
662 EXPECT_TRUE(PopNextReturnsCycle({3}));
663
664 // Make children of 1 have priority equal to 3.
665 scheduler_.SetStreamWeight(1, 200);
666 EXPECT_TRUE(PopNextReturnsCycle({4, 5, 3}));
667
668 // When 4 is blocked, its child 8 should take its place, since it has same
669 // priority.
670 scheduler_.MarkStreamReady(4, false);
671 EXPECT_TRUE(PopNextReturnsCycle({8, 5, 3}));
672 }
673
606 } // namespace test 674 } // namespace test
607 } // namespace gfe_spdy 675 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/http2_write_scheduler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698