Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(251)

Side by Side Diff: cc/base/contiguous_container_unittest.cc

Issue 2119033003: Fix alignment issue of ContiguousContainer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 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 <stddef.h> 5 #include <stddef.h>
6 6
7 #include "cc/base/contiguous_container.h" 7 #include "cc/base/contiguous_container.h"
8 #include "testing/gmock/include/gmock/gmock.h" 8 #include "testing/gmock/include/gmock/gmock.h"
9 #include "testing/gtest/include/gtest/gtest.h" 9 #include "testing/gtest/include/gtest/gtest.h"
10 10
11 namespace cc { 11 namespace cc {
12 namespace { 12 namespace {
13 13
14 struct Point2D { 14 struct Point2D {
15 Point2D() : Point2D(0, 0) {} 15 Point2D() : Point2D(0, 0) {}
16 Point2D(int x, int y) : x(x), y(y) {} 16 Point2D(int x, int y) : x(x), y(y) {}
17 int x, y; 17 int x, y;
18 }; 18 };
19 19
20 struct Point3D : public Point2D { 20 struct Point3D : public Point2D {
21 Point3D() : Point3D(0, 0, 0) {} 21 Point3D() : Point3D(0, 0, 0) {}
22 Point3D(int x, int y, int z) : Point2D(x, y), z(z) {} 22 Point3D(int x, int y, int z) : Point2D(x, y), z(z) {}
23 int z; 23 int z;
24 }; 24 };
25 25
26 // Maximum size of a subclass of Point2D. 26 // Maximum size of a subclass of Point2D.
27 static const size_t kMaxPointSize = sizeof(Point3D); 27 static const size_t kMaxPointSize = sizeof(Point3D);
28 28
29 // Alignment for Point2D and its subclasses.
30 static const size_t kPointAlignment = sizeof(int);
31
32 // How many elements to use for tests with "plenty" of elements. 29 // How many elements to use for tests with "plenty" of elements.
33 static const size_t kNumElements = 150; 30 static const size_t kNumElements = 150;
34 31
32 } // namespace
33
35 TEST(ContiguousContainerTest, SimpleStructs) { 34 TEST(ContiguousContainerTest, SimpleStructs) {
36 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 35 ContiguousContainer<Point2D> list(kMaxPointSize);
37 list.AllocateAndConstruct<Point2D>(1, 2); 36 list.AllocateAndConstruct<Point2D>(1, 2);
38 list.AllocateAndConstruct<Point3D>(3, 4, 5); 37 list.AllocateAndConstruct<Point3D>(3, 4, 5);
39 list.AllocateAndConstruct<Point2D>(6, 7); 38 list.AllocateAndConstruct<Point2D>(6, 7);
40 39
41 ASSERT_EQ(3u, list.size()); 40 ASSERT_EQ(3u, list.size());
42 EXPECT_EQ(1, list[0].x); 41 EXPECT_EQ(1, list[0].x);
43 EXPECT_EQ(2, list[0].y); 42 EXPECT_EQ(2, list[0].y);
44 EXPECT_EQ(3, list[1].x); 43 EXPECT_EQ(3, list[1].x);
45 EXPECT_EQ(4, list[1].y); 44 EXPECT_EQ(4, list[1].y);
46 EXPECT_EQ(5, static_cast<Point3D&>(list[1]).z); 45 EXPECT_EQ(5, static_cast<Point3D&>(list[1]).z);
47 EXPECT_EQ(6, list[2].x); 46 EXPECT_EQ(6, list[2].x);
48 EXPECT_EQ(7, list[2].y); 47 EXPECT_EQ(7, list[2].y);
49 } 48 }
50 49
51 TEST(ContiguousContainerTest, AllocateLots) { 50 TEST(ContiguousContainerTest, AllocateLots) {
52 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 51 ContiguousContainer<Point2D> list(kMaxPointSize);
53 for (int i = 0; i < (int)kNumElements; i++) { 52 for (int i = 0; i < (int)kNumElements; i++) {
54 list.AllocateAndConstruct<Point2D>(i, i); 53 list.AllocateAndConstruct<Point2D>(i, i);
55 list.AllocateAndConstruct<Point2D>(i, i); 54 list.AllocateAndConstruct<Point2D>(i, i);
56 list.RemoveLast(); 55 list.RemoveLast();
57 } 56 }
58 ASSERT_EQ(kNumElements, list.size()); 57 ASSERT_EQ(kNumElements, list.size());
59 for (int i = 0; i < (int)kNumElements; i++) { 58 for (int i = 0; i < (int)kNumElements; i++) {
60 ASSERT_EQ(i, list[i].x); 59 ASSERT_EQ(i, list[i].x);
61 ASSERT_EQ(i, list[i].y); 60 ASSERT_EQ(i, list[i].y);
62 } 61 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 separator.Call(); 159 separator.Call();
161 EXPECT_EQ(3u, list.size()); 160 EXPECT_EQ(3u, list.size());
162 161
163 // The remaining ones are destroyed when the test finishes. 162 // The remaining ones are destroyed when the test finishes.
164 EXPECT_CALL(list[2], Destruct()); 163 EXPECT_CALL(list[2], Destruct());
165 EXPECT_CALL(list[1], Destruct()); 164 EXPECT_CALL(list[1], Destruct());
166 EXPECT_CALL(list[0], Destruct()); 165 EXPECT_CALL(list[0], Destruct());
167 } 166 }
168 167
169 TEST(ContiguousContainerTest, InsertionAndIndexedAccess) { 168 TEST(ContiguousContainerTest, InsertionAndIndexedAccess) {
170 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 169 ContiguousContainer<Point2D> list(kMaxPointSize);
171 170
172 auto& point1 = list.AllocateAndConstruct<Point2D>(); 171 auto& point1 = list.AllocateAndConstruct<Point2D>();
173 auto& point2 = list.AllocateAndConstruct<Point2D>(); 172 auto& point2 = list.AllocateAndConstruct<Point2D>();
174 auto& point3 = list.AllocateAndConstruct<Point2D>(); 173 auto& point3 = list.AllocateAndConstruct<Point2D>();
175 174
176 EXPECT_EQ(3u, list.size()); 175 EXPECT_EQ(3u, list.size());
177 EXPECT_EQ(&point1, &list.first()); 176 EXPECT_EQ(&point1, &list.first());
178 EXPECT_EQ(&point3, &list.last()); 177 EXPECT_EQ(&point3, &list.last());
179 EXPECT_EQ(&point1, &list[0]); 178 EXPECT_EQ(&point1, &list[0]);
180 EXPECT_EQ(&point2, &list[1]); 179 EXPECT_EQ(&point2, &list[1]);
181 EXPECT_EQ(&point3, &list[2]); 180 EXPECT_EQ(&point3, &list[2]);
182 } 181 }
183 182
184 TEST(ContiguousContainerTest, InsertionAndClear) { 183 TEST(ContiguousContainerTest, InsertionAndClear) {
185 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 184 ContiguousContainer<Point2D> list(kMaxPointSize);
186 EXPECT_TRUE(list.empty()); 185 EXPECT_TRUE(list.empty());
187 EXPECT_EQ(0u, list.size()); 186 EXPECT_EQ(0u, list.size());
188 187
189 list.AllocateAndConstruct<Point2D>(); 188 list.AllocateAndConstruct<Point2D>();
190 EXPECT_FALSE(list.empty()); 189 EXPECT_FALSE(list.empty());
191 EXPECT_EQ(1u, list.size()); 190 EXPECT_EQ(1u, list.size());
192 191
193 list.Clear(); 192 list.Clear();
194 EXPECT_TRUE(list.empty()); 193 EXPECT_TRUE(list.empty());
195 EXPECT_EQ(0u, list.size()); 194 EXPECT_EQ(0u, list.size());
196 195
197 list.AllocateAndConstruct<Point2D>(); 196 list.AllocateAndConstruct<Point2D>();
198 EXPECT_FALSE(list.empty()); 197 EXPECT_FALSE(list.empty());
199 EXPECT_EQ(1u, list.size()); 198 EXPECT_EQ(1u, list.size());
200 } 199 }
201 200
202 TEST(ContiguousContainerTest, ElementAddressesAreStable) { 201 TEST(ContiguousContainerTest, ElementAddressesAreStable) {
203 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 202 ContiguousContainer<Point2D> list(kMaxPointSize);
204 std::vector<Point2D*> pointers; 203 std::vector<Point2D*> pointers;
205 for (int i = 0; i < (int)kNumElements; i++) 204 for (int i = 0; i < (int)kNumElements; i++)
206 pointers.push_back(&list.AllocateAndConstruct<Point2D>()); 205 pointers.push_back(&list.AllocateAndConstruct<Point2D>());
207 EXPECT_EQ(kNumElements, list.size()); 206 EXPECT_EQ(kNumElements, list.size());
208 EXPECT_EQ(kNumElements, pointers.size()); 207 EXPECT_EQ(kNumElements, pointers.size());
209 208
210 auto listIt = list.begin(); 209 auto listIt = list.begin();
211 auto vectorIt = pointers.begin(); 210 auto vectorIt = pointers.begin();
212 for (; listIt != list.end(); ++listIt, ++vectorIt) 211 for (; listIt != list.end(); ++listIt, ++vectorIt)
213 EXPECT_EQ(&*listIt, *vectorIt); 212 EXPECT_EQ(&*listIt, *vectorIt);
214 } 213 }
215 214
216 TEST(ContiguousContainerTest, ForwardIteration) { 215 TEST(ContiguousContainerTest, ForwardIteration) {
217 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 216 ContiguousContainer<Point2D> list(kMaxPointSize);
218 for (int i = 0; i < (int)kNumElements; i++) 217 for (int i = 0; i < (int)kNumElements; i++)
219 list.AllocateAndConstruct<Point2D>(i, i); 218 list.AllocateAndConstruct<Point2D>(i, i);
220 unsigned count = 0; 219 unsigned count = 0;
221 for (Point2D& point : list) { 220 for (Point2D& point : list) {
222 EXPECT_EQ((int)count, point.x); 221 EXPECT_EQ((int)count, point.x);
223 count++; 222 count++;
224 } 223 }
225 EXPECT_EQ(kNumElements, count); 224 EXPECT_EQ(kNumElements, count);
226 225
227 static_assert(std::is_same<decltype(*list.begin()), Point2D&>::value, 226 static_assert(std::is_same<decltype(*list.begin()), Point2D&>::value,
228 "Non-const iteration should produce non-const references."); 227 "Non-const iteration should produce non-const references.");
229 } 228 }
230 229
231 TEST(ContiguousContainerTest, ConstForwardIteration) { 230 TEST(ContiguousContainerTest, ConstForwardIteration) {
232 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 231 ContiguousContainer<Point2D> list(kMaxPointSize);
233 for (int i = 0; i < (int)kNumElements; i++) 232 for (int i = 0; i < (int)kNumElements; i++)
234 list.AllocateAndConstruct<Point2D>(i, i); 233 list.AllocateAndConstruct<Point2D>(i, i);
235 234
236 const auto& const_list = list; 235 const auto& const_list = list;
237 unsigned count = 0; 236 unsigned count = 0;
238 for (const Point2D& point : const_list) { 237 for (const Point2D& point : const_list) {
239 EXPECT_EQ((int)count, point.x); 238 EXPECT_EQ((int)count, point.x);
240 count++; 239 count++;
241 } 240 }
242 EXPECT_EQ(kNumElements, count); 241 EXPECT_EQ(kNumElements, count);
243 242
244 static_assert( 243 static_assert(
245 std::is_same<decltype(*const_list.begin()), const Point2D&>::value, 244 std::is_same<decltype(*const_list.begin()), const Point2D&>::value,
246 "Const iteration should produce const references."); 245 "Const iteration should produce const references.");
247 } 246 }
248 247
249 TEST(ContiguousContainerTest, ReverseIteration) { 248 TEST(ContiguousContainerTest, ReverseIteration) {
250 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 249 ContiguousContainer<Point2D> list(kMaxPointSize);
251 for (int i = 0; i < (int)kNumElements; i++) 250 for (int i = 0; i < (int)kNumElements; i++)
252 list.AllocateAndConstruct<Point2D>(i, i); 251 list.AllocateAndConstruct<Point2D>(i, i);
253 252
254 unsigned count = 0; 253 unsigned count = 0;
255 for (auto it = list.rbegin(); it != list.rend(); ++it) { 254 for (auto it = list.rbegin(); it != list.rend(); ++it) {
256 EXPECT_EQ((int)(kNumElements - 1 - count), it->x); 255 EXPECT_EQ((int)(kNumElements - 1 - count), it->x);
257 count++; 256 count++;
258 } 257 }
259 EXPECT_EQ(kNumElements, count); 258 EXPECT_EQ(kNumElements, count);
260 259
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 pop(); 320 pop();
322 check_equal(); // One full, one empty. 321 check_equal(); // One full, one empty.
323 push(); 322 push();
324 pop(); 323 pop();
325 pop(); 324 pop();
326 ASSERT_TRUE(list.empty()); 325 ASSERT_TRUE(list.empty());
327 check_equal(); // Empty. 326 check_equal(); // Empty.
328 } 327 }
329 328
330 TEST(ContiguousContainerTest, AppendByMovingSameList) { 329 TEST(ContiguousContainerTest, AppendByMovingSameList) {
331 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 330 ContiguousContainer<Point2D> list(kMaxPointSize);
332 list.AllocateAndConstruct<Point3D>(1, 2, 3); 331 list.AllocateAndConstruct<Point3D>(1, 2, 3);
333 332
334 // Moves the Point3D to the end, and default-constructs a Point2D in its 333 // Moves the Point3D to the end, and default-constructs a Point2D in its
335 // place. 334 // place.
336 list.AppendByMoving(&list.first(), sizeof(Point3D)); 335 list.AppendByMoving(&list.first(), sizeof(Point3D), ALIGNOF(Point3D));
337 EXPECT_EQ(1, list.last().x); 336 EXPECT_EQ(1, list.last().x);
338 EXPECT_EQ(2, list.last().y); 337 EXPECT_EQ(2, list.last().y);
339 EXPECT_EQ(3, static_cast<const Point3D&>(list.last()).z); 338 EXPECT_EQ(3, static_cast<const Point3D&>(list.last()).z);
340 EXPECT_EQ(2u, list.size()); 339 EXPECT_EQ(2u, list.size());
341 340
342 // Moves that Point2D to the end, and default-constructs another in its 341 // Moves that Point2D to the end, and default-constructs another in its
343 // place. 342 // place.
344 list.first().x = 4; 343 list.first().x = 4;
345 list.AppendByMoving(&list.first(), sizeof(Point2D)); 344 list.AppendByMoving(&list.first(), sizeof(Point2D), ALIGNOF(Point2D));
346 EXPECT_EQ(4, list.last().x); 345 EXPECT_EQ(4, list.last().x);
347 EXPECT_EQ(3u, list.size()); 346 EXPECT_EQ(3u, list.size());
348 } 347 }
349 348
350 TEST(ContiguousContainerTest, AppendByMovingDoesNotDestruct) { 349 TEST(ContiguousContainerTest, AppendByMovingDoesNotDestruct) {
351 // GMock mock objects (e.g. MockDestructible) aren't guaranteed to be safe 350 // GMock mock objects (e.g. MockDestructible) aren't guaranteed to be safe
352 // to memcpy (which is required for AppendByMoving). 351 // to memcpy (which is required for AppendByMoving).
353 class DestructionNotifier { 352 class DestructionNotifier {
354 public: 353 public:
355 explicit DestructionNotifier(bool* flag = nullptr) : flag_(flag) {} 354 explicit DestructionNotifier(bool* flag = nullptr) : flag_(flag) {}
356 ~DestructionNotifier() { 355 ~DestructionNotifier() {
357 if (flag_) 356 if (flag_)
358 *flag_ = true; 357 *flag_ = true;
359 } 358 }
360 359
361 private: 360 private:
362 bool* flag_; 361 bool* flag_;
363 }; 362 };
364 363
365 bool destroyed = false; 364 bool destroyed = false;
366 ContiguousContainer<DestructionNotifier> list1(sizeof(DestructionNotifier)); 365 ContiguousContainer<DestructionNotifier> list1(sizeof(DestructionNotifier));
367 list1.AllocateAndConstruct<DestructionNotifier>(&destroyed); 366 list1.AllocateAndConstruct<DestructionNotifier>(&destroyed);
368 { 367 {
369 // Make sure destructor isn't called during AppendByMoving. 368 // Make sure destructor isn't called during AppendByMoving.
370 ContiguousContainer<DestructionNotifier> list2(sizeof(DestructionNotifier)); 369 ContiguousContainer<DestructionNotifier> list2(sizeof(DestructionNotifier));
371 list2.AppendByMoving(&list1.last(), sizeof(DestructionNotifier)); 370 list2.AppendByMoving(&list1.last(), sizeof(DestructionNotifier),
371 ALIGNOF(DestructionNotifier));
372 EXPECT_FALSE(destroyed); 372 EXPECT_FALSE(destroyed);
373 } 373 }
374 // But it should be destroyed when list2 is. 374 // But it should be destroyed when list2 is.
375 EXPECT_TRUE(destroyed); 375 EXPECT_TRUE(destroyed);
376 } 376 }
377 377
378 TEST(ContiguousContainerTest, AppendByMovingReturnsMovedPointer) { 378 TEST(ContiguousContainerTest, AppendByMovingReturnsMovedPointer) {
379 ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); 379 ContiguousContainer<Point2D> list1(kMaxPointSize);
380 ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); 380 ContiguousContainer<Point2D> list2(kMaxPointSize);
381 381
382 Point2D& point = list1.AllocateAndConstruct<Point2D>(); 382 Point2D& point = list1.AllocateAndConstruct<Point2D>();
383 Point2D& moved_point1 = list2.AppendByMoving(&point, sizeof(Point2D)); 383 Point2D& moved_point1 =
384 list2.AppendByMoving(&point, sizeof(Point2D), ALIGNOF(Point2D));
384 EXPECT_EQ(&moved_point1, &list2.last()); 385 EXPECT_EQ(&moved_point1, &list2.last());
385 386
386 Point2D& moved_point2 = list1.AppendByMoving(&moved_point1, sizeof(Point2D)); 387 Point2D& moved_point2 =
388 list1.AppendByMoving(&moved_point1, sizeof(Point2D), ALIGNOF(Point2D));
387 EXPECT_EQ(&moved_point2, &list1.last()); 389 EXPECT_EQ(&moved_point2, &list1.last());
388 EXPECT_NE(&moved_point1, &moved_point2); 390 EXPECT_NE(&moved_point1, &moved_point2);
389 } 391 }
390 392
391 TEST(ContiguousContainerTest, AppendByMovingReplacesSourceWithNewElement) { 393 TEST(ContiguousContainerTest, AppendByMovingReplacesSourceWithNewElement) {
392 ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); 394 ContiguousContainer<Point2D> list1(kMaxPointSize);
393 ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); 395 ContiguousContainer<Point2D> list2(kMaxPointSize);
394 396
395 list1.AllocateAndConstruct<Point2D>(1, 2); 397 list1.AllocateAndConstruct<Point2D>(1, 2);
396 EXPECT_EQ(1, list1.first().x); 398 EXPECT_EQ(1, list1.first().x);
397 EXPECT_EQ(2, list1.first().y); 399 EXPECT_EQ(2, list1.first().y);
398 400
399 list2.AppendByMoving(&list1.first(), sizeof(Point2D)); 401 list2.AppendByMoving(&list1.first(), sizeof(Point2D), ALIGNOF(Point2D));
400 EXPECT_EQ(0, list1.first().x); 402 EXPECT_EQ(0, list1.first().x);
401 EXPECT_EQ(0, list1.first().y); 403 EXPECT_EQ(0, list1.first().y);
402 EXPECT_EQ(1, list2.first().x); 404 EXPECT_EQ(1, list2.first().x);
403 EXPECT_EQ(2, list2.first().y); 405 EXPECT_EQ(2, list2.first().y);
404 406
405 EXPECT_EQ(1u, list1.size()); 407 EXPECT_EQ(1u, list1.size());
406 EXPECT_EQ(1u, list2.size()); 408 EXPECT_EQ(1u, list2.size());
407 } 409 }
408 410
409 TEST(ContiguousContainerTest, AppendByMovingElementsOfDifferentSizes) { 411 TEST(ContiguousContainerTest, AppendByMovingElementsOfDifferentSizes) {
410 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 412 ContiguousContainer<Point2D> list(kMaxPointSize);
411 list.AllocateAndConstruct<Point3D>(1, 2, 3); 413 list.AllocateAndConstruct<Point3D>(1, 2, 3);
412 list.AllocateAndConstruct<Point2D>(4, 5); 414 list.AllocateAndConstruct<Point2D>(4, 5);
413 415
414 EXPECT_EQ(1, list[0].x); 416 EXPECT_EQ(1, list[0].x);
415 EXPECT_EQ(2, list[0].y); 417 EXPECT_EQ(2, list[0].y);
416 EXPECT_EQ(3, static_cast<const Point3D&>(list[0]).z); 418 EXPECT_EQ(3, static_cast<const Point3D&>(list[0]).z);
417 EXPECT_EQ(4, list[1].x); 419 EXPECT_EQ(4, list[1].x);
418 EXPECT_EQ(5, list[1].y); 420 EXPECT_EQ(5, list[1].y);
419 421
420 // Test that moving the first element actually moves the entire object, not 422 // Test that moving the first element actually moves the entire object, not
421 // just the base element. 423 // just the base element.
422 list.AppendByMoving(&list[0], sizeof(Point3D)); 424 list.AppendByMoving(&list[0], sizeof(Point3D), ALIGNOF(Point3D));
423 EXPECT_EQ(1, list[2].x); 425 EXPECT_EQ(1, list[2].x);
424 EXPECT_EQ(2, list[2].y); 426 EXPECT_EQ(2, list[2].y);
425 EXPECT_EQ(3, static_cast<const Point3D&>(list[2]).z); 427 EXPECT_EQ(3, static_cast<const Point3D&>(list[2]).z);
426 EXPECT_EQ(4, list[1].x); 428 EXPECT_EQ(4, list[1].x);
427 EXPECT_EQ(5, list[1].y); 429 EXPECT_EQ(5, list[1].y);
428 430
429 list.AppendByMoving(&list[1], sizeof(Point2D)); 431 list.AppendByMoving(&list[1], sizeof(Point2D), ALIGNOF(Point2D));
430 EXPECT_EQ(1, list[2].x); 432 EXPECT_EQ(1, list[2].x);
431 EXPECT_EQ(2, list[2].y); 433 EXPECT_EQ(2, list[2].y);
432 EXPECT_EQ(3, static_cast<const Point3D&>(list[2]).z); 434 EXPECT_EQ(3, static_cast<const Point3D&>(list[2]).z);
433 EXPECT_EQ(4, list[3].x); 435 EXPECT_EQ(4, list[3].x);
434 EXPECT_EQ(5, list[3].y); 436 EXPECT_EQ(5, list[3].y);
435 } 437 }
436 438
437 TEST(ContiguousContainerTest, Swap) { 439 TEST(ContiguousContainerTest, Swap) {
438 ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); 440 ContiguousContainer<Point2D> list1(kMaxPointSize);
439 list1.AllocateAndConstruct<Point2D>(1, 2); 441 list1.AllocateAndConstruct<Point2D>(1, 2);
440 ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); 442 ContiguousContainer<Point2D> list2(kMaxPointSize);
441 list2.AllocateAndConstruct<Point2D>(3, 4); 443 list2.AllocateAndConstruct<Point2D>(3, 4);
442 list2.AllocateAndConstruct<Point2D>(5, 6); 444 list2.AllocateAndConstruct<Point2D>(5, 6);
443 445
444 EXPECT_EQ(1u, list1.size()); 446 EXPECT_EQ(1u, list1.size());
445 EXPECT_EQ(1, list1[0].x); 447 EXPECT_EQ(1, list1[0].x);
446 EXPECT_EQ(2, list1[0].y); 448 EXPECT_EQ(2, list1[0].y);
447 EXPECT_EQ(2u, list2.size()); 449 EXPECT_EQ(2u, list2.size());
448 EXPECT_EQ(3, list2[0].x); 450 EXPECT_EQ(3, list2[0].x);
449 EXPECT_EQ(4, list2[0].y); 451 EXPECT_EQ(4, list2[0].y);
450 EXPECT_EQ(5, list2[1].x); 452 EXPECT_EQ(5, list2[1].x);
(...skipping 18 matching lines...) Expand all
469 471
470 // At time of writing, removing elements from the end can cause up to 7x the 472 // At time of writing, removing elements from the end can cause up to 7x the
471 // memory required to be consumed, in the worst case, since we can have up to 473 // memory required to be consumed, in the worst case, since we can have up to
472 // two trailing inner lists that are empty (for 2*size + 4*size in unused 474 // two trailing inner lists that are empty (for 2*size + 4*size in unused
473 // memory, due to the exponential growth strategy). 475 // memory, due to the exponential growth strategy).
474 // Unfortunately, this captures behaviour of the underlying allocator as 476 // Unfortunately, this captures behaviour of the underlying allocator as
475 // well as this container, so we're pretty loose here. This constant may 477 // well as this container, so we're pretty loose here. This constant may
476 // need to be adjusted. 478 // need to be adjusted.
477 const size_t max_waste_factor = 8; 479 const size_t max_waste_factor = 8;
478 480
479 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize, 481 ContiguousContainer<Point2D> list(kMaxPointSize, initial_capacity);
480 initial_capacity);
481 482
482 // The capacity should grow with the list. 483 // The capacity should grow with the list.
483 for (int i = 0; i < iterations; i++) { 484 for (int i = 0; i < iterations; i++) {
484 size_t capacity = list.GetCapacityInBytes(); 485 size_t capacity = list.GetCapacityInBytes();
485 ASSERT_GE(capacity, list.size() * sizeof(Point2D)); 486 ASSERT_GE(capacity, list.size() * sizeof(Point2D));
486 ASSERT_LE(capacity, std::max(list.size() * sizeof(Point2D), 487 ASSERT_LE(capacity, std::max(list.size() * sizeof(Point2D),
487 upper_bound_on_min_capacity) * 488 upper_bound_on_min_capacity) *
488 max_waste_factor); 489 max_waste_factor);
489 list.AllocateAndConstruct<Point2D>(); 490 list.AllocateAndConstruct<Point2D>();
490 } 491 }
491 492
492 // The capacity should shrink with the list. 493 // The capacity should shrink with the list.
493 for (int i = 0; i < iterations; i++) { 494 for (int i = 0; i < iterations; i++) {
494 size_t capacity = list.GetCapacityInBytes(); 495 size_t capacity = list.GetCapacityInBytes();
495 ASSERT_GE(capacity, list.size() * sizeof(Point2D)); 496 ASSERT_GE(capacity, list.size() * sizeof(Point2D));
496 ASSERT_LE(capacity, std::max(list.size() * sizeof(Point2D), 497 ASSERT_LE(capacity, std::max(list.size() * sizeof(Point2D),
497 upper_bound_on_min_capacity) * 498 upper_bound_on_min_capacity) *
498 max_waste_factor); 499 max_waste_factor);
499 list.RemoveLast(); 500 list.RemoveLast();
500 } 501 }
501 } 502 }
502 503
503 TEST(ContiguousContainerTest, CapacityInBytesAfterClear) { 504 TEST(ContiguousContainerTest, CapacityInBytesAfterClear) {
504 // Clearing should restore the capacity of the container to the same as a 505 // Clearing should restore the capacity of the container to the same as a
505 // newly allocated one (without reserved capacity requested). 506 // newly allocated one (without reserved capacity requested).
506 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 507 ContiguousContainer<Point2D> list(kMaxPointSize);
507 size_t empty_capacity = list.GetCapacityInBytes(); 508 size_t empty_capacity = list.GetCapacityInBytes();
508 list.AllocateAndConstruct<Point2D>(); 509 list.AllocateAndConstruct<Point2D>();
509 list.AllocateAndConstruct<Point2D>(); 510 list.AllocateAndConstruct<Point2D>();
510 list.Clear(); 511 list.Clear();
511 EXPECT_EQ(empty_capacity, list.GetCapacityInBytes()); 512 EXPECT_EQ(empty_capacity, list.GetCapacityInBytes());
512 } 513 }
513 514
514 } // namespace 515 TEST(ContiguousContainerTest, Alignment) {
516 ContiguousContainer<char> container(256, 256);
517 void* item1 = container.Allocate(5, 128);
518 ASSERT_TRUE(item1);
519 EXPECT_EQ(0u, reinterpret_cast<size_t>(item1) & 0x7F);
520 EXPECT_GE(container.UsedCapacityInBytes(), 5u);
521 // The initial gap may not be consistent among runs.
522 // |initial_gap|--5--|---------------------unused--------------------------|
523 // |item1|
524 size_t initial_gap = container.UsedCapacityInBytes() - 5;
525
526 void* item2 = container.Allocate(11, 64);
527 ASSERT_TRUE(item2);
528 EXPECT_EQ(0u, reinterpret_cast<size_t>(item2) & 0x3F);
529 // |initial_gap|-------64--------|-11--|--------------unused---------------|
530 // |item1| |item2|
531 EXPECT_EQ(initial_gap + 64u + 11u, container.UsedCapacityInBytes());
532
533 void* item3 = container.Allocate(13, 32);
534 ASSERT_TRUE(item3);
535 EXPECT_EQ(0u, reinterpret_cast<size_t>(item3) & 0x1F);
536 // |initial_gap|-------64--------|----32-----|-13--|-------unused----------|
537 // |item1| |item2| |item3|
538 EXPECT_EQ(initial_gap + 64u + 32u + 13u, container.UsedCapacityInBytes());
539
540 void* item4 = container.Allocate(7, 16);
541 ASSERT_TRUE(item4);
542 EXPECT_EQ(0u, reinterpret_cast<size_t>(item4) & 0x0F);
543 // |initial_gap|-------64--------|----32-----|---16----|--7--|---unused----|
544 // |item1| |item2| |item3| |item4|
545 EXPECT_EQ(initial_gap + 64u + 32u + 16u + 7u,
546 container.UsedCapacityInBytes());
547
548 // All of the above allocations should be in the initial buffer.
549 EXPECT_EQ(container.GetCapacityInBytes(), 256u);
550
551 // item5 may or may not be allocated in the initial buffer, depending on
552 // initial_gap.
553 void* item5 = container.Allocate(9, 16);
554 ASSERT_TRUE(item5);
555 EXPECT_EQ(0u, reinterpret_cast<size_t>(item5) & 0x0F);
556
557 // Definitely the initial buffer can't hold another small object aligned at
558 // 128 bytes, because the buffer has no more available 128-byte aligned
559 // address.
560 void* item6 = container.Allocate(17, 128);
561 ASSERT_TRUE(item6);
562 EXPECT_EQ(0u, reinterpret_cast<size_t>(item6) & 0x3F);
563 EXPECT_GT(container.GetCapacityInBytes(), 256u);
564
565 container.RemoveLast(); // item6
566 container.RemoveLast(); // item5
567 // The container should retain the last empty buffer to avoid reallocation of
568 // buffer for new item allocations.
569 EXPECT_GT(container.GetCapacityInBytes(), 256u);
570
571 container.RemoveLast(); // item4
572 EXPECT_EQ(initial_gap + 64u + 32u + 16u, container.UsedCapacityInBytes());
573 }
574
515 } // namespace cc 575 } // namespace cc
OLDNEW
« no previous file with comments | « cc/base/contiguous_container.cc ('k') | third_party/WebKit/Source/core/paint/PaintControllerPaintTest.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698