OLD | NEW |
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 "cc/base/list_container.h" | 5 #include "cc/base/list_container.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 #include "cc/quads/draw_quad.h" | 8 #include "cc/quads/draw_quad.h" |
9 #include "cc/quads/largest_draw_quad.h" | 9 #include "cc/quads/largest_draw_quad.h" |
10 #include "cc/quads/render_pass_draw_quad.h" | 10 #include "cc/quads/render_pass_draw_quad.h" |
(...skipping 632 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
643 } | 643 } |
644 | 644 |
645 i = 0; | 645 i = 0; |
646 for (ListContainer<SharedQuadState>::ReverseIterator iter = list.rbegin(); | 646 for (ListContainer<SharedQuadState>::ReverseIterator iter = list.rbegin(); |
647 iter != list.rend(); ++iter) { | 647 iter != list.rend(); ++iter) { |
648 EXPECT_EQ(i, iter.index()); | 648 EXPECT_EQ(i, iter.index()); |
649 ++i; | 649 ++i; |
650 } | 650 } |
651 } | 651 } |
652 | 652 |
| 653 // Increments an int when constructed (or the counter pointer is supplied) and |
| 654 // decrements when destructed. |
| 655 class InstanceCounter { |
| 656 public: |
| 657 InstanceCounter() : counter_(nullptr) {} |
| 658 explicit InstanceCounter(int* counter) { SetCounter(counter); } |
| 659 ~InstanceCounter() { |
| 660 if (counter_) |
| 661 --*counter_; |
| 662 } |
| 663 void SetCounter(int* counter) { |
| 664 counter_ = counter; |
| 665 ++*counter_; |
| 666 } |
| 667 |
| 668 private: |
| 669 int* counter_; |
| 670 }; |
| 671 |
| 672 TEST(ListContainerTest, RemoveLastDestruction) { |
| 673 // We keep an explicit instance count to make sure that the destructors are |
| 674 // indeed getting called. |
| 675 int counter = 0; |
| 676 ListContainer<InstanceCounter> list(sizeof(InstanceCounter), 1); |
| 677 EXPECT_EQ(0, counter); |
| 678 EXPECT_EQ(0u, list.size()); |
| 679 |
| 680 // We should be okay to add one and then go back to zero. |
| 681 list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); |
| 682 EXPECT_EQ(1, counter); |
| 683 EXPECT_EQ(1u, list.size()); |
| 684 list.RemoveLast(); |
| 685 EXPECT_EQ(0, counter); |
| 686 EXPECT_EQ(0u, list.size()); |
| 687 |
| 688 // We should also be okay to remove the last multiple times, as long as there |
| 689 // are enough elements in the first place. |
| 690 list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); |
| 691 list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); |
| 692 list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); |
| 693 list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); |
| 694 list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); |
| 695 list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter); |
| 696 list.RemoveLast(); |
| 697 list.RemoveLast(); |
| 698 EXPECT_EQ(4, counter); // Leaves one in the last list. |
| 699 EXPECT_EQ(4u, list.size()); |
| 700 list.RemoveLast(); |
| 701 EXPECT_EQ(3, counter); // Removes an inner list from before. |
| 702 EXPECT_EQ(3u, list.size()); |
| 703 } |
| 704 |
| 705 // TODO(jbroman): std::equal would work if ListContainer iterators satisfied the |
| 706 // usual STL iterator constraints. We should fix that. |
| 707 template <typename It1, typename It2> |
| 708 bool Equal(It1 it1, const It1& end1, It2 it2) { |
| 709 for (; it1 != end1; ++it1, ++it2) { |
| 710 if (!(*it1 == *it2)) |
| 711 return false; |
| 712 } |
| 713 return true; |
| 714 } |
| 715 |
| 716 TEST(ListContainerTest, RemoveLastIteration) { |
| 717 struct SmallStruct { |
| 718 char dummy[16]; |
| 719 }; |
| 720 ListContainer<SmallStruct> list(sizeof(SmallStruct), 1); |
| 721 std::vector<SmallStruct*> pointers; |
| 722 |
| 723 // Utilities which keep these two lists in sync and check that their iteration |
| 724 // order matches. |
| 725 auto push = [&list, &pointers]() { |
| 726 pointers.push_back(list.AllocateAndConstruct<SmallStruct>()); |
| 727 }; |
| 728 auto pop = [&list, &pointers]() { |
| 729 pointers.pop_back(); |
| 730 list.RemoveLast(); |
| 731 }; |
| 732 auto check_equal = [&list, &pointers]() { |
| 733 // They should be of the same size, and compare equal with all four kinds of |
| 734 // iteration. |
| 735 // Apparently Mac doesn't have vector::cbegin and vector::crbegin? |
| 736 const auto& const_pointers = pointers; |
| 737 ASSERT_EQ(list.size(), pointers.size()); |
| 738 ASSERT_TRUE(Equal(list.begin(), list.end(), pointers.begin())); |
| 739 ASSERT_TRUE(Equal(list.cbegin(), list.cend(), const_pointers.begin())); |
| 740 ASSERT_TRUE(Equal(list.rbegin(), list.rend(), pointers.rbegin())); |
| 741 ASSERT_TRUE(Equal(list.crbegin(), list.crend(), const_pointers.rbegin())); |
| 742 }; |
| 743 |
| 744 check_equal(); // Initially empty. |
| 745 push(); |
| 746 check_equal(); // One full inner list. |
| 747 push(); |
| 748 check_equal(); // One full, one partially full. |
| 749 push(); |
| 750 push(); |
| 751 check_equal(); // Two full, one partially full. |
| 752 pop(); |
| 753 check_equal(); // Two full, one empty. |
| 754 pop(); |
| 755 check_equal(); // One full, one partially full, one empty. |
| 756 pop(); |
| 757 check_equal(); // One full, one empty. |
| 758 push(); |
| 759 pop(); |
| 760 pop(); |
| 761 ASSERT_TRUE(list.empty()); |
| 762 check_equal(); // Empty. |
| 763 } |
| 764 |
653 } // namespace | 765 } // namespace |
654 } // namespace cc | 766 } // namespace cc |
OLD | NEW |