TestTreeTraversal.cpp (48622B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include <vector> 8 #include "mozilla/RefPtr.h" 9 #include "gtest/gtest.h" 10 #include "nsRegion.h" 11 #include "nsRect.h" 12 #include "TreeTraversal.h" 13 #include <stack> 14 #include <queue> 15 16 using namespace mozilla::layers; 17 using namespace mozilla; 18 19 enum class SearchNodeType { Needle, Hay }; 20 enum class ForEachNodeType { Continue, Skip }; 21 22 template <class T> 23 class TestNodeBase { 24 public: 25 NS_INLINE_DECL_REFCOUNTING(TestNodeBase<T>); 26 explicit TestNodeBase(T aType, int aExpectedTraversalRank = -1); 27 explicit TestNodeBase(); 28 void SetActualTraversalRank(int aRank); 29 void SetValue(int aValue); 30 void SetType(T aType); 31 void SetRegion(nsRegion aRegion); 32 int GetExpectedTraversalRank(); 33 int GetActualTraversalRank(); 34 int GetValue(); 35 T GetType(); 36 nsRegion GetRegion(); 37 virtual bool IsLeaf() = 0; 38 39 private: 40 MOZ_INIT_OUTSIDE_CTOR int mExpectedTraversalRank; 41 MOZ_INIT_OUTSIDE_CTOR int mActualTraversalRank; 42 MOZ_INIT_OUTSIDE_CTOR int mValue; 43 MOZ_INIT_OUTSIDE_CTOR nsRegion mRegion; 44 MOZ_INIT_OUTSIDE_CTOR T mType; 45 46 protected: 47 virtual ~TestNodeBase() = default; 48 }; 49 50 template <class T> 51 class TestNodeReverse : public TestNodeBase<T> { 52 public: 53 explicit TestNodeReverse(T aType, int aExpectedTraversalRank = -1); 54 explicit TestNodeReverse(); 55 void AddChild(RefPtr<TestNodeReverse<T>> aNode); 56 TestNodeReverse<T>* GetLastChild(); 57 TestNodeReverse<T>* GetPrevSibling(); 58 bool IsLeaf(); 59 60 private: 61 void SetPrevSibling(RefPtr<TestNodeReverse<T>> aNode); 62 void SetLastChild(RefPtr<TestNodeReverse<T>> aNode); 63 RefPtr<TestNodeReverse<T>> mSiblingNode; 64 RefPtr<TestNodeReverse<T>> mLastChildNode; 65 ~TestNodeReverse() = default; 66 }; 67 68 template <class T> 69 class TestNodeForward : public TestNodeBase<T> { 70 public: 71 explicit TestNodeForward(T aType, int aExpectedTraversalRank = -1); 72 explicit TestNodeForward(); 73 void AddChild(RefPtr<TestNodeForward<T>> aNode); 74 TestNodeForward<T>* GetFirstChild(); 75 TestNodeForward<T>* GetNextSibling(); 76 bool IsLeaf(); 77 78 private: 79 void SetNextSibling(RefPtr<TestNodeForward<T>> aNode); 80 void SetLastChild(RefPtr<TestNodeForward<T>> aNode); 81 void SetFirstChild(RefPtr<TestNodeForward<T>> aNode); 82 RefPtr<TestNodeForward<T>> mSiblingNode = nullptr; 83 RefPtr<TestNodeForward<T>> mFirstChildNode = nullptr; 84 // Track last child to facilitate appending children 85 RefPtr<TestNodeForward<T>> mLastChildNode = nullptr; 86 ~TestNodeForward() = default; 87 }; 88 89 template <class T> 90 TestNodeReverse<T>::TestNodeReverse(T aType, int aExpectedTraversalRank) 91 : TestNodeBase<T>(aType, aExpectedTraversalRank) {} 92 93 template <class T> 94 TestNodeReverse<T>::TestNodeReverse() : TestNodeBase<T>() {} 95 96 template <class T> 97 void TestNodeReverse<T>::SetLastChild(RefPtr<TestNodeReverse<T>> aNode) { 98 mLastChildNode = aNode; 99 } 100 101 template <class T> 102 void TestNodeReverse<T>::AddChild(RefPtr<TestNodeReverse<T>> aNode) { 103 aNode->SetPrevSibling(mLastChildNode); 104 SetLastChild(aNode); 105 } 106 107 template <class T> 108 void TestNodeReverse<T>::SetPrevSibling(RefPtr<TestNodeReverse<T>> aNode) { 109 mSiblingNode = aNode; 110 } 111 112 template <class T> 113 TestNodeReverse<T>* TestNodeReverse<T>::GetLastChild() { 114 return mLastChildNode; 115 } 116 117 template <class T> 118 TestNodeReverse<T>* TestNodeReverse<T>::GetPrevSibling() { 119 return mSiblingNode; 120 } 121 122 template <class T> 123 bool TestNodeReverse<T>::IsLeaf() { 124 return !mLastChildNode; 125 } 126 127 template <class T> 128 TestNodeForward<T>::TestNodeForward(T aType, int aExpectedTraversalRank) 129 : TestNodeBase<T>(aType, aExpectedTraversalRank) {} 130 131 template <class T> 132 TestNodeForward<T>::TestNodeForward() : TestNodeBase<T>() {} 133 134 template <class T> 135 void TestNodeForward<T>::AddChild(RefPtr<TestNodeForward<T>> aNode) { 136 if (mFirstChildNode == nullptr) { 137 SetFirstChild(aNode); 138 SetLastChild(aNode); 139 } else { 140 mLastChildNode->SetNextSibling(aNode); 141 SetLastChild(aNode); 142 } 143 } 144 145 template <class T> 146 void TestNodeForward<T>::SetLastChild(RefPtr<TestNodeForward<T>> aNode) { 147 mLastChildNode = aNode; 148 } 149 150 template <class T> 151 void TestNodeForward<T>::SetFirstChild(RefPtr<TestNodeForward<T>> aNode) { 152 mFirstChildNode = aNode; 153 } 154 155 template <class T> 156 void TestNodeForward<T>::SetNextSibling(RefPtr<TestNodeForward<T>> aNode) { 157 mSiblingNode = aNode; 158 } 159 160 template <class T> 161 bool TestNodeForward<T>::IsLeaf() { 162 return !mFirstChildNode; 163 } 164 165 template <class T> 166 TestNodeForward<T>* TestNodeForward<T>::GetFirstChild() { 167 return mFirstChildNode; 168 } 169 170 template <class T> 171 TestNodeForward<T>* TestNodeForward<T>::GetNextSibling() { 172 return mSiblingNode; 173 } 174 175 template <class T> 176 TestNodeBase<T>::TestNodeBase(T aType, int aExpectedTraversalRank) 177 : mExpectedTraversalRank(aExpectedTraversalRank), 178 mActualTraversalRank(-1), 179 mType(aType) {} 180 181 template <class T> 182 TestNodeBase<T>::TestNodeBase() = default; 183 184 template <class T> 185 int TestNodeBase<T>::GetActualTraversalRank() { 186 return mActualTraversalRank; 187 } 188 189 template <class T> 190 void TestNodeBase<T>::SetActualTraversalRank(int aRank) { 191 mActualTraversalRank = aRank; 192 } 193 194 template <class T> 195 int TestNodeBase<T>::GetExpectedTraversalRank() { 196 return mExpectedTraversalRank; 197 } 198 199 template <class T> 200 T TestNodeBase<T>::GetType() { 201 return mType; 202 } 203 204 template <class T> 205 void TestNodeBase<T>::SetType(T aType) { 206 mType = aType; 207 } 208 209 template <class T> 210 nsRegion TestNodeBase<T>::GetRegion() { 211 return mRegion; 212 } 213 214 template <class T> 215 void TestNodeBase<T>::SetRegion(nsRegion aRegion) { 216 mRegion = aRegion; 217 } 218 219 template <class T> 220 int TestNodeBase<T>::GetValue() { 221 return mValue; 222 } 223 224 template <class T> 225 void TestNodeBase<T>::SetValue(int aValue) { 226 mValue = aValue; 227 } 228 229 typedef TestNodeBase<SearchNodeType> SearchTestNode; 230 typedef TestNodeBase<ForEachNodeType> ForEachTestNode; 231 typedef TestNodeReverse<SearchNodeType> SearchTestNodeReverse; 232 typedef TestNodeReverse<ForEachNodeType> ForEachTestNodeReverse; 233 typedef TestNodeForward<SearchNodeType> SearchTestNodeForward; 234 typedef TestNodeForward<ForEachNodeType> ForEachTestNodeForward; 235 236 TEST(TreeTraversal, DepthFirstSearchNull) 237 { 238 RefPtr<SearchTestNodeReverse> nullNode; 239 RefPtr<SearchTestNodeReverse> result = 240 DepthFirstSearch<layers::ReverseIterator>( 241 nullNode.get(), [](SearchTestNodeReverse* aNode) { 242 return aNode->GetType() == SearchNodeType::Needle; 243 }); 244 ASSERT_EQ(result.get(), nullptr) 245 << "Null root did not return null search result."; 246 } 247 248 TEST(TreeTraversal, DepthFirstSearchValueExists) 249 { 250 int visitCount = 0; 251 size_t expectedNeedleTraversalRank = 7; 252 RefPtr<SearchTestNodeForward> needleNode; 253 std::vector<RefPtr<SearchTestNodeForward>> nodeList; 254 nodeList.reserve(10); 255 for (size_t i = 0; i < 10; i++) { 256 if (i == expectedNeedleTraversalRank) { 257 needleNode = new SearchTestNodeForward(SearchNodeType::Needle, i); 258 nodeList.push_back(needleNode); 259 } else if (i < expectedNeedleTraversalRank) { 260 nodeList.push_back(new SearchTestNodeForward(SearchNodeType::Hay, i)); 261 } else { 262 nodeList.push_back(new SearchTestNodeForward(SearchNodeType::Hay)); 263 } 264 } 265 266 RefPtr<SearchTestNodeForward> root = nodeList[0]; 267 nodeList[0]->AddChild(nodeList[1]); 268 nodeList[0]->AddChild(nodeList[4]); 269 nodeList[1]->AddChild(nodeList[2]); 270 nodeList[1]->AddChild(nodeList[3]); 271 nodeList[4]->AddChild(nodeList[5]); 272 nodeList[4]->AddChild(nodeList[6]); 273 nodeList[6]->AddChild(nodeList[7]); 274 nodeList[7]->AddChild(nodeList[8]); 275 nodeList[7]->AddChild(nodeList[9]); 276 277 RefPtr<SearchTestNodeForward> foundNode = 278 DepthFirstSearch<layers::ForwardIterator>( 279 root.get(), [&visitCount](SearchTestNodeForward* aNode) { 280 aNode->SetActualTraversalRank(visitCount); 281 visitCount++; 282 return aNode->GetType() == SearchNodeType::Needle; 283 }); 284 285 for (size_t i = 0; i < nodeList.size(); i++) { 286 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 287 nodeList[i]->GetActualTraversalRank()) 288 << "Node at index " << i << " was hit out of order."; 289 } 290 291 ASSERT_EQ(foundNode, needleNode) << "Search did not return expected node."; 292 ASSERT_EQ(foundNode->GetType(), SearchNodeType::Needle) 293 << "Returned node does not match expected value (something odd " 294 "happened)."; 295 } 296 297 TEST(TreeTraversal, DepthFirstSearchValueExistsReverse) 298 { 299 int visitCount = 0; 300 size_t expectedNeedleTraversalRank = 7; 301 RefPtr<SearchTestNodeReverse> needleNode; 302 std::vector<RefPtr<SearchTestNodeReverse>> nodeList; 303 nodeList.reserve(10); 304 for (size_t i = 0; i < 10; i++) { 305 if (i == expectedNeedleTraversalRank) { 306 needleNode = new SearchTestNodeReverse(SearchNodeType::Needle, i); 307 nodeList.push_back(needleNode); 308 } else if (i < expectedNeedleTraversalRank) { 309 nodeList.push_back(new SearchTestNodeReverse(SearchNodeType::Hay, i)); 310 } else { 311 nodeList.push_back(new SearchTestNodeReverse(SearchNodeType::Hay)); 312 } 313 } 314 315 RefPtr<SearchTestNodeReverse> root = nodeList[0]; 316 nodeList[0]->AddChild(nodeList[4]); 317 nodeList[0]->AddChild(nodeList[1]); 318 nodeList[1]->AddChild(nodeList[3]); 319 nodeList[1]->AddChild(nodeList[2]); 320 nodeList[4]->AddChild(nodeList[6]); 321 nodeList[4]->AddChild(nodeList[5]); 322 nodeList[6]->AddChild(nodeList[7]); 323 nodeList[7]->AddChild(nodeList[9]); 324 nodeList[7]->AddChild(nodeList[8]); 325 326 RefPtr<SearchTestNodeReverse> foundNode = 327 DepthFirstSearch<layers::ReverseIterator>( 328 root.get(), [&visitCount](SearchTestNodeReverse* aNode) { 329 aNode->SetActualTraversalRank(visitCount); 330 visitCount++; 331 return aNode->GetType() == SearchNodeType::Needle; 332 }); 333 334 for (size_t i = 0; i < nodeList.size(); i++) { 335 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 336 nodeList[i]->GetActualTraversalRank()) 337 << "Node at index " << i << " was hit out of order."; 338 } 339 340 ASSERT_EQ(foundNode, needleNode) << "Search did not return expected node."; 341 ASSERT_EQ(foundNode->GetType(), SearchNodeType::Needle) 342 << "Returned node does not match expected value (something odd " 343 "happened)."; 344 } 345 346 TEST(TreeTraversal, DepthFirstSearchRootIsNeedle) 347 { 348 RefPtr<SearchTestNodeReverse> root = 349 new SearchTestNodeReverse(SearchNodeType::Needle, 0); 350 RefPtr<SearchTestNodeReverse> childNode1 = 351 new SearchTestNodeReverse(SearchNodeType::Hay); 352 RefPtr<SearchTestNodeReverse> childNode2 = 353 new SearchTestNodeReverse(SearchNodeType::Hay); 354 int visitCount = 0; 355 RefPtr<SearchTestNodeReverse> result = 356 DepthFirstSearch<layers::ReverseIterator>( 357 root.get(), [&visitCount](SearchTestNodeReverse* aNode) { 358 aNode->SetActualTraversalRank(visitCount); 359 visitCount++; 360 return aNode->GetType() == SearchNodeType::Needle; 361 }); 362 ASSERT_EQ(result, root) << "Search starting at needle did not return needle."; 363 ASSERT_EQ(root->GetExpectedTraversalRank(), root->GetActualTraversalRank()) 364 << "Search starting at needle did not return needle."; 365 ASSERT_EQ(childNode1->GetExpectedTraversalRank(), 366 childNode1->GetActualTraversalRank()) 367 << "Search starting at needle continued past needle."; 368 ASSERT_EQ(childNode2->GetExpectedTraversalRank(), 369 childNode2->GetActualTraversalRank()) 370 << "Search starting at needle continued past needle."; 371 } 372 373 TEST(TreeTraversal, DepthFirstSearchValueDoesNotExist) 374 { 375 int visitCount = 0; 376 std::vector<RefPtr<SearchTestNodeForward>> nodeList; 377 nodeList.reserve(10); 378 for (int i = 0; i < 10; i++) { 379 nodeList.push_back(new SearchTestNodeForward(SearchNodeType::Hay, i)); 380 } 381 382 RefPtr<SearchTestNodeForward> root = nodeList[0]; 383 nodeList[0]->AddChild(nodeList[1]); 384 nodeList[0]->AddChild(nodeList[4]); 385 nodeList[1]->AddChild(nodeList[2]); 386 nodeList[1]->AddChild(nodeList[3]); 387 nodeList[4]->AddChild(nodeList[5]); 388 nodeList[4]->AddChild(nodeList[6]); 389 nodeList[6]->AddChild(nodeList[7]); 390 nodeList[7]->AddChild(nodeList[8]); 391 nodeList[7]->AddChild(nodeList[9]); 392 393 RefPtr<SearchTestNodeForward> foundNode = 394 DepthFirstSearch<layers::ForwardIterator>( 395 root.get(), [&visitCount](SearchTestNodeForward* aNode) { 396 aNode->SetActualTraversalRank(visitCount); 397 visitCount++; 398 return aNode->GetType() == SearchNodeType::Needle; 399 }); 400 401 for (int i = 0; i < 10; i++) { 402 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 403 nodeList[i]->GetActualTraversalRank()) 404 << "Node at index " << i << " was hit out of order."; 405 } 406 407 ASSERT_EQ(foundNode.get(), nullptr) 408 << "Search found something that should not exist."; 409 } 410 411 TEST(TreeTraversal, DepthFirstSearchValueDoesNotExistReverse) 412 { 413 int visitCount = 0; 414 std::vector<RefPtr<SearchTestNodeReverse>> nodeList; 415 nodeList.reserve(10); 416 for (int i = 0; i < 10; i++) { 417 nodeList.push_back(new SearchTestNodeReverse(SearchNodeType::Hay, i)); 418 } 419 420 RefPtr<SearchTestNodeReverse> root = nodeList[0]; 421 nodeList[0]->AddChild(nodeList[4]); 422 nodeList[0]->AddChild(nodeList[1]); 423 nodeList[1]->AddChild(nodeList[3]); 424 nodeList[1]->AddChild(nodeList[2]); 425 nodeList[4]->AddChild(nodeList[6]); 426 nodeList[4]->AddChild(nodeList[5]); 427 nodeList[6]->AddChild(nodeList[7]); 428 nodeList[7]->AddChild(nodeList[9]); 429 nodeList[7]->AddChild(nodeList[8]); 430 431 RefPtr<SearchTestNodeReverse> foundNode = 432 DepthFirstSearch<layers::ReverseIterator>( 433 root.get(), [&visitCount](SearchTestNodeReverse* aNode) { 434 aNode->SetActualTraversalRank(visitCount); 435 visitCount++; 436 return aNode->GetType() == SearchNodeType::Needle; 437 }); 438 439 for (int i = 0; i < 10; i++) { 440 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 441 nodeList[i]->GetActualTraversalRank()) 442 << "Node at index " << i << " was hit out of order."; 443 } 444 445 ASSERT_EQ(foundNode.get(), nullptr) 446 << "Search found something that should not exist."; 447 } 448 449 TEST(TreeTraversal, DepthFirstSearchPostOrderNull) 450 { 451 RefPtr<SearchTestNodeReverse> nullNode; 452 RefPtr<SearchTestNodeReverse> result = 453 DepthFirstSearchPostOrder<layers::ReverseIterator>( 454 nullNode.get(), [](SearchTestNodeReverse* aNode) { 455 return aNode->GetType() == SearchNodeType::Needle; 456 }); 457 ASSERT_EQ(result.get(), nullptr) 458 << "Null root did not return null search result."; 459 } 460 461 TEST(TreeTraversal, DepthFirstSearchPostOrderValueExists) 462 { 463 int visitCount = 0; 464 size_t expectedNeedleTraversalRank = 7; 465 RefPtr<SearchTestNodeForward> needleNode; 466 std::vector<RefPtr<SearchTestNodeForward>> nodeList; 467 for (size_t i = 0; i < 10; i++) { 468 if (i == expectedNeedleTraversalRank) { 469 needleNode = new SearchTestNodeForward(SearchNodeType::Needle, i); 470 nodeList.push_back(needleNode); 471 } else if (i < expectedNeedleTraversalRank) { 472 nodeList.push_back(new SearchTestNodeForward(SearchNodeType::Hay, i)); 473 } else { 474 nodeList.push_back(new SearchTestNodeForward(SearchNodeType::Hay)); 475 } 476 } 477 478 RefPtr<SearchTestNodeForward> root = nodeList[9]; 479 nodeList[9]->AddChild(nodeList[2]); 480 nodeList[9]->AddChild(nodeList[8]); 481 nodeList[2]->AddChild(nodeList[0]); 482 nodeList[2]->AddChild(nodeList[1]); 483 nodeList[8]->AddChild(nodeList[6]); 484 nodeList[8]->AddChild(nodeList[7]); 485 nodeList[6]->AddChild(nodeList[5]); 486 nodeList[5]->AddChild(nodeList[3]); 487 nodeList[5]->AddChild(nodeList[4]); 488 489 RefPtr<SearchTestNodeForward> foundNode = 490 DepthFirstSearchPostOrder<layers::ForwardIterator>( 491 root.get(), [&visitCount](SearchTestNodeForward* aNode) { 492 aNode->SetActualTraversalRank(visitCount); 493 visitCount++; 494 return aNode->GetType() == SearchNodeType::Needle; 495 }); 496 497 for (size_t i = 0; i < nodeList.size(); i++) { 498 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 499 nodeList[i]->GetActualTraversalRank()) 500 << "Node at index " << i << " was hit out of order."; 501 } 502 503 ASSERT_EQ(foundNode, needleNode) << "Search did not return expected node."; 504 ASSERT_EQ(foundNode->GetType(), SearchNodeType::Needle) 505 << "Returned node does not match expected value (something odd " 506 "happened)."; 507 } 508 509 TEST(TreeTraversal, DepthFirstSearchPostOrderValueExistsReverse) 510 { 511 int visitCount = 0; 512 size_t expectedNeedleTraversalRank = 7; 513 RefPtr<SearchTestNodeReverse> needleNode; 514 std::vector<RefPtr<SearchTestNodeReverse>> nodeList; 515 for (size_t i = 0; i < 10; i++) { 516 if (i == expectedNeedleTraversalRank) { 517 needleNode = new SearchTestNodeReverse(SearchNodeType::Needle, i); 518 nodeList.push_back(needleNode); 519 } else if (i < expectedNeedleTraversalRank) { 520 nodeList.push_back(new SearchTestNodeReverse(SearchNodeType::Hay, i)); 521 } else { 522 nodeList.push_back(new SearchTestNodeReverse(SearchNodeType::Hay)); 523 } 524 } 525 526 RefPtr<SearchTestNodeReverse> root = nodeList[9]; 527 nodeList[9]->AddChild(nodeList[8]); 528 nodeList[9]->AddChild(nodeList[2]); 529 nodeList[2]->AddChild(nodeList[1]); 530 nodeList[2]->AddChild(nodeList[0]); 531 nodeList[8]->AddChild(nodeList[7]); 532 nodeList[8]->AddChild(nodeList[6]); 533 nodeList[6]->AddChild(nodeList[5]); 534 nodeList[5]->AddChild(nodeList[4]); 535 nodeList[5]->AddChild(nodeList[3]); 536 537 RefPtr<SearchTestNodeReverse> foundNode = 538 DepthFirstSearchPostOrder<layers::ReverseIterator>( 539 root.get(), [&visitCount](SearchTestNodeReverse* aNode) { 540 aNode->SetActualTraversalRank(visitCount); 541 visitCount++; 542 return aNode->GetType() == SearchNodeType::Needle; 543 }); 544 545 for (size_t i = 0; i < nodeList.size(); i++) { 546 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 547 nodeList[i]->GetActualTraversalRank()) 548 << "Node at index " << i << " was hit out of order."; 549 } 550 551 ASSERT_EQ(foundNode, needleNode) << "Search did not return expected node."; 552 ASSERT_EQ(foundNode->GetType(), SearchNodeType::Needle) 553 << "Returned node does not match expected value (something odd " 554 "happened)."; 555 } 556 557 TEST(TreeTraversal, DepthFirstSearchPostOrderRootIsNeedle) 558 { 559 RefPtr<SearchTestNodeReverse> root = 560 new SearchTestNodeReverse(SearchNodeType::Needle, 0); 561 RefPtr<SearchTestNodeReverse> childNode1 = 562 new SearchTestNodeReverse(SearchNodeType::Hay); 563 RefPtr<SearchTestNodeReverse> childNode2 = 564 new SearchTestNodeReverse(SearchNodeType::Hay); 565 int visitCount = 0; 566 RefPtr<SearchTestNodeReverse> result = 567 DepthFirstSearchPostOrder<layers::ReverseIterator>( 568 root.get(), [&visitCount](SearchTestNodeReverse* aNode) { 569 aNode->SetActualTraversalRank(visitCount); 570 visitCount++; 571 return aNode->GetType() == SearchNodeType::Needle; 572 }); 573 ASSERT_EQ(result, root) << "Search starting at needle did not return needle."; 574 ASSERT_EQ(root->GetExpectedTraversalRank(), root->GetActualTraversalRank()) 575 << "Search starting at needle did not return needle."; 576 ASSERT_EQ(childNode1->GetExpectedTraversalRank(), 577 childNode1->GetActualTraversalRank()) 578 << "Search starting at needle continued past needle."; 579 ASSERT_EQ(childNode2->GetExpectedTraversalRank(), 580 childNode2->GetActualTraversalRank()) 581 << "Search starting at needle continued past needle."; 582 } 583 584 TEST(TreeTraversal, DepthFirstSearchPostOrderValueDoesNotExist) 585 { 586 int visitCount = 0; 587 std::vector<RefPtr<SearchTestNodeForward>> nodeList; 588 nodeList.reserve(10); 589 for (int i = 0; i < 10; i++) { 590 nodeList.push_back(new SearchTestNodeForward(SearchNodeType::Hay, i)); 591 } 592 593 RefPtr<SearchTestNodeForward> root = nodeList[9]; 594 nodeList[9]->AddChild(nodeList[2]); 595 nodeList[9]->AddChild(nodeList[8]); 596 nodeList[2]->AddChild(nodeList[0]); 597 nodeList[2]->AddChild(nodeList[1]); 598 nodeList[8]->AddChild(nodeList[6]); 599 nodeList[8]->AddChild(nodeList[7]); 600 nodeList[6]->AddChild(nodeList[5]); 601 nodeList[5]->AddChild(nodeList[3]); 602 nodeList[5]->AddChild(nodeList[4]); 603 604 RefPtr<SearchTestNodeForward> foundNode = 605 DepthFirstSearchPostOrder<layers::ForwardIterator>( 606 root.get(), [&visitCount](SearchTestNodeForward* aNode) { 607 aNode->SetActualTraversalRank(visitCount); 608 visitCount++; 609 return aNode->GetType() == SearchNodeType::Needle; 610 }); 611 612 for (int i = 0; i < 10; i++) { 613 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 614 nodeList[i]->GetActualTraversalRank()) 615 << "Node at index " << i << " was hit out of order."; 616 } 617 618 ASSERT_EQ(foundNode.get(), nullptr) 619 << "Search found something that should not exist."; 620 } 621 622 TEST(TreeTraversal, DepthFirstSearchPostOrderValueDoesNotExistReverse) 623 { 624 int visitCount = 0; 625 std::vector<RefPtr<SearchTestNodeReverse>> nodeList; 626 nodeList.reserve(10); 627 for (int i = 0; i < 10; i++) { 628 nodeList.push_back(new SearchTestNodeReverse(SearchNodeType::Hay, i)); 629 } 630 631 RefPtr<SearchTestNodeReverse> root = nodeList[9]; 632 nodeList[9]->AddChild(nodeList[8]); 633 nodeList[9]->AddChild(nodeList[2]); 634 nodeList[2]->AddChild(nodeList[1]); 635 nodeList[2]->AddChild(nodeList[0]); 636 nodeList[8]->AddChild(nodeList[7]); 637 nodeList[8]->AddChild(nodeList[6]); 638 nodeList[6]->AddChild(nodeList[5]); 639 nodeList[5]->AddChild(nodeList[4]); 640 nodeList[5]->AddChild(nodeList[3]); 641 642 RefPtr<SearchTestNodeReverse> foundNode = 643 DepthFirstSearchPostOrder<layers::ReverseIterator>( 644 root.get(), [&visitCount](SearchTestNodeReverse* aNode) { 645 aNode->SetActualTraversalRank(visitCount); 646 visitCount++; 647 return aNode->GetType() == SearchNodeType::Needle; 648 }); 649 650 for (int i = 0; i < 10; i++) { 651 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 652 nodeList[i]->GetActualTraversalRank()) 653 << "Node at index " << i << " was hit out of order."; 654 } 655 656 ASSERT_EQ(foundNode.get(), nullptr) 657 << "Search found something that should not exist."; 658 } 659 660 TEST(TreeTraversal, BreadthFirstSearchNull) 661 { 662 RefPtr<SearchTestNodeReverse> nullNode; 663 RefPtr<SearchTestNodeReverse> result = 664 BreadthFirstSearch<layers::ReverseIterator>( 665 nullNode.get(), [](SearchTestNodeReverse* aNode) { 666 return aNode->GetType() == SearchNodeType::Needle; 667 }); 668 ASSERT_EQ(result.get(), nullptr) 669 << "Null root did not return null search result."; 670 } 671 672 TEST(TreeTraversal, BreadthFirstSearchRootIsNeedle) 673 { 674 RefPtr<SearchTestNodeReverse> root = 675 new SearchTestNodeReverse(SearchNodeType::Needle, 0); 676 RefPtr<SearchTestNodeReverse> childNode1 = 677 new SearchTestNodeReverse(SearchNodeType::Hay); 678 RefPtr<SearchTestNodeReverse> childNode2 = 679 new SearchTestNodeReverse(SearchNodeType::Hay); 680 int visitCount = 0; 681 RefPtr<SearchTestNodeReverse> result = 682 BreadthFirstSearch<layers::ReverseIterator>( 683 root.get(), [&visitCount](SearchTestNodeReverse* aNode) { 684 aNode->SetActualTraversalRank(visitCount); 685 visitCount++; 686 return aNode->GetType() == SearchNodeType::Needle; 687 }); 688 ASSERT_EQ(result, root) << "Search starting at needle did not return needle."; 689 ASSERT_EQ(root->GetExpectedTraversalRank(), root->GetActualTraversalRank()) 690 << "Search starting at needle did not return needle."; 691 ASSERT_EQ(childNode1->GetExpectedTraversalRank(), 692 childNode1->GetActualTraversalRank()) 693 << "Search starting at needle continued past needle."; 694 ASSERT_EQ(childNode2->GetExpectedTraversalRank(), 695 childNode2->GetActualTraversalRank()) 696 << "Search starting at needle continued past needle."; 697 } 698 699 TEST(TreeTraversal, BreadthFirstSearchValueExists) 700 { 701 int visitCount = 0; 702 size_t expectedNeedleTraversalRank = 7; 703 RefPtr<SearchTestNodeForward> needleNode; 704 std::vector<RefPtr<SearchTestNodeForward>> nodeList; 705 nodeList.reserve(10); 706 for (size_t i = 0; i < 10; i++) { 707 if (i == expectedNeedleTraversalRank) { 708 needleNode = new SearchTestNodeForward(SearchNodeType::Needle, i); 709 nodeList.push_back(needleNode); 710 } else if (i < expectedNeedleTraversalRank) { 711 nodeList.push_back(new SearchTestNodeForward(SearchNodeType::Hay, i)); 712 } else { 713 nodeList.push_back(new SearchTestNodeForward(SearchNodeType::Hay)); 714 } 715 } 716 717 RefPtr<SearchTestNodeForward> root = nodeList[0]; 718 nodeList[0]->AddChild(nodeList[1]); 719 nodeList[0]->AddChild(nodeList[2]); 720 nodeList[1]->AddChild(nodeList[3]); 721 nodeList[1]->AddChild(nodeList[4]); 722 nodeList[2]->AddChild(nodeList[5]); 723 nodeList[2]->AddChild(nodeList[6]); 724 nodeList[6]->AddChild(nodeList[7]); 725 nodeList[7]->AddChild(nodeList[8]); 726 nodeList[7]->AddChild(nodeList[9]); 727 728 RefPtr<SearchTestNodeForward> foundNode = 729 BreadthFirstSearch<layers::ForwardIterator>( 730 root.get(), [&visitCount](SearchTestNodeForward* aNode) { 731 aNode->SetActualTraversalRank(visitCount); 732 visitCount++; 733 return aNode->GetType() == SearchNodeType::Needle; 734 }); 735 736 for (size_t i = 0; i < nodeList.size(); i++) { 737 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 738 nodeList[i]->GetActualTraversalRank()) 739 << "Node at index " << i << " was hit out of order."; 740 } 741 742 ASSERT_EQ(foundNode, needleNode) << "Search did not return expected node."; 743 ASSERT_EQ(foundNode->GetType(), SearchNodeType::Needle) 744 << "Returned node does not match expected value (something odd " 745 "happened)."; 746 } 747 748 TEST(TreeTraversal, BreadthFirstSearchValueExistsReverse) 749 { 750 int visitCount = 0; 751 size_t expectedNeedleTraversalRank = 7; 752 RefPtr<SearchTestNodeReverse> needleNode; 753 std::vector<RefPtr<SearchTestNodeReverse>> nodeList; 754 nodeList.reserve(10); 755 for (size_t i = 0; i < 10; i++) { 756 if (i == expectedNeedleTraversalRank) { 757 needleNode = new SearchTestNodeReverse(SearchNodeType::Needle, i); 758 nodeList.push_back(needleNode); 759 } else if (i < expectedNeedleTraversalRank) { 760 nodeList.push_back(new SearchTestNodeReverse(SearchNodeType::Hay, i)); 761 } else { 762 nodeList.push_back(new SearchTestNodeReverse(SearchNodeType::Hay)); 763 } 764 } 765 766 RefPtr<SearchTestNodeReverse> root = nodeList[0]; 767 nodeList[0]->AddChild(nodeList[2]); 768 nodeList[0]->AddChild(nodeList[1]); 769 nodeList[1]->AddChild(nodeList[4]); 770 nodeList[1]->AddChild(nodeList[3]); 771 nodeList[2]->AddChild(nodeList[6]); 772 nodeList[2]->AddChild(nodeList[5]); 773 nodeList[6]->AddChild(nodeList[7]); 774 nodeList[7]->AddChild(nodeList[9]); 775 nodeList[7]->AddChild(nodeList[8]); 776 777 RefPtr<SearchTestNodeReverse> foundNode = 778 BreadthFirstSearch<layers::ReverseIterator>( 779 root.get(), [&visitCount](SearchTestNodeReverse* aNode) { 780 aNode->SetActualTraversalRank(visitCount); 781 visitCount++; 782 return aNode->GetType() == SearchNodeType::Needle; 783 }); 784 785 for (size_t i = 0; i < nodeList.size(); i++) { 786 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 787 nodeList[i]->GetActualTraversalRank()) 788 << "Node at index " << i << " was hit out of order."; 789 } 790 791 ASSERT_EQ(foundNode, needleNode) << "Search did not return expected node."; 792 ASSERT_EQ(foundNode->GetType(), SearchNodeType::Needle) 793 << "Returned node does not match expected value (something odd " 794 "happened)."; 795 } 796 797 TEST(TreeTraversal, BreadthFirstSearchValueDoesNotExist) 798 { 799 int visitCount = 0; 800 std::vector<RefPtr<SearchTestNodeForward>> nodeList; 801 nodeList.reserve(10); 802 for (int i = 0; i < 10; i++) { 803 nodeList.push_back(new SearchTestNodeForward(SearchNodeType::Hay, i)); 804 } 805 806 RefPtr<SearchTestNodeForward> root = nodeList[0]; 807 nodeList[0]->AddChild(nodeList[1]); 808 nodeList[0]->AddChild(nodeList[2]); 809 nodeList[1]->AddChild(nodeList[3]); 810 nodeList[1]->AddChild(nodeList[4]); 811 nodeList[2]->AddChild(nodeList[5]); 812 nodeList[2]->AddChild(nodeList[6]); 813 nodeList[6]->AddChild(nodeList[7]); 814 nodeList[7]->AddChild(nodeList[8]); 815 nodeList[7]->AddChild(nodeList[9]); 816 817 RefPtr<SearchTestNodeForward> foundNode = 818 BreadthFirstSearch<layers::ForwardIterator>( 819 root.get(), [&visitCount](SearchTestNodeForward* aNode) { 820 aNode->SetActualTraversalRank(visitCount); 821 visitCount++; 822 return aNode->GetType() == SearchNodeType::Needle; 823 }); 824 825 for (size_t i = 0; i < nodeList.size(); i++) { 826 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 827 nodeList[i]->GetActualTraversalRank()) 828 << "Node at index " << i << " was hit out of order."; 829 } 830 831 ASSERT_EQ(foundNode.get(), nullptr) 832 << "Search found something that should not exist."; 833 } 834 835 TEST(TreeTraversal, BreadthFirstSearchValueDoesNotExistReverse) 836 { 837 int visitCount = 0; 838 std::vector<RefPtr<SearchTestNodeReverse>> nodeList; 839 nodeList.reserve(10); 840 for (int i = 0; i < 10; i++) { 841 nodeList.push_back(new SearchTestNodeReverse(SearchNodeType::Hay, i)); 842 } 843 844 RefPtr<SearchTestNodeReverse> root = nodeList[0]; 845 nodeList[0]->AddChild(nodeList[2]); 846 nodeList[0]->AddChild(nodeList[1]); 847 nodeList[1]->AddChild(nodeList[4]); 848 nodeList[1]->AddChild(nodeList[3]); 849 nodeList[2]->AddChild(nodeList[6]); 850 nodeList[2]->AddChild(nodeList[5]); 851 nodeList[6]->AddChild(nodeList[7]); 852 nodeList[7]->AddChild(nodeList[9]); 853 nodeList[7]->AddChild(nodeList[8]); 854 855 RefPtr<SearchTestNodeReverse> foundNode = 856 BreadthFirstSearch<layers::ReverseIterator>( 857 root.get(), [&visitCount](SearchTestNodeReverse* aNode) { 858 aNode->SetActualTraversalRank(visitCount); 859 visitCount++; 860 return aNode->GetType() == SearchNodeType::Needle; 861 }); 862 863 for (size_t i = 0; i < nodeList.size(); i++) { 864 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 865 nodeList[i]->GetActualTraversalRank()) 866 << "Node at index " << i << " was hit out of order."; 867 } 868 869 ASSERT_EQ(foundNode.get(), nullptr) 870 << "Search found something that should not exist."; 871 } 872 873 TEST(TreeTraversal, ForEachNodeNullStillRuns) 874 { 875 RefPtr<ForEachTestNodeReverse> nullNode; 876 ForEachNode<layers::ReverseIterator>( 877 nullNode.get(), 878 [](ForEachTestNodeReverse* aNode) { return TraversalFlag::Continue; }); 879 } 880 881 TEST(TreeTraversal, ForEachNodeAllEligible) 882 { 883 std::vector<RefPtr<ForEachTestNodeForward>> nodeList; 884 int visitCount = 0; 885 nodeList.reserve(10); 886 for (int i = 0; i < 10; i++) { 887 nodeList.push_back( 888 new ForEachTestNodeForward(ForEachNodeType::Continue, i)); 889 } 890 891 RefPtr<ForEachTestNodeForward> root = nodeList[0]; 892 nodeList[0]->AddChild(nodeList[1]); 893 nodeList[0]->AddChild(nodeList[4]); 894 nodeList[1]->AddChild(nodeList[2]); 895 nodeList[1]->AddChild(nodeList[3]); 896 nodeList[4]->AddChild(nodeList[5]); 897 nodeList[4]->AddChild(nodeList[6]); 898 nodeList[6]->AddChild(nodeList[7]); 899 nodeList[7]->AddChild(nodeList[8]); 900 nodeList[7]->AddChild(nodeList[9]); 901 902 ForEachNode<layers::ForwardIterator>( 903 root.get(), [&visitCount](ForEachTestNodeForward* aNode) { 904 aNode->SetActualTraversalRank(visitCount); 905 visitCount++; 906 return aNode->GetType() == ForEachNodeType::Continue 907 ? TraversalFlag::Continue 908 : TraversalFlag::Skip; 909 }); 910 911 for (size_t i = 0; i < nodeList.size(); i++) { 912 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 913 nodeList[i]->GetActualTraversalRank()) 914 << "Node at index " << i << " was hit out of order."; 915 } 916 } 917 918 TEST(TreeTraversal, ForEachNodeAllEligibleReverse) 919 { 920 std::vector<RefPtr<ForEachTestNodeReverse>> nodeList; 921 int visitCount = 0; 922 nodeList.reserve(10); 923 for (int i = 0; i < 10; i++) { 924 nodeList.push_back( 925 new ForEachTestNodeReverse(ForEachNodeType::Continue, i)); 926 } 927 928 RefPtr<ForEachTestNodeReverse> root = nodeList[0]; 929 nodeList[0]->AddChild(nodeList[4]); 930 nodeList[0]->AddChild(nodeList[1]); 931 nodeList[1]->AddChild(nodeList[3]); 932 nodeList[1]->AddChild(nodeList[2]); 933 nodeList[4]->AddChild(nodeList[6]); 934 nodeList[4]->AddChild(nodeList[5]); 935 nodeList[6]->AddChild(nodeList[7]); 936 nodeList[7]->AddChild(nodeList[9]); 937 nodeList[7]->AddChild(nodeList[8]); 938 939 ForEachNode<layers::ReverseIterator>( 940 root.get(), [&visitCount](ForEachTestNodeReverse* aNode) { 941 aNode->SetActualTraversalRank(visitCount); 942 visitCount++; 943 return aNode->GetType() == ForEachNodeType::Continue 944 ? TraversalFlag::Continue 945 : TraversalFlag::Skip; 946 }); 947 948 for (size_t i = 0; i < nodeList.size(); i++) { 949 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 950 nodeList[i]->GetActualTraversalRank()) 951 << "Node at index " << i << " was hit out of order."; 952 } 953 } 954 955 TEST(TreeTraversal, ForEachNodeSomeIneligibleNodes) 956 { 957 std::vector<RefPtr<ForEachTestNodeForward>> expectedVisitedNodeList; 958 std::vector<RefPtr<ForEachTestNodeForward>> expectedSkippedNodeList; 959 int visitCount = 0; 960 961 expectedVisitedNodeList.push_back( 962 new ForEachTestNodeForward(ForEachNodeType::Continue, 0)); 963 expectedVisitedNodeList.push_back( 964 new ForEachTestNodeForward(ForEachNodeType::Skip, 1)); 965 expectedVisitedNodeList.push_back( 966 new ForEachTestNodeForward(ForEachNodeType::Continue, 2)); 967 expectedVisitedNodeList.push_back( 968 new ForEachTestNodeForward(ForEachNodeType::Skip, 3)); 969 970 expectedSkippedNodeList.push_back( 971 new ForEachTestNodeForward(ForEachNodeType::Continue)); 972 expectedSkippedNodeList.push_back( 973 new ForEachTestNodeForward(ForEachNodeType::Continue)); 974 expectedSkippedNodeList.push_back( 975 new ForEachTestNodeForward(ForEachNodeType::Skip)); 976 expectedSkippedNodeList.push_back( 977 new ForEachTestNodeForward(ForEachNodeType::Skip)); 978 979 RefPtr<ForEachTestNodeForward> root = expectedVisitedNodeList[0]; 980 expectedVisitedNodeList[0]->AddChild(expectedVisitedNodeList[1]); 981 expectedVisitedNodeList[0]->AddChild(expectedVisitedNodeList[2]); 982 expectedVisitedNodeList[1]->AddChild(expectedSkippedNodeList[0]); 983 expectedVisitedNodeList[1]->AddChild(expectedSkippedNodeList[1]); 984 expectedVisitedNodeList[2]->AddChild(expectedVisitedNodeList[3]); 985 expectedVisitedNodeList[3]->AddChild(expectedSkippedNodeList[2]); 986 expectedVisitedNodeList[3]->AddChild(expectedSkippedNodeList[3]); 987 988 ForEachNode<layers::ForwardIterator>( 989 root.get(), [&visitCount](ForEachTestNodeForward* aNode) { 990 aNode->SetActualTraversalRank(visitCount); 991 visitCount++; 992 return aNode->GetType() == ForEachNodeType::Continue 993 ? TraversalFlag::Continue 994 : TraversalFlag::Skip; 995 }); 996 997 for (size_t i = 0; i < expectedVisitedNodeList.size(); i++) { 998 ASSERT_EQ(expectedVisitedNodeList[i]->GetExpectedTraversalRank(), 999 expectedVisitedNodeList[i]->GetActualTraversalRank()) 1000 << "Node at index " << i << " was hit out of order."; 1001 } 1002 1003 for (size_t i = 0; i < expectedSkippedNodeList.size(); i++) { 1004 ASSERT_EQ(expectedSkippedNodeList[i]->GetExpectedTraversalRank(), 1005 expectedSkippedNodeList[i]->GetActualTraversalRank()) 1006 << "Node at index " << i << "was not expected to be hit."; 1007 } 1008 } 1009 1010 TEST(TreeTraversal, ForEachNodeSomeIneligibleNodesReverse) 1011 { 1012 std::vector<RefPtr<ForEachTestNodeReverse>> expectedVisitedNodeList; 1013 std::vector<RefPtr<ForEachTestNodeReverse>> expectedSkippedNodeList; 1014 int visitCount = 0; 1015 1016 expectedVisitedNodeList.push_back( 1017 new ForEachTestNodeReverse(ForEachNodeType::Continue, 0)); 1018 expectedVisitedNodeList.push_back( 1019 new ForEachTestNodeReverse(ForEachNodeType::Skip, 1)); 1020 expectedVisitedNodeList.push_back( 1021 new ForEachTestNodeReverse(ForEachNodeType::Continue, 2)); 1022 expectedVisitedNodeList.push_back( 1023 new ForEachTestNodeReverse(ForEachNodeType::Skip, 3)); 1024 1025 expectedSkippedNodeList.push_back( 1026 new ForEachTestNodeReverse(ForEachNodeType::Continue)); 1027 expectedSkippedNodeList.push_back( 1028 new ForEachTestNodeReverse(ForEachNodeType::Continue)); 1029 expectedSkippedNodeList.push_back( 1030 new ForEachTestNodeReverse(ForEachNodeType::Skip)); 1031 expectedSkippedNodeList.push_back( 1032 new ForEachTestNodeReverse(ForEachNodeType::Skip)); 1033 1034 RefPtr<ForEachTestNodeReverse> root = expectedVisitedNodeList[0]; 1035 expectedVisitedNodeList[0]->AddChild(expectedVisitedNodeList[2]); 1036 expectedVisitedNodeList[0]->AddChild(expectedVisitedNodeList[1]); 1037 expectedVisitedNodeList[1]->AddChild(expectedSkippedNodeList[1]); 1038 expectedVisitedNodeList[1]->AddChild(expectedSkippedNodeList[0]); 1039 expectedVisitedNodeList[2]->AddChild(expectedVisitedNodeList[3]); 1040 expectedVisitedNodeList[3]->AddChild(expectedSkippedNodeList[3]); 1041 expectedVisitedNodeList[3]->AddChild(expectedSkippedNodeList[2]); 1042 1043 ForEachNode<layers::ReverseIterator>( 1044 root.get(), [&visitCount](ForEachTestNodeReverse* aNode) { 1045 aNode->SetActualTraversalRank(visitCount); 1046 visitCount++; 1047 return aNode->GetType() == ForEachNodeType::Continue 1048 ? TraversalFlag::Continue 1049 : TraversalFlag::Skip; 1050 }); 1051 1052 for (size_t i = 0; i < expectedVisitedNodeList.size(); i++) { 1053 ASSERT_EQ(expectedVisitedNodeList[i]->GetExpectedTraversalRank(), 1054 expectedVisitedNodeList[i]->GetActualTraversalRank()) 1055 << "Node at index " << i << " was hit out of order."; 1056 } 1057 1058 for (size_t i = 0; i < expectedSkippedNodeList.size(); i++) { 1059 ASSERT_EQ(expectedSkippedNodeList[i]->GetExpectedTraversalRank(), 1060 expectedSkippedNodeList[i]->GetActualTraversalRank()) 1061 << "Node at index " << i << "was not expected to be hit."; 1062 } 1063 } 1064 1065 TEST(TreeTraversal, ForEachNodeIneligibleRoot) 1066 { 1067 int visitCount = 0; 1068 1069 RefPtr<ForEachTestNodeReverse> root = 1070 new ForEachTestNodeReverse(ForEachNodeType::Skip, 0); 1071 RefPtr<ForEachTestNodeReverse> childNode1 = 1072 new ForEachTestNodeReverse(ForEachNodeType::Continue); 1073 RefPtr<ForEachTestNodeReverse> chlidNode2 = 1074 new ForEachTestNodeReverse(ForEachNodeType::Skip); 1075 1076 ForEachNode<layers::ReverseIterator>( 1077 root.get(), [&visitCount](ForEachTestNodeReverse* aNode) { 1078 aNode->SetActualTraversalRank(visitCount); 1079 visitCount++; 1080 return aNode->GetType() == ForEachNodeType::Continue 1081 ? TraversalFlag::Continue 1082 : TraversalFlag::Skip; 1083 }); 1084 1085 ASSERT_EQ(root->GetExpectedTraversalRank(), root->GetActualTraversalRank()) 1086 << "Root was hit out of order."; 1087 ASSERT_EQ(childNode1->GetExpectedTraversalRank(), 1088 childNode1->GetActualTraversalRank()) 1089 << "Eligible child was still hit."; 1090 ASSERT_EQ(chlidNode2->GetExpectedTraversalRank(), 1091 chlidNode2->GetActualTraversalRank()) 1092 << "Ineligible child was still hit."; 1093 } 1094 1095 TEST(TreeTraversal, ForEachNodeLeavesIneligible) 1096 { 1097 std::vector<RefPtr<ForEachTestNodeForward>> nodeList; 1098 nodeList.reserve(10); 1099 int visitCount = 0; 1100 for (int i = 0; i < 10; i++) { 1101 if (i == 1 || i == 9) { 1102 nodeList.push_back(new ForEachTestNodeForward(ForEachNodeType::Skip, i)); 1103 } else { 1104 nodeList.push_back( 1105 new ForEachTestNodeForward(ForEachNodeType::Continue, i)); 1106 } 1107 } 1108 1109 RefPtr<ForEachTestNodeForward> root = nodeList[0]; 1110 nodeList[0]->AddChild(nodeList[1]); 1111 nodeList[0]->AddChild(nodeList[2]); 1112 nodeList[2]->AddChild(nodeList[3]); 1113 nodeList[2]->AddChild(nodeList[4]); 1114 nodeList[4]->AddChild(nodeList[5]); 1115 nodeList[4]->AddChild(nodeList[6]); 1116 nodeList[6]->AddChild(nodeList[7]); 1117 nodeList[7]->AddChild(nodeList[8]); 1118 nodeList[7]->AddChild(nodeList[9]); 1119 1120 ForEachNode<layers::ForwardIterator>( 1121 root.get(), [&visitCount](ForEachTestNodeForward* aNode) { 1122 aNode->SetActualTraversalRank(visitCount); 1123 visitCount++; 1124 return aNode->GetType() == ForEachNodeType::Continue 1125 ? TraversalFlag::Continue 1126 : TraversalFlag::Skip; 1127 }); 1128 1129 for (size_t i = 0; i < nodeList.size(); i++) { 1130 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 1131 nodeList[i]->GetActualTraversalRank()) 1132 << "Node at index " << i << " was hit out of order."; 1133 } 1134 } 1135 1136 TEST(TreeTraversal, ForEachNodeLeavesIneligibleReverse) 1137 { 1138 std::vector<RefPtr<ForEachTestNodeReverse>> nodeList; 1139 nodeList.reserve(10); 1140 int visitCount = 0; 1141 for (int i = 0; i < 10; i++) { 1142 if (i == 1 || i == 9) { 1143 nodeList.push_back(new ForEachTestNodeReverse(ForEachNodeType::Skip, i)); 1144 } else { 1145 nodeList.push_back( 1146 new ForEachTestNodeReverse(ForEachNodeType::Continue, i)); 1147 } 1148 } 1149 1150 RefPtr<ForEachTestNodeReverse> root = nodeList[0]; 1151 nodeList[0]->AddChild(nodeList[2]); 1152 nodeList[0]->AddChild(nodeList[1]); 1153 nodeList[2]->AddChild(nodeList[4]); 1154 nodeList[2]->AddChild(nodeList[3]); 1155 nodeList[4]->AddChild(nodeList[6]); 1156 nodeList[4]->AddChild(nodeList[5]); 1157 nodeList[6]->AddChild(nodeList[7]); 1158 nodeList[7]->AddChild(nodeList[9]); 1159 nodeList[7]->AddChild(nodeList[8]); 1160 1161 ForEachNode<layers::ReverseIterator>( 1162 root.get(), [&visitCount](ForEachTestNodeReverse* aNode) { 1163 aNode->SetActualTraversalRank(visitCount); 1164 visitCount++; 1165 return aNode->GetType() == ForEachNodeType::Continue 1166 ? TraversalFlag::Continue 1167 : TraversalFlag::Skip; 1168 }); 1169 1170 for (size_t i = 0; i < nodeList.size(); i++) { 1171 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 1172 nodeList[i]->GetActualTraversalRank()) 1173 << "Node at index " << i << " was hit out of order."; 1174 } 1175 } 1176 1177 TEST(TreeTraversal, ForEachNodeLambdaReturnsVoid) 1178 { 1179 std::vector<RefPtr<ForEachTestNodeReverse>> nodeList; 1180 nodeList.reserve(10); 1181 int visitCount = 0; 1182 for (int i = 0; i < 10; i++) { 1183 nodeList.push_back( 1184 new ForEachTestNodeReverse(ForEachNodeType::Continue, i)); 1185 } 1186 1187 RefPtr<ForEachTestNodeReverse> root = nodeList[0]; 1188 nodeList[0]->AddChild(nodeList[4]); 1189 nodeList[0]->AddChild(nodeList[1]); 1190 nodeList[1]->AddChild(nodeList[3]); 1191 nodeList[1]->AddChild(nodeList[2]); 1192 nodeList[4]->AddChild(nodeList[6]); 1193 nodeList[4]->AddChild(nodeList[5]); 1194 nodeList[6]->AddChild(nodeList[7]); 1195 nodeList[7]->AddChild(nodeList[9]); 1196 nodeList[7]->AddChild(nodeList[8]); 1197 1198 ForEachNode<layers::ReverseIterator>( 1199 root.get(), [&visitCount](ForEachTestNodeReverse* aNode) { 1200 aNode->SetActualTraversalRank(visitCount); 1201 visitCount++; 1202 }); 1203 1204 for (size_t i = 0; i < nodeList.size(); i++) { 1205 ASSERT_EQ(nodeList[i]->GetExpectedTraversalRank(), 1206 nodeList[i]->GetActualTraversalRank()) 1207 << "Node at index " << i << " was hit out of order."; 1208 } 1209 } 1210 1211 struct AssignSearchNodeTypesWithLastLeafAsNeedle { 1212 RefPtr<SearchTestNodeForward>& node; 1213 void operator()(SearchTestNodeForward* aNode) { 1214 aNode->SetType(SearchNodeType::Hay); 1215 if (aNode->IsLeaf()) { 1216 node = aNode; 1217 } 1218 } 1219 }; 1220 1221 struct AssignSearchNodeTypesAllHay { 1222 void operator()(SearchTestNode* aNode) { 1223 aNode->SetType(SearchNodeType::Hay); 1224 } 1225 }; 1226 1227 struct AssignSearchNodeTypesWithFirstLeafAsNeedle { 1228 RefPtr<SearchTestNodeReverse>& needleNode; 1229 void operator()(SearchTestNodeReverse* aNode) { 1230 if (!needleNode && aNode->IsLeaf()) { 1231 needleNode = aNode; 1232 } 1233 aNode->SetType(SearchNodeType::Hay); 1234 } 1235 }; 1236 1237 struct AssignSearchNodeValuesAllFalseValuesReverse { 1238 int falseValue; 1239 RefPtr<SearchTestNodeReverse>& needleNode; 1240 void operator()(SearchTestNodeReverse* aNode) { 1241 aNode->SetValue(falseValue); 1242 if (!needleNode && aNode->IsLeaf()) { 1243 needleNode = aNode; 1244 } 1245 } 1246 }; 1247 1248 struct AssignSearchNodeValuesAllFalseValuesForward { 1249 int falseValue; 1250 RefPtr<SearchTestNodeForward>& needleNode; 1251 void operator()(SearchTestNodeForward* aNode) { 1252 aNode->SetValue(falseValue); 1253 needleNode = aNode; 1254 } 1255 }; 1256 1257 struct AllocateUnitRegionsToLeavesOnly { 1258 int& xWrap; 1259 int& squareCount; 1260 void operator()(ForEachTestNode* aNode) { 1261 if (aNode->IsLeaf()) { 1262 int x = squareCount % xWrap; 1263 int y = squareCount / xWrap; 1264 aNode->SetRegion(nsRegion(nsRect(x, y, 1, 1))); 1265 squareCount++; 1266 } 1267 } 1268 }; 1269 1270 template <typename Node> 1271 static RefPtr<Node> DepthFirstSearchForwardRecursive(RefPtr<Node> aNode) { 1272 if (aNode->GetType() == SearchNodeType::Needle) { 1273 return aNode; 1274 } 1275 for (RefPtr<Node> node = aNode->GetFirstChild(); node != nullptr; 1276 node = node->GetNextSibling()) { 1277 if (RefPtr<Node> foundNode = DepthFirstSearchForwardRecursive(node)) { 1278 return foundNode; 1279 } 1280 } 1281 return nullptr; 1282 } 1283 1284 template <typename Node> 1285 static RefPtr<Node> DepthFirstSearchCaptureVariablesForwardRecursive( 1286 RefPtr<Node> aNode, int a, int b, int c, int d, int e, int f, int g, int h, 1287 int i, int j, int k, int l, int m, int& n, int& o, int& p, int& q, int& r, 1288 int& s, int& t, int& u, int& v, int& w, int& x, int& y, int& z) { 1289 if (aNode->GetValue() == a + b + c + d + e + f + g + h + i + j + k + l + m + 1290 n + o + p + q + r + s + t + u + v + w + x + y + 1291 z) { 1292 return aNode; 1293 } 1294 for (RefPtr<Node> node = aNode->GetFirstChild(); node != nullptr; 1295 node = node->GetNextSibling()) { 1296 if (RefPtr<Node> foundNode = 1297 DepthFirstSearchCaptureVariablesForwardRecursive( 1298 node, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, 1299 t, u, v, w, x, y, z)) { 1300 return foundNode; 1301 } 1302 } 1303 return nullptr; 1304 } 1305 1306 template <typename Node> 1307 static RefPtr<Node> DepthFirstSearchPostOrderForwardRecursive( 1308 RefPtr<Node> aNode) { 1309 for (RefPtr<Node> node = aNode->GetFirstChild(); node != nullptr; 1310 node = node->GetNextSibling()) { 1311 if (RefPtr<Node> foundNode = 1312 DepthFirstSearchPostOrderForwardRecursive(node)) { 1313 return foundNode; 1314 } 1315 } 1316 if (aNode->GetType() == SearchNodeType::Needle) { 1317 return aNode; 1318 } 1319 return nullptr; 1320 } 1321 1322 template <typename Node> 1323 static RefPtr<Node> BreadthFirstSearchForwardQueue(RefPtr<Node> aNode) { 1324 std::queue<RefPtr<Node>> nodes; 1325 nodes.push(aNode); 1326 while (!nodes.empty()) { 1327 RefPtr<Node> node = nodes.front(); 1328 nodes.pop(); 1329 if (node->GetType() == SearchNodeType::Needle) { 1330 return node; 1331 } 1332 for (RefPtr<Node> childNode = node->GetFirstChild(); childNode != nullptr; 1333 childNode = childNode->GetNextSibling()) { 1334 nodes.push(childNode); 1335 } 1336 } 1337 return nullptr; 1338 } 1339 1340 template <typename Node> 1341 static RefPtr<Node> DepthFirstSearchReverseRecursive(RefPtr<Node> aNode) { 1342 if (aNode->GetType() == SearchNodeType::Needle) { 1343 return aNode; 1344 } 1345 for (RefPtr<Node> node = aNode->GetLastChild(); node != nullptr; 1346 node = node->GetPrevSibling()) { 1347 if (RefPtr<Node> foundNode = DepthFirstSearchReverseRecursive(node)) { 1348 return foundNode; 1349 } 1350 } 1351 return nullptr; 1352 } 1353 1354 template <typename Node> 1355 static RefPtr<Node> DepthFirstSearchCaptureVariablesReverseRecursive( 1356 RefPtr<Node> aNode, int a, int b, int c, int d, int e, int f, int g, int h, 1357 int i, int j, int k, int l, int m, int& n, int& o, int& p, int& q, int& r, 1358 int& s, int& t, int& u, int& v, int& w, int& x, int& y, int& z) { 1359 if (aNode->GetValue() == a + b + c + d + e + f + g + h + i + j + k + l + m + 1360 n + o + p + q + r + s + t + u + v + w + x + y + 1361 z) { 1362 return aNode; 1363 } 1364 for (RefPtr<Node> node = aNode->GetLastChild(); node != nullptr; 1365 node = node->GetPrevSibling()) { 1366 if (RefPtr<Node> foundNode = 1367 DepthFirstSearchCaptureVariablesReverseRecursive( 1368 node, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, 1369 t, u, v, w, x, y, z)) { 1370 return foundNode; 1371 } 1372 } 1373 return nullptr; 1374 } 1375 1376 template <typename Node> 1377 static RefPtr<Node> DepthFirstSearchPostOrderReverseRecursive( 1378 RefPtr<Node> aNode) { 1379 for (RefPtr<Node> node = aNode->GetLastChild(); node != nullptr; 1380 node = node->GetPrevSibling()) { 1381 if (RefPtr<Node> foundNode = 1382 DepthFirstSearchPostOrderReverseRecursive(node)) { 1383 return foundNode; 1384 } 1385 } 1386 if (aNode->GetType() == SearchNodeType::Needle) { 1387 return aNode; 1388 } 1389 return nullptr; 1390 } 1391 1392 template <typename Node> 1393 static RefPtr<Node> BreadthFirstSearchReverseQueue(RefPtr<Node> aNode) { 1394 std::queue<RefPtr<Node>> nodes; 1395 nodes.push(aNode); 1396 while (!nodes.empty()) { 1397 RefPtr<Node> node = nodes.front(); 1398 nodes.pop(); 1399 if (node->GetType() == SearchNodeType::Needle) { 1400 return node; 1401 } 1402 for (RefPtr<Node> childNode = node->GetLastChild(); childNode != nullptr; 1403 childNode = childNode->GetPrevSibling()) { 1404 nodes.push(childNode); 1405 } 1406 } 1407 return nullptr; 1408 }