Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / cc / base / sidecar_list_container_unittest.cc
blob0012014df8f9d1a3b32df59952ec543e3a655a29
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/base/sidecar_list_container.h"
7 #include <algorithm>
9 #include "base/logging.h"
10 #include "testing/gtest/include/gtest/gtest.h"
12 namespace cc {
13 namespace {
15 const size_t kNumInitiallyReservedElements = 2;
16 const size_t kNumElementsForTest = 100;
18 class DestructionNotifier {
19 public:
20 DestructionNotifier() : flag_(nullptr) {}
21 explicit DestructionNotifier(bool* flag) { set_flag(flag); }
22 ~DestructionNotifier() {
23 if (flag_)
24 *flag_ = true;
26 void set_flag(bool* flag) {
27 if (flag)
28 DCHECK(!*flag);
29 flag_ = flag;
32 private:
33 bool* flag_;
36 class TestElement {
37 public:
38 TestElement() {}
39 virtual ~TestElement() {}
40 void set_destruction_flag(bool* flag) { notifier_.set_flag(flag); }
42 private:
43 DestructionNotifier notifier_;
46 class DerivedTestElement : public TestElement {
47 public:
48 int additional_field = 0;
51 class TestSidecar {
52 public:
53 TestSidecar() {}
54 explicit TestSidecar(bool* destruction_flag) : notifier_(destruction_flag) {}
56 static void Destroy(void* sidecar) {
57 static_cast<TestSidecar*>(sidecar)->~TestSidecar();
60 protected:
61 virtual ~TestSidecar() {}
63 private:
64 DestructionNotifier notifier_;
67 class DerivedTestSidecar : public TestSidecar {
68 public:
69 DerivedTestSidecar() {}
70 explicit DerivedTestSidecar(bool* destruction_flag)
71 : TestSidecar(destruction_flag) {}
72 int additional_field = 0;
74 private:
75 ~DerivedTestSidecar() override {}
78 class TestContainer : public SidecarListContainer<TestElement> {
79 public:
80 TestContainer()
81 : SidecarListContainer(
82 std::max(sizeof(TestElement), sizeof(DerivedTestElement)),
83 std::max(sizeof(TestSidecar), sizeof(DerivedTestSidecar)),
84 kNumInitiallyReservedElements,
85 &TestSidecar::Destroy) {}
88 TEST(SidecarListContainerTest, Destructor) {
89 bool element_destroyed = false;
90 bool sidecar_destroyed = false;
93 TestContainer container;
95 TestElement* element = container.AllocateAndConstruct<TestElement>();
96 TestSidecar* sidecar =
97 new (container.GetSidecar(element)) TestSidecar(&sidecar_destroyed);
98 element->set_destruction_flag(&element_destroyed);
100 // They shouldn't be destroyed yet. And they shouldn't overlap in memory.
101 ASSERT_FALSE(element_destroyed);
102 ASSERT_FALSE(sidecar_destroyed);
103 ASSERT_GE(reinterpret_cast<char*>(sidecar),
104 reinterpret_cast<char*>(element) + sizeof(TestElement));
107 // They should, however, be destroyed when going out of scope.
108 ASSERT_TRUE(element_destroyed);
109 ASSERT_TRUE(sidecar_destroyed);
112 TEST(SidecarListContainerTest, Clear) {
113 bool element_destroyed = false;
114 bool sidecar_destroyed = false;
116 TestContainer container;
118 TestElement* element = container.AllocateAndConstruct<TestElement>();
119 new (container.GetSidecar(element)) TestSidecar(&sidecar_destroyed);
120 element->set_destruction_flag(&element_destroyed);
122 // They shouldn't be destroyed yet.
123 ASSERT_FALSE(element_destroyed);
124 ASSERT_FALSE(sidecar_destroyed);
126 // They should, however, be destroyed after clearing.
127 container.clear();
128 EXPECT_TRUE(element_destroyed);
129 EXPECT_TRUE(sidecar_destroyed);
132 TEST(SidecarListContainerTest, DerivedTypes) {
133 bool element_destroyed = false;
134 bool sidecar_destroyed = false;
137 TestContainer container;
139 DerivedTestElement* element =
140 container.AllocateAndConstruct<DerivedTestElement>();
141 DerivedTestSidecar* sidecar = new (container.GetSidecar(element))
142 DerivedTestSidecar(&sidecar_destroyed);
143 element->set_destruction_flag(&element_destroyed);
144 element->additional_field = 12;
145 sidecar->additional_field = 13;
147 // They shouldn't be destroyed yet.
148 ASSERT_FALSE(element_destroyed);
149 ASSERT_FALSE(sidecar_destroyed);
152 // They should, however, be destroyed when going out of scope.
153 EXPECT_TRUE(element_destroyed);
154 EXPECT_TRUE(sidecar_destroyed);
157 TEST(SidecarListContainerTest, AddingAndRemovingElements) {
158 TestContainer container;
159 EXPECT_TRUE(container.empty());
160 EXPECT_EQ(0u, container.size());
161 EXPECT_EQ(container.end(), container.begin());
163 for (size_t i = 1; i <= kNumElementsForTest; i++) {
164 TestElement* element = container.AllocateAndConstruct<TestElement>();
165 new (container.GetSidecar(element)) TestSidecar();
167 ASSERT_FALSE(container.empty());
168 ASSERT_EQ(i, container.size());
169 ASSERT_NE(container.end(), container.begin());
172 size_t num_elements = 0;
173 for (const auto* element : container) {
174 (void)element;
175 num_elements++;
177 EXPECT_EQ(kNumElementsForTest, num_elements);
179 container.clear();
180 EXPECT_TRUE(container.empty());
181 EXPECT_EQ(0u, container.size());
182 EXPECT_EQ(container.end(), container.begin());
185 TEST(SidecarListContainerTest, RemoveLast) {
186 // We need only ensure that the sidecar is also destroyed on RemoveLast.
187 // The rest is logic already present in ListContainer.
188 bool sidecar_destroyed = false;
189 TestContainer container;
190 TestElement* element = container.AllocateAndConstruct<TestElement>();
191 new (container.GetSidecar(element)) TestSidecar(&sidecar_destroyed);
192 ASSERT_FALSE(sidecar_destroyed);
193 container.RemoveLast();
194 ASSERT_TRUE(sidecar_destroyed);
197 } // namespace
198 } // namespace cc