1 // Copyright (c) 2013 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/spdy_priority_forest.h" 6 7 #include "base/basictypes.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 10 namespace net { 11 12 TEST(SpdyPriorityForestTest, AddAndRemoveNodes) { 13 SpdyPriorityForest<uint32,int16> forest; 14 EXPECT_EQ(0, forest.num_nodes()); 15 EXPECT_FALSE(forest.NodeExists(1)); 16 17 EXPECT_TRUE(forest.AddRootNode(1, 1000)); 18 EXPECT_EQ(1, forest.num_nodes()); 19 ASSERT_TRUE(forest.NodeExists(1)); 20 EXPECT_EQ(1000, forest.GetPriority(1)); 21 EXPECT_FALSE(forest.NodeExists(5)); 22 23 EXPECT_TRUE(forest.AddRootNode(5, 50)); 24 EXPECT_FALSE(forest.AddRootNode(5, 500)); 25 EXPECT_EQ(2, forest.num_nodes()); 26 EXPECT_TRUE(forest.NodeExists(1)); 27 ASSERT_TRUE(forest.NodeExists(5)); 28 EXPECT_EQ(50, forest.GetPriority(5)); 29 EXPECT_FALSE(forest.NodeExists(13)); 30 31 EXPECT_TRUE(forest.AddRootNode(13, 130)); 32 EXPECT_EQ(3, forest.num_nodes()); 33 EXPECT_TRUE(forest.NodeExists(1)); 34 EXPECT_TRUE(forest.NodeExists(5)); 35 ASSERT_TRUE(forest.NodeExists(13)); 36 EXPECT_EQ(130, forest.GetPriority(13)); 37 38 EXPECT_TRUE(forest.RemoveNode(5)); 39 EXPECT_FALSE(forest.RemoveNode(5)); 40 EXPECT_EQ(2, forest.num_nodes()); 41 EXPECT_TRUE(forest.NodeExists(1)); 42 EXPECT_FALSE(forest.NodeExists(5)); 43 EXPECT_TRUE(forest.NodeExists(13)); 44 45 // The parent node 19 doesn't exist, so this should fail: 46 EXPECT_FALSE(forest.AddNonRootNode(7, 19, false)); 47 // This should succed, creating node 7: 48 EXPECT_TRUE(forest.AddNonRootNode(7, 13, false)); 49 // Now node 7 already exists, so this should fail: 50 EXPECT_FALSE(forest.AddNonRootNode(7, 1, false)); 51 // Node 13 already has a child (7), so this should fail: 52 EXPECT_FALSE(forest.AddNonRootNode(17, 13, false)); 53 54 ASSERT_TRUE(forest.ValidateInvariantsForTests()); 55 } 56 57 TEST(SpdyPriorityForestTest, SetParent) { 58 SpdyPriorityForest<uint32,int16> forest; 59 forest.AddRootNode(1, 1000); 60 forest.AddNonRootNode(2, 1, false); 61 forest.AddNonRootNode(3, 2, false); 62 forest.AddNonRootNode(5, 3, false); 63 forest.AddNonRootNode(7, 5, false); 64 forest.AddNonRootNode(9, 7, false); 65 forest.AddRootNode(11, 2000); 66 forest.AddNonRootNode(13, 11, false); 67 // We can't set the parent of a nonexistent node, or set the parent of an 68 // existing node to a nonexistent node. 69 EXPECT_FALSE(forest.SetParent(99, 13, false)); 70 EXPECT_FALSE(forest.SetParent(5, 99, false)); 71 // We can't make a node a child a node that already has a child: 72 EXPECT_FALSE(forest.SetParent(13, 7, false)); 73 EXPECT_FALSE(forest.SetParent(3, 11, false)); 74 // These would create cycles: 75 EXPECT_FALSE(forest.SetParent(11, 13, false)); 76 EXPECT_FALSE(forest.SetParent(1, 9, false)); 77 EXPECT_FALSE(forest.SetParent(3, 9, false)); 78 // But this change is legit: 79 EXPECT_EQ(7u, forest.GetChild(5)); 80 EXPECT_TRUE(forest.SetParent(7, 13, false)); 81 EXPECT_EQ(0u, forest.GetChild(5)); 82 EXPECT_EQ(13u, forest.GetParent(7)); 83 EXPECT_EQ(7u, forest.GetChild(13)); 84 // So is this change (now that 9 is no longer a descendant of 1): 85 EXPECT_TRUE(forest.SetParent(1, 9, false)); 86 EXPECT_EQ(9u, forest.GetParent(1)); 87 EXPECT_EQ(1u, forest.GetChild(9)); 88 // We must allow setting the parent of a node to its same parent (even though 89 // that parent of course has a child already), so that we can change 90 // orderedness. 91 EXPECT_EQ(1u, forest.GetParent(2)); 92 EXPECT_EQ(2u, forest.GetChild(1)); 93 EXPECT_FALSE(forest.IsNodeUnordered(2)); 94 EXPECT_TRUE(forest.SetParent(2, 1, true)); 95 EXPECT_EQ(1u, forest.GetParent(2)); 96 EXPECT_EQ(2u, forest.GetChild(1)); 97 EXPECT_TRUE(forest.IsNodeUnordered(2)); 98 99 ASSERT_TRUE(forest.ValidateInvariantsForTests()); 100 } 101 102 TEST(SpdyPriorityForestTest, RemoveNodesFromMiddleOfChain) { 103 SpdyPriorityForest<uint32,int16> forest; 104 forest.AddRootNode(1, 1000); 105 forest.AddNonRootNode(2, 1, false); 106 forest.AddNonRootNode(3, 2, true); 107 forest.AddNonRootNode(5, 3, false); 108 forest.AddNonRootNode(7, 5, true); 109 forest.AddNonRootNode(9, 7, true); 110 111 // Remove a node from the middle, with unordered links on both sides. The 112 // new merged link should also be unordered. 113 EXPECT_TRUE(forest.NodeExists(7)); 114 EXPECT_EQ(7u, forest.GetChild(5)); 115 EXPECT_EQ(7u, forest.GetParent(9)); 116 EXPECT_TRUE(forest.IsNodeUnordered(9)); 117 EXPECT_TRUE(forest.RemoveNode(7)); 118 EXPECT_FALSE(forest.NodeExists(7)); 119 EXPECT_EQ(9u, forest.GetChild(5)); 120 EXPECT_EQ(5u, forest.GetParent(9)); 121 EXPECT_TRUE(forest.IsNodeUnordered(9)); 122 123 // Remove another node from the middle, with an unordered link on only one 124 // side. The new merged link should be ordered. 125 EXPECT_TRUE(forest.NodeExists(2)); 126 EXPECT_EQ(2u, forest.GetChild(1)); 127 EXPECT_EQ(2u, forest.GetParent(3)); 128 EXPECT_FALSE(forest.IsNodeUnordered(2)); 129 EXPECT_TRUE(forest.IsNodeUnordered(3)); 130 EXPECT_TRUE(forest.RemoveNode(2)); 131 EXPECT_FALSE(forest.NodeExists(2)); 132 EXPECT_EQ(3u, forest.GetChild(1)); 133 EXPECT_EQ(1u, forest.GetParent(3)); 134 EXPECT_FALSE(forest.IsNodeUnordered(3)); 135 136 // Try removing the root. 137 EXPECT_TRUE(forest.NodeExists(1)); 138 EXPECT_EQ(0u, forest.GetParent(1)); 139 EXPECT_EQ(1000, forest.GetPriority(1)); 140 EXPECT_EQ(1u, forest.GetParent(3)); 141 EXPECT_EQ(0, forest.GetPriority(3)); 142 EXPECT_TRUE(forest.RemoveNode(1)); 143 EXPECT_FALSE(forest.NodeExists(1)); 144 EXPECT_EQ(0u, forest.GetParent(3)); 145 EXPECT_EQ(1000, forest.GetPriority(3)); 146 147 // Now try removing the tail. 148 EXPECT_TRUE(forest.NodeExists(9)); 149 EXPECT_EQ(9u, forest.GetChild(5)); 150 EXPECT_TRUE(forest.RemoveNode(9)); 151 EXPECT_FALSE(forest.NodeExists(9)); 152 EXPECT_EQ(0u, forest.GetChild(5)); 153 154 ASSERT_TRUE(forest.ValidateInvariantsForTests()); 155 } 156 157 TEST(SpdyPriorityForestTest, MergeOrderedAndUnorderedLinks1) { 158 SpdyPriorityForest<uint32,int16> forest; 159 forest.AddRootNode(1, 1000); 160 forest.AddNonRootNode(2, 1, true); 161 forest.AddNonRootNode(3, 2, false); 162 163 EXPECT_EQ(2u, forest.GetChild(1)); 164 EXPECT_EQ(3u, forest.GetChild(2)); 165 EXPECT_EQ(1u, forest.GetParent(2)); 166 EXPECT_EQ(2u, forest.GetParent(3)); 167 EXPECT_TRUE(forest.IsNodeUnordered(2)); 168 EXPECT_FALSE(forest.IsNodeUnordered(3)); 169 EXPECT_TRUE(forest.RemoveNode(2)); 170 EXPECT_FALSE(forest.NodeExists(2)); 171 EXPECT_EQ(3u, forest.GetChild(1)); 172 EXPECT_EQ(1u, forest.GetParent(3)); 173 EXPECT_FALSE(forest.IsNodeUnordered(3)); 174 175 ASSERT_TRUE(forest.ValidateInvariantsForTests()); 176 } 177 178 TEST(SpdyPriorityForestTest, MergeOrderedAndUnorderedLinks2) { 179 SpdyPriorityForest<uint32,int16> forest; 180 forest.AddRootNode(1, 1000); 181 forest.AddNonRootNode(2, 1, false); 182 forest.AddNonRootNode(3, 2, true); 183 184 EXPECT_EQ(2u, forest.GetChild(1)); 185 EXPECT_EQ(3u, forest.GetChild(2)); 186 EXPECT_EQ(1u, forest.GetParent(2)); 187 EXPECT_EQ(2u, forest.GetParent(3)); 188 EXPECT_FALSE(forest.IsNodeUnordered(2)); 189 EXPECT_TRUE(forest.IsNodeUnordered(3)); 190 EXPECT_TRUE(forest.RemoveNode(2)); 191 EXPECT_FALSE(forest.NodeExists(2)); 192 EXPECT_EQ(3u, forest.GetChild(1)); 193 EXPECT_EQ(1u, forest.GetParent(3)); 194 EXPECT_FALSE(forest.IsNodeUnordered(3)); 195 196 ASSERT_TRUE(forest.ValidateInvariantsForTests()); 197 } 198 199 TEST(SpdyPriorityForestTest, WeightedSelectionOfForests) { 200 SpdyPriorityForest<uint32,int16> forest; 201 forest.AddRootNode(1, 10); 202 forest.AddRootNode(3, 20); 203 forest.AddRootNode(5, 70); 204 EXPECT_EQ(70, forest.GetPriority(5)); 205 EXPECT_TRUE(forest.SetPriority(5, 40)); 206 EXPECT_FALSE(forest.SetPriority(7, 80)); 207 EXPECT_EQ(40, forest.GetPriority(5)); 208 forest.AddNonRootNode(7, 3, false); 209 EXPECT_FALSE(forest.IsMarkedReadyToRead(1)); 210 EXPECT_TRUE(forest.MarkReadyToRead(1)); 211 EXPECT_TRUE(forest.IsMarkedReadyToRead(1)); 212 EXPECT_TRUE(forest.MarkReadyToRead(5)); 213 EXPECT_TRUE(forest.MarkReadyToRead(7)); 214 EXPECT_FALSE(forest.MarkReadyToRead(99)); 215 216 int counts[8] = {0}; 217 for (int i = 0; i < 7000; ++i) { 218 const uint32 node_id = forest.NextNodeToRead(); 219 ASSERT_TRUE(node_id == 1 || node_id == 5 || node_id == 7) 220 << "node_id is " << node_id; 221 ++counts[node_id]; 222 } 223 224 // In theory, these could fail even if the weighted random selection is 225 // implemented correctly, but it's very unlikely. 226 EXPECT_GE(counts[1], 800); EXPECT_LE(counts[1], 1200); 227 EXPECT_GE(counts[7], 1600); EXPECT_LE(counts[7], 2400); 228 EXPECT_GE(counts[5], 3200); EXPECT_LE(counts[5], 4800); 229 230 // If we unmark all but one node, then we know for sure that that node will 231 // be selected next. 232 EXPECT_TRUE(forest.MarkNoLongerReadyToRead(1)); 233 EXPECT_TRUE(forest.MarkNoLongerReadyToRead(7)); 234 EXPECT_FALSE(forest.MarkNoLongerReadyToRead(99)); 235 EXPECT_EQ(5u, forest.NextNodeToRead()); 236 237 ASSERT_TRUE(forest.ValidateInvariantsForTests()); 238 } 239 240 TEST(SpdyPriorityForestTest, SelectionBetweenUnorderedNodes) { 241 SpdyPriorityForest<uint32,int16> forest; 242 forest.AddRootNode(1, 1000); 243 forest.AddNonRootNode(2, 1, false); 244 forest.AddNonRootNode(3, 2, true); 245 forest.AddNonRootNode(4, 3, true); 246 forest.AddNonRootNode(5, 4, true); 247 forest.AddNonRootNode(6, 5, true); 248 forest.AddNonRootNode(7, 6, false); 249 EXPECT_FALSE(forest.IsMarkedReadyToWrite(2)); 250 EXPECT_TRUE(forest.MarkReadyToWrite(2)); 251 EXPECT_TRUE(forest.IsMarkedReadyToWrite(2)); 252 EXPECT_TRUE(forest.MarkReadyToWrite(4)); 253 EXPECT_TRUE(forest.MarkReadyToWrite(6)); 254 EXPECT_TRUE(forest.MarkReadyToWrite(7)); 255 EXPECT_FALSE(forest.MarkReadyToWrite(99)); 256 257 int counts[8] = {0}; 258 for (int i = 0; i < 6000; ++i) { 259 const uint32 node_id = forest.NextNodeToWrite(); 260 ASSERT_TRUE(node_id == 2 || node_id == 4 || node_id == 6) 261 << "node_id is " << node_id; 262 ++counts[node_id]; 263 } 264 265 // In theory, these could fail even if the random selection is implemented 266 // correctly, but it's very unlikely. 267 EXPECT_GE(counts[2], 1600); EXPECT_LE(counts[2], 2400); 268 EXPECT_GE(counts[4], 1600); EXPECT_LE(counts[4], 2400); 269 EXPECT_GE(counts[6], 1600); EXPECT_LE(counts[6], 2400); 270 271 // Once we unmark that group of nodes, the next node up should be node 7, 272 // which has an ordered dependency on said group. 273 EXPECT_TRUE(forest.MarkNoLongerReadyToWrite(2)); 274 EXPECT_TRUE(forest.MarkNoLongerReadyToWrite(4)); 275 EXPECT_TRUE(forest.MarkNoLongerReadyToWrite(6)); 276 EXPECT_FALSE(forest.MarkNoLongerReadyToWrite(99)); 277 EXPECT_EQ(7u, forest.NextNodeToWrite()); 278 279 ASSERT_TRUE(forest.ValidateInvariantsForTests()); 280 } 281 282 } // namespace net 283