| Index: cc/quads/list_container_unittest.cc
|
| diff --git a/cc/quads/list_container_unittest.cc b/cc/quads/list_container_unittest.cc
|
| index 76dd966b16a39efad8fbd735f66baecd3a7f82d9..ab7f6ea80754f4be839bd6732ec53daa64e8cafe 100644
|
| --- a/cc/quads/list_container_unittest.cc
|
| +++ b/cc/quads/list_container_unittest.cc
|
| @@ -650,5 +650,117 @@ TEST(ListContainerTest,
|
| }
|
| }
|
|
|
| +// Increments an int when constructed (or the counter pointer is supplied) and
|
| +// decrements when destructed.
|
| +class InstanceCounter {
|
| + public:
|
| + InstanceCounter() : counter_(nullptr) {}
|
| + explicit InstanceCounter(int* counter) { SetCounter(counter); }
|
| + ~InstanceCounter() {
|
| + if (counter_)
|
| + --*counter_;
|
| + }
|
| + void SetCounter(int* counter) {
|
| + counter_ = counter;
|
| + ++*counter_;
|
| + }
|
| +
|
| + private:
|
| + int* counter_;
|
| +};
|
| +
|
| +TEST(ListContainerTest, RemoveLastDestruction) {
|
| + // We keep an explicit instance count to make sure that the destructors are
|
| + // indeed getting called.
|
| + int counter = 0;
|
| + ListContainer<InstanceCounter> list(sizeof(InstanceCounter), 1);
|
| + EXPECT_EQ(0, counter);
|
| + EXPECT_EQ(0u, list.size());
|
| +
|
| + // We should be okay to add one and then go back to zero.
|
| + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter);
|
| + EXPECT_EQ(1, counter);
|
| + EXPECT_EQ(1u, list.size());
|
| + list.RemoveLast();
|
| + EXPECT_EQ(0, counter);
|
| + EXPECT_EQ(0u, list.size());
|
| +
|
| + // We should also be okay to remove the last multiple times, as long as there
|
| + // are enough elements in the first place.
|
| + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter);
|
| + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter);
|
| + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter);
|
| + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter);
|
| + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter);
|
| + list.AllocateAndConstruct<InstanceCounter>()->SetCounter(&counter);
|
| + list.RemoveLast();
|
| + list.RemoveLast();
|
| + EXPECT_EQ(4, counter); // Leaves one in the last list.
|
| + EXPECT_EQ(4u, list.size());
|
| + list.RemoveLast();
|
| + EXPECT_EQ(3, counter); // Removes an inner list from before.
|
| + EXPECT_EQ(3u, list.size());
|
| +}
|
| +
|
| +// TODO(jbroman): std::equal would work if ListContainer iterators satisfied the
|
| +// usual STL iterator constraints. We should fix that.
|
| +template <typename It1, typename It2>
|
| +bool Equal(It1 it1, const It1& end1, It2 it2) {
|
| + for (; it1 != end1; ++it1, ++it2) {
|
| + if (!(*it1 == *it2))
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +TEST(ListContainerTest, RemoveLastIteration) {
|
| + struct SmallStruct {
|
| + char dummy[16];
|
| + };
|
| + ListContainer<SmallStruct> list(sizeof(SmallStruct), 1);
|
| + std::vector<SmallStruct*> pointers;
|
| +
|
| + // Utilities which keep these two lists in sync and check that their iteration
|
| + // order matches.
|
| + auto push = [&list, &pointers]() {
|
| + pointers.push_back(list.AllocateAndConstruct<SmallStruct>());
|
| + };
|
| + auto pop = [&list, &pointers]() {
|
| + pointers.pop_back();
|
| + list.RemoveLast();
|
| + };
|
| + auto check_equal = [&list, &pointers]() {
|
| + // They should be of the same size, and compare equal with all four kinds of
|
| + // iteration.
|
| + // Apparently Mac doesn't have vector::cbegin and vector::crbegin?
|
| + const auto& const_pointers = pointers;
|
| + ASSERT_EQ(list.size(), pointers.size());
|
| + ASSERT_TRUE(Equal(list.begin(), list.end(), pointers.begin()));
|
| + ASSERT_TRUE(Equal(list.cbegin(), list.cend(), const_pointers.begin()));
|
| + ASSERT_TRUE(Equal(list.rbegin(), list.rend(), pointers.rbegin()));
|
| + ASSERT_TRUE(Equal(list.crbegin(), list.crend(), const_pointers.rbegin()));
|
| + };
|
| +
|
| + check_equal(); // Initially empty.
|
| + push();
|
| + check_equal(); // One full inner list.
|
| + push();
|
| + check_equal(); // One full, one partially full.
|
| + push();
|
| + push();
|
| + check_equal(); // Two full, one partially full.
|
| + pop();
|
| + check_equal(); // Two full, one empty.
|
| + pop();
|
| + check_equal(); // One full, one partially full, one empty.
|
| + pop();
|
| + check_equal(); // One full, one empty.
|
| + push();
|
| + pop();
|
| + pop();
|
| + ASSERT_TRUE(list.empty());
|
| + check_equal(); // Empty.
|
| +}
|
| +
|
| } // namespace
|
| } // namespace cc
|
|
|