[go: nahoru, domu]

cc: Move list_container_unittest.cc to cc/base/.

This CL takes care of moving unittest file to cc/base. The
ListContainer class now gets tested using dummy classes of following
types -

1. DerivedElement - This has classes derived from it. This tests
classes created using ListContainer(size_t max_size_for_derived_class)
constructor.

2. NonDerivedElement - This does not have any classes derived from it.
This tests classes created using ListContainer() constructor.

BUG=492952
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel

Review URL: https://codereview.chromium.org/1165653002

Cr-Commit-Position: refs/heads/master@{#333095}
diff --git a/cc/BUILD.gn b/cc/BUILD.gn
index 58540a9..3c89a02 100644
--- a/cc/BUILD.gn
+++ b/cc/BUILD.gn
@@ -772,6 +772,7 @@
     "animation/transform_operations_unittest.cc",
     "base/float_quad_unittest.cc",
     "base/histograms_unittest.cc",
+    "base/list_container_unittest.cc",
     "base/math_util_unittest.cc",
     "base/region_unittest.cc",
     "base/rolling_time_delta_history_unittest.cc",
@@ -837,7 +838,6 @@
     "playback/pixel_ref_map_unittest.cc",
     "playback/recording_source_unittest.cc",
     "quads/draw_quad_unittest.cc",
-    "quads/list_container_unittest.cc",
     "quads/render_pass_unittest.cc",
     "raster/scoped_gpu_raster_unittest.cc",
     "raster/task_graph_runner_unittest.cc",
diff --git a/cc/base/list_container_unittest.cc b/cc/base/list_container_unittest.cc
new file mode 100644
index 0000000..cfe593b
--- /dev/null
+++ b/cc/base/list_container_unittest.cc
@@ -0,0 +1,712 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/base/list_container.h"
+
+#include <vector>
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+// Element class having derived classes.
+class DerivedElement {
+ public:
+  virtual ~DerivedElement() {}
+
+ protected:
+  bool bool_values[1];
+  char char_values[1];
+  int int_values[1];
+  long long_values[1];
+};
+
+class DerivedElement1 : public DerivedElement {
+ protected:
+  bool bool_values1[1];
+  char char_values1[1];
+  int int_values1[1];
+  long long_values1[1];
+};
+
+class DerivedElement2 : public DerivedElement {
+ protected:
+  bool bool_values2[2];
+  char char_values2[2];
+  int int_values2[2];
+  long long_values2[2];
+};
+
+class DerivedElement3 : public DerivedElement {
+ protected:
+  bool bool_values3[3];
+  char char_values3[3];
+  int int_values3[3];
+  long long_values3[3];
+};
+
+const size_t kLargestDerivedElementSize = sizeof(DerivedElement3);
+
+size_t LargestDerivedElementSize() {
+  static_assert(sizeof(DerivedElement1) <= kLargestDerivedElementSize,
+                "Largest Derived Element size needs update. DerivedElement1 is "
+                "currently largest.");
+  static_assert(sizeof(DerivedElement2) <= kLargestDerivedElementSize,
+                "Largest Derived Element size needs update. DerivedElement2 is "
+                "currently largest.");
+
+  return kLargestDerivedElementSize;
+}
+
+// Element class having no derived classes.
+class NonDerivedElement {
+ public:
+  NonDerivedElement() {}
+  ~NonDerivedElement() {}
+
+  int int_values[1];
+};
+
+bool isConstNonDerivedElementPointer(const NonDerivedElement* ptr) {
+  return true;
+}
+
+bool isConstNonDerivedElementPointer(NonDerivedElement* ptr) {
+  return false;
+}
+
+const int kMagicNumberToUseForSimpleDerivedElementOne = 42;
+const int kMagicNumberToUseForSimpleDerivedElementTwo = 314;
+
+class SimpleDerivedElement : public DerivedElement {
+ public:
+  ~SimpleDerivedElement() override {}
+  void set_value(int val) { value = val; }
+  int get_value() { return value; }
+
+ private:
+  int value;
+};
+
+class SimpleDerivedElementConstructMagicNumberOne
+    : public SimpleDerivedElement {
+ public:
+  SimpleDerivedElementConstructMagicNumberOne() : SimpleDerivedElement() {
+    set_value(kMagicNumberToUseForSimpleDerivedElementOne);
+  }
+};
+
+class SimpleDerivedElementConstructMagicNumberTwo
+    : public SimpleDerivedElement {
+ public:
+  SimpleDerivedElementConstructMagicNumberTwo() : SimpleDerivedElement() {
+    set_value(kMagicNumberToUseForSimpleDerivedElementTwo);
+  }
+};
+
+class MockDerivedElement : public SimpleDerivedElementConstructMagicNumberOne {
+ public:
+  ~MockDerivedElement() override { Destruct(); }
+  MOCK_METHOD0(Destruct, void());
+};
+
+class MockDerivedElementSubclass : public MockDerivedElement {
+ public:
+  MockDerivedElementSubclass() {
+    set_value(kMagicNumberToUseForSimpleDerivedElementTwo);
+  }
+};
+
+const size_t kCurrentLargestDerivedElementSize =
+    std::max(LargestDerivedElementSize(), sizeof(MockDerivedElementSubclass));
+
+TEST(ListContainerTest, ConstructorCalledInAllocateAndConstruct) {
+  ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+
+  size_t size = 2;
+  SimpleDerivedElementConstructMagicNumberOne* de_1 =
+      list.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberOne>();
+  SimpleDerivedElementConstructMagicNumberTwo* de_2 =
+      list.AllocateAndConstruct<SimpleDerivedElementConstructMagicNumberTwo>();
+
+  EXPECT_EQ(size, list.size());
+  EXPECT_EQ(de_1, list.front());
+  EXPECT_EQ(de_2, list.back());
+
+  EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementOne, de_1->get_value());
+  EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, de_2->get_value());
+}
+
+TEST(ListContainerTest, DestructorCalled) {
+  ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+
+  size_t size = 1;
+  MockDerivedElement* de_1 = list.AllocateAndConstruct<MockDerivedElement>();
+
+  EXPECT_CALL(*de_1, Destruct());
+  EXPECT_EQ(size, list.size());
+  EXPECT_EQ(de_1, list.front());
+}
+
+TEST(ListContainerTest, DestructorCalledOnceWhenClear) {
+  ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+  size_t size = 1;
+  MockDerivedElement* de_1 = list.AllocateAndConstruct<MockDerivedElement>();
+
+  EXPECT_EQ(size, list.size());
+  EXPECT_EQ(de_1, list.front());
+
+  // Make sure destructor is called once during clear, and won't be called
+  // again.
+  testing::MockFunction<void()> separator;
+  {
+    testing::InSequence s;
+    EXPECT_CALL(*de_1, Destruct());
+    EXPECT_CALL(separator, Call());
+    EXPECT_CALL(*de_1, Destruct()).Times(0);
+  }
+
+  list.clear();
+  separator.Call();
+}
+
+TEST(ListContainerTest, ReplaceExistingElement) {
+  ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+  size_t size = 1;
+  MockDerivedElement* de_1 = list.AllocateAndConstruct<MockDerivedElement>();
+
+  EXPECT_EQ(size, list.size());
+  EXPECT_EQ(de_1, list.front());
+
+  // Make sure destructor is called once during clear, and won't be called
+  // again.
+  testing::MockFunction<void()> separator;
+  {
+    testing::InSequence s;
+    EXPECT_CALL(*de_1, Destruct());
+    EXPECT_CALL(separator, Call());
+    EXPECT_CALL(*de_1, Destruct()).Times(0);
+  }
+
+  list.ReplaceExistingElement<MockDerivedElementSubclass>(list.begin());
+  EXPECT_EQ(kMagicNumberToUseForSimpleDerivedElementTwo, de_1->get_value());
+  separator.Call();
+
+  EXPECT_CALL(*de_1, Destruct());
+  list.clear();
+}
+
+TEST(ListContainerTest, DestructorCalledOnceWhenErase) {
+  ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+  size_t size = 1;
+  MockDerivedElement* de_1 = list.AllocateAndConstruct<MockDerivedElement>();
+
+  EXPECT_EQ(size, list.size());
+  EXPECT_EQ(de_1, list.front());
+
+  // Make sure destructor is called once during clear, and won't be called
+  // again.
+  testing::MockFunction<void()> separator;
+  {
+    testing::InSequence s;
+    EXPECT_CALL(*de_1, Destruct());
+    EXPECT_CALL(separator, Call());
+    EXPECT_CALL(*de_1, Destruct()).Times(0);
+  }
+
+  list.EraseAndInvalidateAllPointers(list.begin());
+  separator.Call();
+}
+
+TEST(ListContainerTest, SimpleIndexAccessNonDerivedElement) {
+  ListContainer<NonDerivedElement> list;
+
+  size_t size = 3;
+  NonDerivedElement* nde_1 = list.AllocateAndConstruct<NonDerivedElement>();
+  NonDerivedElement* nde_2 = list.AllocateAndConstruct<NonDerivedElement>();
+  NonDerivedElement* nde_3 = list.AllocateAndConstruct<NonDerivedElement>();
+
+  EXPECT_EQ(size, list.size());
+  EXPECT_EQ(nde_1, list.front());
+  EXPECT_EQ(nde_3, list.back());
+  EXPECT_EQ(list.front(), list.ElementAt(0));
+  EXPECT_EQ(nde_2, list.ElementAt(1));
+  EXPECT_EQ(list.back(), list.ElementAt(2));
+}
+
+TEST(ListContainerTest, SimpleInsertionNonDerivedElement) {
+  ListContainer<NonDerivedElement> list;
+
+  size_t size = 3;
+  NonDerivedElement* nde_1 = list.AllocateAndConstruct<NonDerivedElement>();
+  list.AllocateAndConstruct<NonDerivedElement>();
+  NonDerivedElement* nde_3 = list.AllocateAndConstruct<NonDerivedElement>();
+
+  EXPECT_EQ(size, list.size());
+  EXPECT_EQ(nde_1, list.front());
+  EXPECT_EQ(nde_3, list.back());
+}
+
+TEST(ListContainerTest, SimpleInsertionAndClearNonDerivedElement) {
+  ListContainer<NonDerivedElement> list;
+  EXPECT_TRUE(list.empty());
+  EXPECT_EQ(0u, list.size());
+
+  size_t size = 3;
+  NonDerivedElement* nde_1 = list.AllocateAndConstruct<NonDerivedElement>();
+  list.AllocateAndConstruct<NonDerivedElement>();
+  NonDerivedElement* nde_3 = list.AllocateAndConstruct<NonDerivedElement>();
+
+  EXPECT_EQ(size, list.size());
+  EXPECT_EQ(nde_1, list.front());
+  EXPECT_EQ(nde_3, list.back());
+  EXPECT_FALSE(list.empty());
+
+  list.clear();
+  EXPECT_TRUE(list.empty());
+  EXPECT_EQ(0u, list.size());
+}
+
+TEST(ListContainerTest, SimpleInsertionClearAndInsertAgainNonDerivedElement) {
+  ListContainer<NonDerivedElement> list;
+  EXPECT_TRUE(list.empty());
+  EXPECT_EQ(0u, list.size());
+
+  size_t size = 2;
+  NonDerivedElement* nde_front = list.AllocateAndConstruct<NonDerivedElement>();
+  NonDerivedElement* nde_back = list.AllocateAndConstruct<NonDerivedElement>();
+
+  EXPECT_EQ(size, list.size());
+  EXPECT_EQ(nde_front, list.front());
+  EXPECT_EQ(nde_back, list.back());
+  EXPECT_FALSE(list.empty());
+
+  list.clear();
+  EXPECT_TRUE(list.empty());
+  EXPECT_EQ(0u, list.size());
+
+  size = 3;
+  nde_front = list.AllocateAndConstruct<NonDerivedElement>();
+  list.AllocateAndConstruct<NonDerivedElement>();
+  nde_back = list.AllocateAndConstruct<NonDerivedElement>();
+
+  EXPECT_EQ(size, list.size());
+  EXPECT_EQ(nde_front, list.front());
+  EXPECT_EQ(nde_back, list.back());
+  EXPECT_FALSE(list.empty());
+}
+
+// This test is used to test when there is more than one allocation needed
+// for, ListContainer can still perform like normal vector.
+TEST(ListContainerTest,
+     SimpleInsertionTriggerMoreThanOneAllocationNonDerivedElement) {
+  ListContainer<NonDerivedElement> list(sizeof(NonDerivedElement), 2);
+  std::vector<NonDerivedElement*> nde_list;
+  size_t size = 10;
+  for (size_t i = 0; i < size; ++i) {
+    nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>());
+  }
+  EXPECT_EQ(size, list.size());
+
+  ListContainer<NonDerivedElement>::Iterator iter = list.begin();
+  for (std::vector<NonDerivedElement*>::const_iterator nde_iter =
+           nde_list.begin();
+       nde_iter != nde_list.end(); ++nde_iter) {
+    EXPECT_EQ(*nde_iter, *iter);
+    ++iter;
+  }
+}
+
+TEST(ListContainerTest,
+     CorrectAllocationSizeForMoreThanOneAllocationNonDerivedElement) {
+  // Constructor sets the allocation size to 2. Every time ListContainer needs
+  // to allocate again, it doubles allocation size. In this test, 10 elements is
+  // needed, thus ListContainerShould allocate spaces 2, 4 and 8 elements.
+  ListContainer<NonDerivedElement> list(sizeof(NonDerivedElement), 2);
+  std::vector<NonDerivedElement*> nde_list;
+  size_t size = 10;
+  for (size_t i = 0; i < size; ++i) {
+    // Before asking for a new element, space available without another
+    // allocation follows.
+    switch (i) {
+      case 2:
+      case 6:
+        EXPECT_EQ(0u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 1:
+      case 5:
+        EXPECT_EQ(1u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 0:
+      case 4:
+        EXPECT_EQ(2u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 3:
+        EXPECT_EQ(3u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 9:
+        EXPECT_EQ(5u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 8:
+        EXPECT_EQ(6u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 7:
+        EXPECT_EQ(7u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      default:
+        break;
+    }
+    nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>());
+    // After asking for a new element, space available without another
+    // allocation follows.
+    switch (i) {
+      case 1:
+      case 5:
+        EXPECT_EQ(0u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 0:
+      case 4:
+        EXPECT_EQ(1u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 3:
+        EXPECT_EQ(2u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 2:
+        EXPECT_EQ(3u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 9:
+        EXPECT_EQ(4u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 8:
+        EXPECT_EQ(5u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 7:
+        EXPECT_EQ(6u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      case 6:
+        EXPECT_EQ(7u, list.AvailableSizeWithoutAnotherAllocationForTesting());
+        break;
+      default:
+        break;
+    }
+  }
+  EXPECT_EQ(size, list.size());
+
+  ListContainer<NonDerivedElement>::Iterator iter = list.begin();
+  for (std::vector<NonDerivedElement*>::const_iterator nde_iter =
+           nde_list.begin();
+       nde_iter != nde_list.end(); ++nde_iter) {
+    EXPECT_EQ(*nde_iter, *iter);
+    ++iter;
+  }
+}
+
+TEST(ListContainerTest, SimpleIterationNonDerivedElement) {
+  ListContainer<NonDerivedElement> list;
+  std::vector<NonDerivedElement*> nde_list;
+  size_t size = 10;
+  for (size_t i = 0; i < size; ++i) {
+    nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>());
+  }
+  EXPECT_EQ(size, list.size());
+
+  size_t num_iters_in_list = 0;
+  {
+    std::vector<NonDerivedElement*>::const_iterator nde_iter = nde_list.begin();
+    for (ListContainer<NonDerivedElement>::Iterator iter = list.begin();
+         iter != list.end(); ++iter) {
+      EXPECT_EQ(*nde_iter, *iter);
+      ++num_iters_in_list;
+      ++nde_iter;
+    }
+  }
+
+  size_t num_iters_in_vector = 0;
+  {
+    ListContainer<NonDerivedElement>::Iterator iter = list.begin();
+    for (std::vector<NonDerivedElement*>::const_iterator nde_iter =
+             nde_list.begin();
+         nde_iter != nde_list.end(); ++nde_iter) {
+      EXPECT_EQ(*nde_iter, *iter);
+      ++num_iters_in_vector;
+      ++iter;
+    }
+  }
+
+  EXPECT_EQ(num_iters_in_vector, num_iters_in_list);
+}
+
+TEST(ListContainerTest, SimpleConstIteratorIterationNonDerivedElement) {
+  ListContainer<NonDerivedElement> list;
+  std::vector<const NonDerivedElement*> nde_list;
+  size_t size = 10;
+  for (size_t i = 0; i < size; ++i) {
+    nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>());
+  }
+  EXPECT_EQ(size, list.size());
+
+  {
+    std::vector<const NonDerivedElement*>::const_iterator nde_iter =
+        nde_list.begin();
+    for (ListContainer<NonDerivedElement>::ConstIterator iter = list.begin();
+         iter != list.end(); ++iter) {
+      EXPECT_TRUE(isConstNonDerivedElementPointer(*iter));
+      EXPECT_EQ(*nde_iter, *iter);
+      ++nde_iter;
+    }
+  }
+
+  {
+    std::vector<const NonDerivedElement*>::const_iterator nde_iter =
+        nde_list.begin();
+    for (ListContainer<NonDerivedElement>::Iterator iter = list.begin();
+         iter != list.end(); ++iter) {
+      EXPECT_FALSE(isConstNonDerivedElementPointer(*iter));
+      EXPECT_EQ(*nde_iter, *iter);
+      ++nde_iter;
+    }
+  }
+
+  {
+    ListContainer<NonDerivedElement>::ConstIterator iter = list.begin();
+    for (std::vector<const NonDerivedElement*>::const_iterator nde_iter =
+             nde_list.begin();
+         nde_iter != nde_list.end(); ++nde_iter) {
+      EXPECT_EQ(*nde_iter, *iter);
+      ++iter;
+    }
+  }
+}
+
+TEST(ListContainerTest, SimpleReverseInsertionNonDerivedElement) {
+  ListContainer<NonDerivedElement> list;
+  std::vector<NonDerivedElement*> nde_list;
+  size_t size = 10;
+  for (size_t i = 0; i < size; ++i) {
+    nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>());
+  }
+  EXPECT_EQ(size, list.size());
+
+  {
+    std::vector<NonDerivedElement*>::const_reverse_iterator nde_iter =
+        nde_list.rbegin();
+    for (ListContainer<NonDerivedElement>::ReverseIterator iter = list.rbegin();
+         iter != list.rend(); ++iter) {
+      EXPECT_EQ(*nde_iter, *iter);
+      ++nde_iter;
+    }
+  }
+
+  {
+    ListContainer<NonDerivedElement>::ReverseIterator iter = list.rbegin();
+    for (std::vector<NonDerivedElement*>::reverse_iterator nde_iter =
+             nde_list.rbegin();
+         nde_iter != nde_list.rend(); ++nde_iter) {
+      EXPECT_EQ(*nde_iter, *iter);
+      ++iter;
+    }
+  }
+}
+
+TEST(ListContainerTest, SimpleDeletion) {
+  ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+  std::vector<SimpleDerivedElement*> sde_list;
+  size_t size = 10;
+  for (size_t i = 0; i < size; ++i) {
+    sde_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>());
+    sde_list.back()->set_value(i);
+  }
+  EXPECT_EQ(size, list.size());
+
+  list.EraseAndInvalidateAllPointers(list.begin());
+  --size;
+  EXPECT_EQ(size, list.size());
+  int i = 1;
+  for (ListContainer<DerivedElement>::Iterator iter = list.begin();
+       iter != list.end(); ++iter) {
+    EXPECT_EQ(i, static_cast<SimpleDerivedElement*>(*iter)->get_value());
+    ++i;
+  }
+}
+
+TEST(ListContainerTest, DeletionAllInAllocation) {
+  const size_t kReserve = 10;
+  ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize,
+                                     kReserve);
+  std::vector<SimpleDerivedElement*> sde_list;
+  // Add enough elements to cause another allocation.
+  for (size_t i = 0; i < kReserve + 1; ++i) {
+    sde_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>());
+    sde_list.back()->set_value(static_cast<int>(i));
+  }
+  EXPECT_EQ(kReserve + 1, list.size());
+
+  // Remove everything in the first allocation.
+  for (size_t i = 0; i < kReserve; ++i)
+    list.EraseAndInvalidateAllPointers(list.begin());
+  EXPECT_EQ(1u, list.size());
+
+  // The last element is left.
+  SimpleDerivedElement* de = static_cast<SimpleDerivedElement*>(*list.begin());
+  EXPECT_EQ(static_cast<int>(kReserve), de->get_value());
+
+  // Remove the element from the 2nd allocation.
+  list.EraseAndInvalidateAllPointers(list.begin());
+  EXPECT_EQ(0u, list.size());
+}
+
+TEST(ListContainerTest, DeletionAllInAllocationReversed) {
+  const size_t kReserve = 10;
+  ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize,
+                                     kReserve);
+  std::vector<SimpleDerivedElement*> sde_list;
+  // Add enough elements to cause another allocation.
+  for (size_t i = 0; i < kReserve + 1; ++i) {
+    sde_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>());
+    sde_list.back()->set_value(static_cast<int>(i));
+  }
+  EXPECT_EQ(kReserve + 1, list.size());
+
+  // Remove everything in the 2nd allocation.
+  auto it = list.begin();
+  for (size_t i = 0; i < kReserve; ++i)
+    ++it;
+  list.EraseAndInvalidateAllPointers(it);
+
+  // The 2nd-last element is next, and the rest of the elements exist.
+  size_t i = kReserve - 1;
+  for (auto it = list.rbegin(); it != list.rend(); ++it) {
+    SimpleDerivedElement* de = static_cast<SimpleDerivedElement*>(*it);
+    EXPECT_EQ(static_cast<int>(i), de->get_value());
+    --i;
+  }
+
+  // Can forward iterate too.
+  i = 0;
+  for (auto it = list.begin(); it != list.end(); ++it) {
+    SimpleDerivedElement* de = static_cast<SimpleDerivedElement*>(*it);
+    EXPECT_EQ(static_cast<int>(i), de->get_value());
+    ++i;
+  }
+
+  // Remove the last thing from the 1st allocation.
+  it = list.begin();
+  for (size_t i = 0; i < kReserve - 1; ++i)
+    ++it;
+  list.EraseAndInvalidateAllPointers(it);
+
+  // The 2nd-last element is next, and the rest of the elements exist.
+  i = kReserve - 2;
+  for (auto it = list.rbegin(); it != list.rend(); ++it) {
+    SimpleDerivedElement* de = static_cast<SimpleDerivedElement*>(*it);
+    EXPECT_EQ(static_cast<int>(i), de->get_value());
+    --i;
+  }
+
+  // Can forward iterate too.
+  i = 0;
+  for (auto it = list.begin(); it != list.end(); ++it) {
+    SimpleDerivedElement* de = static_cast<SimpleDerivedElement*>(*it);
+    EXPECT_EQ(static_cast<int>(i), de->get_value());
+    ++i;
+  }
+}
+
+TEST(ListContainerTest, SimpleIterationAndManipulation) {
+  ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+  std::vector<SimpleDerivedElement*> sde_list;
+  size_t size = 10;
+  for (size_t i = 0; i < size; ++i) {
+    SimpleDerivedElement* simple_dq =
+        list.AllocateAndConstruct<SimpleDerivedElement>();
+    sde_list.push_back(simple_dq);
+  }
+  EXPECT_EQ(size, list.size());
+
+  ListContainer<DerivedElement>::Iterator iter = list.begin();
+  for (int i = 0; i < 10; ++i) {
+    static_cast<SimpleDerivedElement*>(*iter)->set_value(i);
+    ++iter;
+  }
+
+  int i = 0;
+  for (std::vector<SimpleDerivedElement*>::const_iterator sde_iter =
+           sde_list.begin();
+       sde_iter < sde_list.end(); ++sde_iter) {
+    EXPECT_EQ(i, (*sde_iter)->get_value());
+    ++i;
+  }
+}
+
+TEST(ListContainerTest, SimpleManipulationWithIndexSimpleDerivedElement) {
+  ListContainer<DerivedElement> list(kCurrentLargestDerivedElementSize);
+  std::vector<SimpleDerivedElement*> de_list;
+  size_t size = 10;
+  for (size_t i = 0; i < size; ++i) {
+    de_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>());
+  }
+  EXPECT_EQ(size, list.size());
+
+  for (size_t i = 0; i < size; ++i) {
+    static_cast<SimpleDerivedElement*>(list.ElementAt(i))->set_value(i);
+  }
+
+  int i = 0;
+  for (std::vector<SimpleDerivedElement*>::const_iterator
+           de_iter = de_list.begin();
+       de_iter != de_list.end(); ++de_iter, ++i) {
+    EXPECT_EQ(i, (*de_iter)->get_value());
+  }
+}
+
+TEST(ListContainerTest,
+     SimpleManipulationWithIndexMoreThanOneAllocationSimpleDerivedElement) {
+  ListContainer<DerivedElement> list(LargestDerivedElementSize(), 2);
+  std::vector<SimpleDerivedElement*> de_list;
+  size_t size = 10;
+  for (size_t i = 0; i < size; ++i) {
+    de_list.push_back(list.AllocateAndConstruct<SimpleDerivedElement>());
+  }
+  EXPECT_EQ(size, list.size());
+
+  for (size_t i = 0; i < size; ++i) {
+    static_cast<SimpleDerivedElement*>(list.ElementAt(i))->set_value(i);
+  }
+
+  int i = 0;
+  for (std::vector<SimpleDerivedElement*>::const_iterator
+           de_iter = de_list.begin();
+       de_iter != de_list.end(); ++de_iter, ++i) {
+    EXPECT_EQ(i, (*de_iter)->get_value());
+  }
+}
+
+TEST(ListContainerTest,
+     SimpleIterationAndReverseIterationWithIndexNonDerivedElement) {
+  ListContainer<NonDerivedElement> list;
+  std::vector<NonDerivedElement*> nde_list;
+  size_t size = 10;
+  for (size_t i = 0; i < size; ++i) {
+    nde_list.push_back(list.AllocateAndConstruct<NonDerivedElement>());
+  }
+  EXPECT_EQ(size, list.size());
+
+  size_t i = 0;
+  for (ListContainer<NonDerivedElement>::Iterator iter = list.begin();
+       iter != list.end(); ++iter) {
+    EXPECT_EQ(i, iter.index());
+    ++i;
+  }
+
+  i = 0;
+  for (ListContainer<NonDerivedElement>::ReverseIterator iter = list.rbegin();
+       iter != list.rend(); ++iter) {
+    EXPECT_EQ(i, iter.index());
+    ++i;
+  }
+}
+
+}  // namespace
+}  // namespace cc
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 98997ce..c1e456a7 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -16,6 +16,7 @@
       'base/delayed_unique_notifier_unittest.cc',
       'base/float_quad_unittest.cc',
       'base/histograms_unittest.cc',
+      'base/list_container_unittest.cc',
       'base/math_util_unittest.cc',
       'base/region_unittest.cc',
       'base/rolling_time_delta_history_unittest.cc',
@@ -85,7 +86,6 @@
       'playback/recording_source_unittest.cc',
       'quads/draw_polygon_unittest.cc',
       'quads/draw_quad_unittest.cc',
-      'quads/list_container_unittest.cc',
       'quads/render_pass_unittest.cc',
       'raster/scoped_gpu_raster_unittest.cc',
       'raster/task_graph_runner_unittest.cc',
diff --git a/cc/quads/list_container_unittest.cc b/cc/quads/list_container_unittest.cc
deleted file mode 100644
index 77c4d57a..0000000
--- a/cc/quads/list_container_unittest.cc
+++ /dev/null
@@ -1,765 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/base/list_container.h"
-
-#include <vector>
-#include "cc/quads/draw_quad.h"
-#include "cc/quads/largest_draw_quad.h"
-#include "cc/quads/render_pass_draw_quad.h"
-#include "cc/quads/shared_quad_state.h"
-#include "cc/quads/stream_video_draw_quad.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// TODO(jbroman): This unit test should be made generic and moved to cc/base/.
-
-namespace cc {
-namespace {
-
-int kMagicNumberToUseForDrawQuadOne = 42;
-int kMagicNumberToUseForDrawQuadTwo = 314;
-
-bool isConstSharedQuadStatePointer(const SharedQuadState* ptr) {
-  return true;
-}
-
-bool isConstSharedQuadStatePointer(SharedQuadState* ptr) {
-  return false;
-}
-
-class SimpleDrawQuad : public DrawQuad {
- public:
-  ~SimpleDrawQuad() override {}
-
-  void set_value(int val) { value = val; }
-  int get_value() { return value; }
-  void ExtendValue(base::trace_event::TracedValue* value) const override {}
-
- private:
-  int value;
-};
-
-class SimpleDrawQuadConstructMagicNumberOne : public SimpleDrawQuad {
- public:
-  SimpleDrawQuadConstructMagicNumberOne() : SimpleDrawQuad() {
-    set_value(kMagicNumberToUseForDrawQuadOne);
-  }
-};
-
-class SimpleDrawQuadConstructMagicNumberTwo : public SimpleDrawQuad {
- public:
-  SimpleDrawQuadConstructMagicNumberTwo() : SimpleDrawQuad() {
-    set_value(kMagicNumberToUseForDrawQuadTwo);
-  }
-};
-
-class MockDrawQuad : public SimpleDrawQuadConstructMagicNumberOne {
- public:
-  ~MockDrawQuad() override { Destruct(); }
-  MOCK_METHOD0(Destruct, void());
-};
-
-class MockDrawQuadSubclass : public MockDrawQuad {
- public:
-  MockDrawQuadSubclass() { set_value(kMagicNumberToUseForDrawQuadTwo); }
-};
-
-const size_t kLargestQuadSize =
-    std::max(LargestDrawQuadSize(), sizeof(MockDrawQuadSubclass));
-
-TEST(ListContainerTest, ConstructorCalledInAllocateAndConstruct) {
-  ListContainer<DrawQuad> list(kLargestQuadSize);
-
-  size_t size = 2;
-  SimpleDrawQuadConstructMagicNumberOne* dq_1 =
-      list.AllocateAndConstruct<SimpleDrawQuadConstructMagicNumberOne>();
-  SimpleDrawQuadConstructMagicNumberTwo* dq_2 =
-      list.AllocateAndConstruct<SimpleDrawQuadConstructMagicNumberTwo>();
-
-  EXPECT_EQ(size, list.size());
-  EXPECT_EQ(dq_1, list.front());
-  EXPECT_EQ(dq_2, list.back());
-
-  EXPECT_EQ(kMagicNumberToUseForDrawQuadOne, dq_1->get_value());
-  EXPECT_EQ(kMagicNumberToUseForDrawQuadTwo, dq_2->get_value());
-}
-
-TEST(ListContainerTest, DestructorCalled) {
-  ListContainer<DrawQuad> list(kLargestQuadSize);
-
-  size_t size = 1;
-  MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>();
-
-  EXPECT_CALL(*dq_1, Destruct());
-  EXPECT_EQ(size, list.size());
-  EXPECT_EQ(dq_1, list.front());
-}
-
-TEST(ListContainerTest, DestructorCalledOnceWhenClear) {
-  ListContainer<DrawQuad> list(kLargestQuadSize);
-  size_t size = 1;
-  MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>();
-
-  EXPECT_EQ(size, list.size());
-  EXPECT_EQ(dq_1, list.front());
-
-  // Make sure destructor is called once during clear, and won't be called
-  // again.
-  testing::MockFunction<void()> separator;
-  {
-    testing::InSequence s;
-    EXPECT_CALL(*dq_1, Destruct());
-    EXPECT_CALL(separator, Call());
-    EXPECT_CALL(*dq_1, Destruct()).Times(0);
-  }
-
-  list.clear();
-  separator.Call();
-}
-
-TEST(ListContainerTest, ReplaceExistingElement) {
-  ListContainer<DrawQuad> list(kLargestQuadSize);
-  size_t size = 1;
-  MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>();
-
-  EXPECT_EQ(size, list.size());
-  EXPECT_EQ(dq_1, list.front());
-
-  // Make sure destructor is called once during clear, and won't be called
-  // again.
-  testing::MockFunction<void()> separator;
-  {
-    testing::InSequence s;
-    EXPECT_CALL(*dq_1, Destruct());
-    EXPECT_CALL(separator, Call());
-    EXPECT_CALL(*dq_1, Destruct()).Times(0);
-  }
-
-  list.ReplaceExistingElement<MockDrawQuadSubclass>(list.begin());
-  EXPECT_EQ(kMagicNumberToUseForDrawQuadTwo, dq_1->get_value());
-  separator.Call();
-
-  EXPECT_CALL(*dq_1, Destruct());
-  list.clear();
-}
-
-TEST(ListContainerTest, DestructorCalledOnceWhenErase) {
-  ListContainer<DrawQuad> list(kLargestQuadSize);
-  size_t size = 1;
-  MockDrawQuad* dq_1 = list.AllocateAndConstruct<MockDrawQuad>();
-
-  EXPECT_EQ(size, list.size());
-  EXPECT_EQ(dq_1, list.front());
-
-  // Make sure destructor is called once during clear, and won't be called
-  // again.
-  testing::MockFunction<void()> separator;
-  {
-    testing::InSequence s;
-    EXPECT_CALL(*dq_1, Destruct());
-    EXPECT_CALL(separator, Call());
-    EXPECT_CALL(*dq_1, Destruct()).Times(0);
-  }
-
-  list.EraseAndInvalidateAllPointers(list.begin());
-  separator.Call();
-}
-
-TEST(ListContainerTest, SimpleIndexAccessSharedQuadState) {
-  ListContainer<SharedQuadState> list;
-
-  size_t size = 3;
-  SharedQuadState* sqs_1 = list.AllocateAndConstruct<SharedQuadState>();
-  SharedQuadState* sqs_2 = list.AllocateAndConstruct<SharedQuadState>();
-  SharedQuadState* sqs_3 = list.AllocateAndConstruct<SharedQuadState>();
-
-  EXPECT_EQ(size, list.size());
-  EXPECT_EQ(sqs_1, list.front());
-  EXPECT_EQ(sqs_3, list.back());
-  EXPECT_EQ(list.front(), list.ElementAt(0));
-  EXPECT_EQ(sqs_2, list.ElementAt(1));
-  EXPECT_EQ(list.back(), list.ElementAt(2));
-}
-
-TEST(ListContainerTest, SimpleInsertionSharedQuadState) {
-  ListContainer<SharedQuadState> list;
-
-  size_t size = 3;
-  SharedQuadState* sqs_1 = list.AllocateAndConstruct<SharedQuadState>();
-  list.AllocateAndConstruct<SharedQuadState>();
-  SharedQuadState* sqs_3 = list.AllocateAndConstruct<SharedQuadState>();
-
-  EXPECT_EQ(size, list.size());
-  EXPECT_EQ(sqs_1, list.front());
-  EXPECT_EQ(sqs_3, list.back());
-}
-
-TEST(ListContainerTest, SimpleInsertionAndClearSharedQuadState) {
-  ListContainer<SharedQuadState> list;
-  EXPECT_TRUE(list.empty());
-  EXPECT_EQ(0u, list.size());
-
-  size_t size = 3;
-  SharedQuadState* sqs_1 = list.AllocateAndConstruct<SharedQuadState>();
-  list.AllocateAndConstruct<SharedQuadState>();
-  SharedQuadState* sqs_3 = list.AllocateAndConstruct<SharedQuadState>();
-
-  EXPECT_EQ(size, list.size());
-  EXPECT_EQ(sqs_1, list.front());
-  EXPECT_EQ(sqs_3, list.back());
-  EXPECT_FALSE(list.empty());
-
-  list.clear();
-  EXPECT_TRUE(list.empty());
-  EXPECT_EQ(0u, list.size());
-}
-
-TEST(ListContainerTest, SimpleInsertionClearAndInsertAgainSharedQuadState) {
-  ListContainer<SharedQuadState> list;
-  EXPECT_TRUE(list.empty());
-  EXPECT_EQ(0u, list.size());
-
-  size_t size = 2;
-  SharedQuadState* sqs_front = list.AllocateAndConstruct<SharedQuadState>();
-  SharedQuadState* sqs_back = list.AllocateAndConstruct<SharedQuadState>();
-
-  EXPECT_EQ(size, list.size());
-  EXPECT_EQ(sqs_front, list.front());
-  EXPECT_EQ(sqs_back, list.back());
-  EXPECT_FALSE(list.empty());
-
-  list.clear();
-  EXPECT_TRUE(list.empty());
-  EXPECT_EQ(0u, list.size());
-
-  size = 3;
-  sqs_front = list.AllocateAndConstruct<SharedQuadState>();
-  list.AllocateAndConstruct<SharedQuadState>();
-  sqs_back = list.AllocateAndConstruct<SharedQuadState>();
-
-  EXPECT_EQ(size, list.size());
-  EXPECT_EQ(sqs_front, list.front());
-  EXPECT_EQ(sqs_back, list.back());
-  EXPECT_FALSE(list.empty());
-}
-
-// This test is used to test when there is more than one allocation needed
-// for, ListContainer can still perform like normal vector.
-TEST(ListContainerTest,
-     SimpleInsertionTriggerMoreThanOneAllocationSharedQuadState) {
-  ListContainer<SharedQuadState> list(sizeof(SharedQuadState), 2);
-  std::vector<SharedQuadState*> sqs_list;
-  size_t size = 10;
-  for (size_t i = 0; i < size; ++i) {
-    sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>());
-  }
-  EXPECT_EQ(size, list.size());
-
-  ListContainer<SharedQuadState>::Iterator iter = list.begin();
-  for (std::vector<SharedQuadState*>::const_iterator sqs_iter =
-           sqs_list.begin();
-       sqs_iter != sqs_list.end(); ++sqs_iter) {
-    EXPECT_EQ(*sqs_iter, *iter);
-    ++iter;
-  }
-}
-
-TEST(ListContainerTest,
-     CorrectAllocationSizeForMoreThanOneAllocationSharedQuadState) {
-  // Constructor sets the allocation size to 2. Every time ListContainer needs
-  // to allocate again, it doubles allocation size. In this test, 10 elements is
-  // needed, thus ListContainerShould allocate spaces 2, 4 and 8 elements.
-  ListContainer<SharedQuadState> list(sizeof(SharedQuadState), 2);
-  std::vector<SharedQuadState*> sqs_list;
-  size_t size = 10;
-  for (size_t i = 0; i < size; ++i) {
-    // Before asking for a new element, space available without another
-    // allocation follows.
-    switch (i) {
-      case 2:
-      case 6:
-        EXPECT_EQ(0u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 1:
-      case 5:
-        EXPECT_EQ(1u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 0:
-      case 4:
-        EXPECT_EQ(2u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 3:
-        EXPECT_EQ(3u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 9:
-        EXPECT_EQ(5u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 8:
-        EXPECT_EQ(6u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 7:
-        EXPECT_EQ(7u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      default:
-        break;
-    }
-    sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>());
-    // After asking for a new element, space available without another
-    // allocation follows.
-    switch (i) {
-      case 1:
-      case 5:
-        EXPECT_EQ(0u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 0:
-      case 4:
-        EXPECT_EQ(1u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 3:
-        EXPECT_EQ(2u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 2:
-        EXPECT_EQ(3u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 9:
-        EXPECT_EQ(4u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 8:
-        EXPECT_EQ(5u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 7:
-        EXPECT_EQ(6u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      case 6:
-        EXPECT_EQ(7u, list.AvailableSizeWithoutAnotherAllocationForTesting());
-        break;
-      default:
-        break;
-    }
-  }
-  EXPECT_EQ(size, list.size());
-
-  ListContainer<SharedQuadState>::Iterator iter = list.begin();
-  for (std::vector<SharedQuadState*>::const_iterator sqs_iter =
-           sqs_list.begin();
-       sqs_iter != sqs_list.end(); ++sqs_iter) {
-    EXPECT_EQ(*sqs_iter, *iter);
-    ++iter;
-  }
-}
-
-TEST(ListContainerTest, SimpleIterationSharedQuadState) {
-  ListContainer<SharedQuadState> list;
-  std::vector<SharedQuadState*> sqs_list;
-  size_t size = 10;
-  for (size_t i = 0; i < size; ++i) {
-    sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>());
-  }
-  EXPECT_EQ(size, list.size());
-
-  size_t num_iters_in_list = 0;
-  {
-    std::vector<SharedQuadState*>::const_iterator sqs_iter = sqs_list.begin();
-    for (ListContainer<SharedQuadState>::Iterator iter = list.begin();
-         iter != list.end(); ++iter) {
-      EXPECT_EQ(*sqs_iter, *iter);
-      ++num_iters_in_list;
-      ++sqs_iter;
-    }
-  }
-
-  size_t num_iters_in_vector = 0;
-  {
-    ListContainer<SharedQuadState>::Iterator iter = list.begin();
-    for (std::vector<SharedQuadState*>::const_iterator sqs_iter =
-             sqs_list.begin();
-         sqs_iter != sqs_list.end(); ++sqs_iter) {
-      EXPECT_EQ(*sqs_iter, *iter);
-      ++num_iters_in_vector;
-      ++iter;
-    }
-  }
-
-  EXPECT_EQ(num_iters_in_vector, num_iters_in_list);
-}
-
-TEST(ListContainerTest, SimpleConstIteratorIterationSharedQuadState) {
-  ListContainer<SharedQuadState> list;
-  std::vector<const SharedQuadState*> sqs_list;
-  size_t size = 10;
-  for (size_t i = 0; i < size; ++i) {
-    sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>());
-  }
-  EXPECT_EQ(size, list.size());
-
-  {
-    std::vector<const SharedQuadState*>::const_iterator sqs_iter =
-        sqs_list.begin();
-    for (ListContainer<SharedQuadState>::ConstIterator iter = list.begin();
-         iter != list.end(); ++iter) {
-      EXPECT_TRUE(isConstSharedQuadStatePointer(*iter));
-      EXPECT_EQ(*sqs_iter, *iter);
-      ++sqs_iter;
-    }
-  }
-
-  {
-    std::vector<const SharedQuadState*>::const_iterator sqs_iter =
-        sqs_list.begin();
-    for (ListContainer<SharedQuadState>::Iterator iter = list.begin();
-         iter != list.end(); ++iter) {
-      EXPECT_FALSE(isConstSharedQuadStatePointer(*iter));
-      EXPECT_EQ(*sqs_iter, *iter);
-      ++sqs_iter;
-    }
-  }
-
-  {
-    ListContainer<SharedQuadState>::ConstIterator iter = list.begin();
-    for (std::vector<const SharedQuadState*>::const_iterator sqs_iter =
-             sqs_list.begin();
-         sqs_iter != sqs_list.end(); ++sqs_iter) {
-      EXPECT_EQ(*sqs_iter, *iter);
-      ++iter;
-    }
-  }
-}
-
-TEST(ListContainerTest, SimpleReverseInsertionSharedQuadState) {
-  ListContainer<SharedQuadState> list;
-  std::vector<SharedQuadState*> sqs_list;
-  size_t size = 10;
-  for (size_t i = 0; i < size; ++i) {
-    sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>());
-  }
-  EXPECT_EQ(size, list.size());
-
-  {
-    std::vector<SharedQuadState*>::const_reverse_iterator sqs_iter =
-        sqs_list.rbegin();
-    for (ListContainer<SharedQuadState>::ReverseIterator iter = list.rbegin();
-         iter != list.rend(); ++iter) {
-      EXPECT_EQ(*sqs_iter, *iter);
-      ++sqs_iter;
-    }
-  }
-
-  {
-    ListContainer<SharedQuadState>::ReverseIterator iter = list.rbegin();
-    for (std::vector<SharedQuadState*>::reverse_iterator sqs_iter =
-             sqs_list.rbegin();
-         sqs_iter != sqs_list.rend(); ++sqs_iter) {
-      EXPECT_EQ(*sqs_iter, *iter);
-      ++iter;
-    }
-  }
-}
-
-TEST(ListContainerTest, SimpleDeletion) {
-  ListContainer<DrawQuad> list(kLargestQuadSize);
-  std::vector<SimpleDrawQuad*> sdq_list;
-  size_t size = 10;
-  for (size_t i = 0; i < size; ++i) {
-    sdq_list.push_back(list.AllocateAndConstruct<SimpleDrawQuad>());
-    sdq_list.back()->set_value(i);
-  }
-  EXPECT_EQ(size, list.size());
-
-  list.EraseAndInvalidateAllPointers(list.begin());
-  --size;
-  EXPECT_EQ(size, list.size());
-  int i = 1;
-  for (ListContainer<DrawQuad>::Iterator iter = list.begin();
-       iter != list.end(); ++iter) {
-    EXPECT_EQ(i, static_cast<SimpleDrawQuad*>(*iter)->get_value());
-    ++i;
-  }
-}
-
-TEST(ListContainerTest, DeletionAllInAllocation) {
-  const size_t kReserve = 10;
-  ListContainer<DrawQuad> list(kLargestQuadSize, kReserve);
-  std::vector<SimpleDrawQuad*> sdq_list;
-  // Add enough quads to cause another allocation.
-  for (size_t i = 0; i < kReserve + 1; ++i) {
-    sdq_list.push_back(list.AllocateAndConstruct<SimpleDrawQuad>());
-    sdq_list.back()->set_value(static_cast<int>(i));
-  }
-  EXPECT_EQ(kReserve + 1, list.size());
-
-  // Remove everything in the first allocation.
-  for (size_t i = 0; i < kReserve; ++i)
-    list.EraseAndInvalidateAllPointers(list.begin());
-  EXPECT_EQ(1u, list.size());
-
-  // The last quad is left.
-  SimpleDrawQuad* quad = static_cast<SimpleDrawQuad*>(*list.begin());
-  EXPECT_EQ(static_cast<int>(kReserve), quad->get_value());
-
-  // Remove the quad from the 2nd allocation.
-  list.EraseAndInvalidateAllPointers(list.begin());
-  EXPECT_EQ(0u, list.size());
-}
-
-TEST(ListContainerTest, DeletionAllInAllocationReversed) {
-  const size_t kReserve = 10;
-  ListContainer<DrawQuad> list(kLargestQuadSize, kReserve);
-  std::vector<SimpleDrawQuad*> sdq_list;
-  // Add enough quads to cause another allocation.
-  for (size_t i = 0; i < kReserve + 1; ++i) {
-    sdq_list.push_back(list.AllocateAndConstruct<SimpleDrawQuad>());
-    sdq_list.back()->set_value(static_cast<int>(i));
-  }
-  EXPECT_EQ(kReserve + 1, list.size());
-
-  // Remove everything in the 2nd allocation.
-  auto it = list.begin();
-  for (size_t i = 0; i < kReserve; ++i)
-    ++it;
-  list.EraseAndInvalidateAllPointers(it);
-
-  // The 2nd-last quad is next, and the rest of the quads exist.
-  size_t i = kReserve - 1;
-  for (auto it = list.rbegin(); it != list.rend(); ++it) {
-    SimpleDrawQuad* quad = static_cast<SimpleDrawQuad*>(*it);
-    EXPECT_EQ(static_cast<int>(i), quad->get_value());
-    --i;
-  }
-
-  // Can forward iterate too.
-  i = 0;
-  for (auto it = list.begin(); it != list.end(); ++it) {
-    SimpleDrawQuad* quad = static_cast<SimpleDrawQuad*>(*it);
-    EXPECT_EQ(static_cast<int>(i), quad->get_value());
-    ++i;
-  }
-
-  // Remove the last thing from the 1st allocation.
-  it = list.begin();
-  for (size_t i = 0; i < kReserve - 1; ++i)
-    ++it;
-  list.EraseAndInvalidateAllPointers(it);
-
-  // The 2nd-last quad is next, and the rest of the quads exist.
-  i = kReserve - 2;
-  for (auto it = list.rbegin(); it != list.rend(); ++it) {
-    SimpleDrawQuad* quad = static_cast<SimpleDrawQuad*>(*it);
-    EXPECT_EQ(static_cast<int>(i), quad->get_value());
-    --i;
-  }
-
-  // Can forward iterate too.
-  i = 0;
-  for (auto it = list.begin(); it != list.end(); ++it) {
-    SimpleDrawQuad* quad = static_cast<SimpleDrawQuad*>(*it);
-    EXPECT_EQ(static_cast<int>(i), quad->get_value());
-    ++i;
-  }
-}
-
-TEST(ListContainerTest, SimpleIterationAndManipulation) {
-  ListContainer<DrawQuad> list(kLargestQuadSize);
-  std::vector<SimpleDrawQuad*> sdq_list;
-  size_t size = 10;
-  for (size_t i = 0; i < size; ++i) {
-    SimpleDrawQuad* simple_dq = list.AllocateAndConstruct<SimpleDrawQuad>();
-    sdq_list.push_back(simple_dq);
-  }
-  EXPECT_EQ(size, list.size());
-
-  ListContainer<DrawQuad>::Iterator iter = list.begin();
-  for (int i = 0; i < 10; ++i) {
-    static_cast<SimpleDrawQuad*>(*iter)->set_value(i);
-    ++iter;
-  }
-
-  int i = 0;
-  for (std::vector<SimpleDrawQuad*>::const_iterator sdq_iter = sdq_list.begin();
-       sdq_iter < sdq_list.end(); ++sdq_iter) {
-    EXPECT_EQ(i, (*sdq_iter)->get_value());
-    ++i;
-  }
-}
-
-TEST(ListContainerTest, SimpleManipulationWithIndexSimpleDrawQuad) {
-  ListContainer<DrawQuad> list(kLargestQuadSize);
-  std::vector<SimpleDrawQuad*> dq_list;
-  size_t size = 10;
-  for (size_t i = 0; i < size; ++i) {
-    dq_list.push_back(list.AllocateAndConstruct<SimpleDrawQuad>());
-  }
-  EXPECT_EQ(size, list.size());
-
-  for (size_t i = 0; i < size; ++i) {
-    static_cast<SimpleDrawQuad*>(list.ElementAt(i))->set_value(i);
-  }
-
-  int i = 0;
-  for (std::vector<SimpleDrawQuad*>::const_iterator dq_iter = dq_list.begin();
-       dq_iter != dq_list.end(); ++dq_iter, ++i) {
-    EXPECT_EQ(i, (*dq_iter)->get_value());
-  }
-}
-
-TEST(ListContainerTest,
-     SimpleManipulationWithIndexMoreThanOneAllocationSimpleDrawQuad) {
-  ListContainer<DrawQuad> list(LargestDrawQuadSize(), 2);
-  std::vector<SimpleDrawQuad*> dq_list;
-  size_t size = 10;
-  for (size_t i = 0; i < size; ++i) {
-    dq_list.push_back(list.AllocateAndConstruct<SimpleDrawQuad>());
-  }
-  EXPECT_EQ(size, list.size());
-
-  for (size_t i = 0; i < size; ++i) {
-    static_cast<SimpleDrawQuad*>(list.ElementAt(i))->set_value(i);
-  }
-
-  int i = 0;
-  for (std::vector<SimpleDrawQuad*>::const_iterator dq_iter = dq_list.begin();
-       dq_iter != dq_list.end(); ++dq_iter, ++i) {
-    EXPECT_EQ(i, (*dq_iter)->get_value());
-  }
-}
-
-TEST(ListContainerTest,
-     SimpleIterationAndReverseIterationWithIndexSharedQuadState) {
-  ListContainer<SharedQuadState> list;
-  std::vector<SharedQuadState*> sqs_list;
-  size_t size = 10;
-  for (size_t i = 0; i < size; ++i) {
-    sqs_list.push_back(list.AllocateAndConstruct<SharedQuadState>());
-  }
-  EXPECT_EQ(size, list.size());
-
-  size_t i = 0;
-  for (ListContainer<SharedQuadState>::Iterator iter = list.begin();
-       iter != list.end(); ++iter) {
-    EXPECT_EQ(i, iter.index());
-    ++i;
-  }
-
-  i = 0;
-  for (ListContainer<SharedQuadState>::ReverseIterator iter = list.rbegin();
-       iter != list.rend(); ++iter) {
-    EXPECT_EQ(i, iter.index());
-    ++i;
-  }
-}
-
-// 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