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

Side by Side Diff: third_party/WebKit/Source/platform/graphics/ContiguousContainerTest.cpp

Issue 2119033003: Fix alignment issue of ContiguousContainer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase 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 "platform/graphics/ContiguousContainer.h" 5 #include "platform/graphics/ContiguousContainer.h"
6 6
7 #include "testing/gmock/include/gmock/gmock.h" 7 #include "testing/gmock/include/gmock/gmock.h"
8 #include "testing/gtest/include/gtest/gtest.h" 8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "wtf/TypeTraits.h" 9 #include "wtf/TypeTraits.h"
10 10
11 namespace blink { 11 namespace blink {
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 unsigned kNumElements = 150; 30 static const unsigned kNumElements = 150;
34 31
32 } // namespace
33
35 TEST(ContiguousContainerTest, SimpleStructs) 34 TEST(ContiguousContainerTest, SimpleStructs)
36 { 35 {
37 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 36 ContiguousContainer<Point2D> list(kMaxPointSize);
38 list.allocateAndConstruct<Point2D>(1, 2); 37 list.allocateAndConstruct<Point2D>(1, 2);
39 list.allocateAndConstruct<Point3D>(3, 4, 5); 38 list.allocateAndConstruct<Point3D>(3, 4, 5);
40 list.allocateAndConstruct<Point2D>(6, 7); 39 list.allocateAndConstruct<Point2D>(6, 7);
41 40
42 ASSERT_EQ(3u, list.size()); 41 ASSERT_EQ(3u, list.size());
43 EXPECT_EQ(1, list[0].x); 42 EXPECT_EQ(1, list[0].x);
44 EXPECT_EQ(2, list[0].y); 43 EXPECT_EQ(2, list[0].y);
45 EXPECT_EQ(3, list[1].x); 44 EXPECT_EQ(3, list[1].x);
46 EXPECT_EQ(4, list[1].y); 45 EXPECT_EQ(4, list[1].y);
47 EXPECT_EQ(5, static_cast<Point3D&>(list[1]).z); 46 EXPECT_EQ(5, static_cast<Point3D&>(list[1]).z);
48 EXPECT_EQ(6, list[2].x); 47 EXPECT_EQ(6, list[2].x);
49 EXPECT_EQ(7, list[2].y); 48 EXPECT_EQ(7, list[2].y);
50 } 49 }
51 50
52 TEST(ContiguousContainerTest, AllocateLots) 51 TEST(ContiguousContainerTest, AllocateLots)
53 { 52 {
54 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 53 ContiguousContainer<Point2D> list(kMaxPointSize);
55 for (int i = 0; i < (int)kNumElements; i++) { 54 for (int i = 0; i < (int)kNumElements; i++) {
56 list.allocateAndConstruct<Point2D>(i, i); 55 list.allocateAndConstruct<Point2D>(i, i);
57 list.allocateAndConstruct<Point2D>(i, i); 56 list.allocateAndConstruct<Point2D>(i, i);
58 list.removeLast(); 57 list.removeLast();
59 } 58 }
60 ASSERT_EQ(kNumElements, list.size()); 59 ASSERT_EQ(kNumElements, list.size());
61 for (int i = 0; i < (int)kNumElements; i++) { 60 for (int i = 0; i < (int)kNumElements; i++) {
62 ASSERT_EQ(i, list[i].x); 61 ASSERT_EQ(i, list[i].x);
63 ASSERT_EQ(i, list[i].y); 62 ASSERT_EQ(i, list[i].y);
64 } 63 }
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 EXPECT_EQ(3u, list.size()); 165 EXPECT_EQ(3u, list.size());
167 166
168 // The remaining ones are destroyed when the test finishes. 167 // The remaining ones are destroyed when the test finishes.
169 EXPECT_CALL(list[2], destruct()); 168 EXPECT_CALL(list[2], destruct());
170 EXPECT_CALL(list[1], destruct()); 169 EXPECT_CALL(list[1], destruct());
171 EXPECT_CALL(list[0], destruct()); 170 EXPECT_CALL(list[0], destruct());
172 } 171 }
173 172
174 TEST(ContiguousContainerTest, InsertionAndIndexedAccess) 173 TEST(ContiguousContainerTest, InsertionAndIndexedAccess)
175 { 174 {
176 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 175 ContiguousContainer<Point2D> list(kMaxPointSize);
177 176
178 auto& point1 = list.allocateAndConstruct<Point2D>(); 177 auto& point1 = list.allocateAndConstruct<Point2D>();
179 auto& point2 = list.allocateAndConstruct<Point2D>(); 178 auto& point2 = list.allocateAndConstruct<Point2D>();
180 auto& point3 = list.allocateAndConstruct<Point2D>(); 179 auto& point3 = list.allocateAndConstruct<Point2D>();
181 180
182 EXPECT_EQ(3u, list.size()); 181 EXPECT_EQ(3u, list.size());
183 EXPECT_EQ(&point1, &list.first()); 182 EXPECT_EQ(&point1, &list.first());
184 EXPECT_EQ(&point3, &list.last()); 183 EXPECT_EQ(&point3, &list.last());
185 EXPECT_EQ(&point1, &list[0]); 184 EXPECT_EQ(&point1, &list[0]);
186 EXPECT_EQ(&point2, &list[1]); 185 EXPECT_EQ(&point2, &list[1]);
187 EXPECT_EQ(&point3, &list[2]); 186 EXPECT_EQ(&point3, &list[2]);
188 } 187 }
189 188
190 TEST(ContiguousContainerTest, InsertionAndClear) 189 TEST(ContiguousContainerTest, InsertionAndClear)
191 { 190 {
192 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 191 ContiguousContainer<Point2D> list(kMaxPointSize);
193 EXPECT_TRUE(list.isEmpty()); 192 EXPECT_TRUE(list.isEmpty());
194 EXPECT_EQ(0u, list.size()); 193 EXPECT_EQ(0u, list.size());
195 194
196 list.allocateAndConstruct<Point2D>(); 195 list.allocateAndConstruct<Point2D>();
197 EXPECT_FALSE(list.isEmpty()); 196 EXPECT_FALSE(list.isEmpty());
198 EXPECT_EQ(1u, list.size()); 197 EXPECT_EQ(1u, list.size());
199 198
200 list.clear(); 199 list.clear();
201 EXPECT_TRUE(list.isEmpty()); 200 EXPECT_TRUE(list.isEmpty());
202 EXPECT_EQ(0u, list.size()); 201 EXPECT_EQ(0u, list.size());
203 202
204 list.allocateAndConstruct<Point2D>(); 203 list.allocateAndConstruct<Point2D>();
205 EXPECT_FALSE(list.isEmpty()); 204 EXPECT_FALSE(list.isEmpty());
206 EXPECT_EQ(1u, list.size()); 205 EXPECT_EQ(1u, list.size());
207 } 206 }
208 207
209 TEST(ContiguousContainerTest, ElementAddressesAreStable) 208 TEST(ContiguousContainerTest, ElementAddressesAreStable)
210 { 209 {
211 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 210 ContiguousContainer<Point2D> list(kMaxPointSize);
212 Vector<Point2D*> pointers; 211 Vector<Point2D*> pointers;
213 for (int i = 0; i < (int)kNumElements; i++) 212 for (int i = 0; i < (int)kNumElements; i++)
214 pointers.append(&list.allocateAndConstruct<Point2D>()); 213 pointers.append(&list.allocateAndConstruct<Point2D>());
215 EXPECT_EQ(kNumElements, list.size()); 214 EXPECT_EQ(kNumElements, list.size());
216 EXPECT_EQ(kNumElements, pointers.size()); 215 EXPECT_EQ(kNumElements, pointers.size());
217 216
218 auto listIt = list.begin(); 217 auto listIt = list.begin();
219 auto vectorIt = pointers.begin(); 218 auto vectorIt = pointers.begin();
220 for (; listIt != list.end(); ++listIt, ++vectorIt) 219 for (; listIt != list.end(); ++listIt, ++vectorIt)
221 EXPECT_EQ(&*listIt, *vectorIt); 220 EXPECT_EQ(&*listIt, *vectorIt);
222 } 221 }
223 222
224 TEST(ContiguousContainerTest, ForwardIteration) 223 TEST(ContiguousContainerTest, ForwardIteration)
225 { 224 {
226 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 225 ContiguousContainer<Point2D> list(kMaxPointSize);
227 for (int i = 0; i < (int)kNumElements; i++) 226 for (int i = 0; i < (int)kNumElements; i++)
228 list.allocateAndConstruct<Point2D>(i, i); 227 list.allocateAndConstruct<Point2D>(i, i);
229 unsigned count = 0; 228 unsigned count = 0;
230 for (Point2D& point : list) { 229 for (Point2D& point : list) {
231 EXPECT_EQ((int)count, point.x); 230 EXPECT_EQ((int)count, point.x);
232 count++; 231 count++;
233 } 232 }
234 EXPECT_EQ(kNumElements, count); 233 EXPECT_EQ(kNumElements, count);
235 234
236 static_assert(std::is_same<decltype(*list.begin()), Point2D&>::value, 235 static_assert(std::is_same<decltype(*list.begin()), Point2D&>::value,
237 "Non-const iteration should produce non-const references."); 236 "Non-const iteration should produce non-const references.");
238 } 237 }
239 238
240 TEST(ContiguousContainerTest, ConstForwardIteration) 239 TEST(ContiguousContainerTest, ConstForwardIteration)
241 { 240 {
242 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 241 ContiguousContainer<Point2D> list(kMaxPointSize);
243 for (int i = 0; i < (int)kNumElements; i++) 242 for (int i = 0; i < (int)kNumElements; i++)
244 list.allocateAndConstruct<Point2D>(i, i); 243 list.allocateAndConstruct<Point2D>(i, i);
245 244
246 const auto& constList = list; 245 const auto& constList = list;
247 unsigned count = 0; 246 unsigned count = 0;
248 for (const Point2D& point : constList) { 247 for (const Point2D& point : constList) {
249 EXPECT_EQ((int)count, point.x); 248 EXPECT_EQ((int)count, point.x);
250 count++; 249 count++;
251 } 250 }
252 EXPECT_EQ(kNumElements, count); 251 EXPECT_EQ(kNumElements, count);
253 252
254 static_assert(std::is_same<decltype(*constList.begin()), const Point2D&>::va lue, 253 static_assert(std::is_same<decltype(*constList.begin()), const Point2D&>::va lue,
255 "Const iteration should produce const references."); 254 "Const iteration should produce const references.");
256 } 255 }
257 256
258 TEST(ContiguousContainerTest, ReverseIteration) 257 TEST(ContiguousContainerTest, ReverseIteration)
259 { 258 {
260 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 259 ContiguousContainer<Point2D> list(kMaxPointSize);
261 for (int i = 0; i < (int)kNumElements; i++) 260 for (int i = 0; i < (int)kNumElements; i++)
262 list.allocateAndConstruct<Point2D>(i, i); 261 list.allocateAndConstruct<Point2D>(i, i);
263 262
264 unsigned count = 0; 263 unsigned count = 0;
265 for (auto it = list.rbegin(); it != list.rend(); ++it) { 264 for (auto it = list.rbegin(); it != list.rend(); ++it) {
266 EXPECT_EQ((int)(kNumElements - 1 - count), it->x); 265 EXPECT_EQ((int)(kNumElements - 1 - count), it->x);
267 count++; 266 count++;
268 } 267 }
269 EXPECT_EQ(kNumElements, count); 268 EXPECT_EQ(kNumElements, count);
270 269
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 check_equal(); // One full, one empty. 333 check_equal(); // One full, one empty.
335 push(); 334 push();
336 pop(); 335 pop();
337 pop(); 336 pop();
338 ASSERT_TRUE(list.isEmpty()); 337 ASSERT_TRUE(list.isEmpty());
339 check_equal(); // Empty. 338 check_equal(); // Empty.
340 } 339 }
341 340
342 TEST(ContiguousContainerTest, AppendByMovingSameList) 341 TEST(ContiguousContainerTest, AppendByMovingSameList)
343 { 342 {
344 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 343 ContiguousContainer<Point2D> list(kMaxPointSize);
345 list.allocateAndConstruct<Point3D>(1, 2, 3); 344 list.allocateAndConstruct<Point3D>(1, 2, 3);
346 345
347 // Moves the Point3D to the end, and default-constructs a Point2D in its 346 // Moves the Point3D to the end, and default-constructs a Point2D in its
348 // place. 347 // place.
349 list.appendByMoving(list.first(), sizeof(Point3D)); 348 list.appendByMoving(list.first(), sizeof(Point3D), log2Alignment<Point3D>()) ;
350 EXPECT_EQ(1, list.last().x); 349 EXPECT_EQ(1, list.last().x);
351 EXPECT_EQ(2, list.last().y); 350 EXPECT_EQ(2, list.last().y);
352 EXPECT_EQ(3, static_cast<const Point3D&>(list.last()).z); 351 EXPECT_EQ(3, static_cast<const Point3D&>(list.last()).z);
353 EXPECT_EQ(2u, list.size()); 352 EXPECT_EQ(2u, list.size());
354 353
355 // Moves that Point2D to the end, and default-constructs another in its 354 // Moves that Point2D to the end, and default-constructs another in its
356 // place. 355 // place.
357 list.first().x = 4; 356 list.first().x = 4;
358 list.appendByMoving(list.first(), sizeof(Point2D)); 357 list.appendByMoving(list.first(), sizeof(Point2D), log2Alignment<Point2D>()) ;
359 EXPECT_EQ(4, list.last().x); 358 EXPECT_EQ(4, list.last().x);
360 EXPECT_EQ(3u, list.size()); 359 EXPECT_EQ(3u, list.size());
361 } 360 }
362 361
363 TEST(ContiguousContainerTest, AppendByMovingDoesNotDestruct) 362 TEST(ContiguousContainerTest, AppendByMovingDoesNotDestruct)
364 { 363 {
365 // GMock mock objects (e.g. MockDestructible) aren't guaranteed to be safe 364 // GMock mock objects (e.g. MockDestructible) aren't guaranteed to be safe
366 // to memcpy (which is required for appendByMoving). 365 // to memcpy (which is required for appendByMoving).
367 class DestructionNotifier { 366 class DestructionNotifier {
368 public: 367 public:
369 DestructionNotifier(bool* flag = nullptr) : m_flag(flag) { } 368 DestructionNotifier(bool* flag = nullptr) : m_flag(flag) { }
370 ~DestructionNotifier() { if (m_flag) *m_flag = true; } 369 ~DestructionNotifier() { if (m_flag) *m_flag = true; }
371 private: 370 private:
372 bool* m_flag; 371 bool* m_flag;
373 }; 372 };
374 373
375 bool destroyed = false; 374 bool destroyed = false;
376 ContiguousContainer<DestructionNotifier> list1(sizeof(DestructionNotifier)); 375 ContiguousContainer<DestructionNotifier> list1(sizeof(DestructionNotifier));
377 list1.allocateAndConstruct<DestructionNotifier>(&destroyed); 376 list1.allocateAndConstruct<DestructionNotifier>(&destroyed);
378 { 377 {
379 // Make sure destructor isn't called during appendByMoving. 378 // Make sure destructor isn't called during appendByMoving.
380 ContiguousContainer<DestructionNotifier> list2(sizeof(DestructionNotifie r)); 379 ContiguousContainer<DestructionNotifier> list2(sizeof(DestructionNotifie r));
381 list2.appendByMoving(list1.last(), sizeof(DestructionNotifier)); 380 list2.appendByMoving(list1.last(), sizeof(DestructionNotifier), log2Alig nment<DestructionNotifier>());
382 EXPECT_FALSE(destroyed); 381 EXPECT_FALSE(destroyed);
383 } 382 }
384 // But it should be destroyed when list2 is. 383 // But it should be destroyed when list2 is.
385 EXPECT_TRUE(destroyed); 384 EXPECT_TRUE(destroyed);
386 } 385 }
387 386
388 TEST(ContiguousContainerTest, AppendByMovingReturnsMovedPointer) 387 TEST(ContiguousContainerTest, AppendByMovingReturnsMovedPointer)
389 { 388 {
390 ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); 389 ContiguousContainer<Point2D> list1(kMaxPointSize);
391 ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); 390 ContiguousContainer<Point2D> list2(kMaxPointSize);
392 391
393 Point2D& point = list1.allocateAndConstruct<Point2D>(); 392 Point2D& point = list1.allocateAndConstruct<Point2D>();
394 Point2D& movedPoint1 = list2.appendByMoving(point, sizeof(Point2D)); 393 Point2D& movedPoint1 = list2.appendByMoving(point, sizeof(Point2D), log2Alig nment<Point2D>());
395 EXPECT_EQ(&movedPoint1, &list2.last()); 394 EXPECT_EQ(&movedPoint1, &list2.last());
396 395
397 Point2D& movedPoint2 = list1.appendByMoving(movedPoint1, sizeof(Point2D)); 396 Point2D& movedPoint2 = list1.appendByMoving(movedPoint1, sizeof(Point2D), lo g2Alignment<Point2D>());
398 EXPECT_EQ(&movedPoint2, &list1.last()); 397 EXPECT_EQ(&movedPoint2, &list1.last());
399 EXPECT_NE(&movedPoint1, &movedPoint2); 398 EXPECT_NE(&movedPoint1, &movedPoint2);
400 } 399 }
401 400
402 TEST(ContiguousContainerTest, AppendByMovingReplacesSourceWithNewElement) 401 TEST(ContiguousContainerTest, AppendByMovingReplacesSourceWithNewElement)
403 { 402 {
404 ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); 403 ContiguousContainer<Point2D> list1(kMaxPointSize);
405 ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); 404 ContiguousContainer<Point2D> list2(kMaxPointSize);
406 405
407 list1.allocateAndConstruct<Point2D>(1, 2); 406 list1.allocateAndConstruct<Point2D>(1, 2);
408 EXPECT_EQ(1, list1.first().x); 407 EXPECT_EQ(1, list1.first().x);
409 EXPECT_EQ(2, list1.first().y); 408 EXPECT_EQ(2, list1.first().y);
410 409
411 list2.appendByMoving(list1.first(), sizeof(Point2D)); 410 list2.appendByMoving(list1.first(), sizeof(Point2D), log2Alignment<Point2D>( ));
412 EXPECT_EQ(0, list1.first().x); 411 EXPECT_EQ(0, list1.first().x);
413 EXPECT_EQ(0, list1.first().y); 412 EXPECT_EQ(0, list1.first().y);
414 EXPECT_EQ(1, list2.first().x); 413 EXPECT_EQ(1, list2.first().x);
415 EXPECT_EQ(2, list2.first().y); 414 EXPECT_EQ(2, list2.first().y);
416 415
417 EXPECT_EQ(1u, list1.size()); 416 EXPECT_EQ(1u, list1.size());
418 EXPECT_EQ(1u, list2.size()); 417 EXPECT_EQ(1u, list2.size());
419 } 418 }
420 419
421 TEST(ContiguousContainerTest, AppendByMovingElementsOfDifferentSizes) 420 TEST(ContiguousContainerTest, AppendByMovingElementsOfDifferentSizes)
422 { 421 {
423 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 422 ContiguousContainer<Point2D> list(kMaxPointSize);
424 list.allocateAndConstruct<Point3D>(1, 2, 3); 423 list.allocateAndConstruct<Point3D>(1, 2, 3);
425 list.allocateAndConstruct<Point2D>(4, 5); 424 list.allocateAndConstruct<Point2D>(4, 5);
426 425
427 EXPECT_EQ(1, list[0].x); 426 EXPECT_EQ(1, list[0].x);
428 EXPECT_EQ(2, list[0].y); 427 EXPECT_EQ(2, list[0].y);
429 EXPECT_EQ(3, static_cast<const Point3D&>(list[0]).z); 428 EXPECT_EQ(3, static_cast<const Point3D&>(list[0]).z);
430 EXPECT_EQ(4, list[1].x); 429 EXPECT_EQ(4, list[1].x);
431 EXPECT_EQ(5, list[1].y); 430 EXPECT_EQ(5, list[1].y);
432 431
433 // Test that moving the first element actually moves the entire object, not 432 // Test that moving the first element actually moves the entire object, not
434 // just the base element. 433 // just the base element.
435 list.appendByMoving(list[0], sizeof(Point3D)); 434 list.appendByMoving(list[0], sizeof(Point3D), log2Alignment<Point3D>());
436 EXPECT_EQ(1, list[2].x); 435 EXPECT_EQ(1, list[2].x);
437 EXPECT_EQ(2, list[2].y); 436 EXPECT_EQ(2, list[2].y);
438 EXPECT_EQ(3, static_cast<const Point3D&>(list[2]).z); 437 EXPECT_EQ(3, static_cast<const Point3D&>(list[2]).z);
439 EXPECT_EQ(4, list[1].x); 438 EXPECT_EQ(4, list[1].x);
440 EXPECT_EQ(5, list[1].y); 439 EXPECT_EQ(5, list[1].y);
441 440
442 list.appendByMoving(list[1], sizeof(Point2D)); 441 list.appendByMoving(list[1], sizeof(Point2D), log2Alignment<Point2D>());
443 EXPECT_EQ(1, list[2].x); 442 EXPECT_EQ(1, list[2].x);
444 EXPECT_EQ(2, list[2].y); 443 EXPECT_EQ(2, list[2].y);
445 EXPECT_EQ(3, static_cast<const Point3D&>(list[2]).z); 444 EXPECT_EQ(3, static_cast<const Point3D&>(list[2]).z);
446 EXPECT_EQ(4, list[3].x); 445 EXPECT_EQ(4, list[3].x);
447 EXPECT_EQ(5, list[3].y); 446 EXPECT_EQ(5, list[3].y);
448 } 447 }
449 448
450 TEST(ContiguousContainerTest, Swap) 449 TEST(ContiguousContainerTest, Swap)
451 { 450 {
452 ContiguousContainer<Point2D, kPointAlignment> list1(kMaxPointSize); 451 ContiguousContainer<Point2D> list1(kMaxPointSize);
453 list1.allocateAndConstruct<Point2D>(1, 2); 452 list1.allocateAndConstruct<Point2D>(1, 2);
454 ContiguousContainer<Point2D, kPointAlignment> list2(kMaxPointSize); 453 ContiguousContainer<Point2D> list2(kMaxPointSize);
455 list2.allocateAndConstruct<Point2D>(3, 4); 454 list2.allocateAndConstruct<Point2D>(3, 4);
456 list2.allocateAndConstruct<Point2D>(5, 6); 455 list2.allocateAndConstruct<Point2D>(5, 6);
457 456
458 EXPECT_EQ(1u, list1.size()); 457 EXPECT_EQ(1u, list1.size());
459 EXPECT_EQ(1, list1[0].x); 458 EXPECT_EQ(1, list1[0].x);
460 EXPECT_EQ(2, list1[0].y); 459 EXPECT_EQ(2, list1[0].y);
461 EXPECT_EQ(2u, list2.size()); 460 EXPECT_EQ(2u, list2.size());
462 EXPECT_EQ(3, list2[0].x); 461 EXPECT_EQ(3, list2[0].x);
463 EXPECT_EQ(4, list2[0].y); 462 EXPECT_EQ(4, list2[0].y);
464 EXPECT_EQ(5, list2[1].x); 463 EXPECT_EQ(5, list2[1].x);
(...skipping 19 matching lines...) Expand all
484 483
485 // At time of writing, removing elements from the end can cause up to 7x the 484 // At time of writing, removing elements from the end can cause up to 7x the
486 // memory required to be consumed, in the worst case, since we can have up t o 485 // memory required to be consumed, in the worst case, since we can have up t o
487 // two trailing inner lists that are empty (for 2*size + 4*size in unused 486 // two trailing inner lists that are empty (for 2*size + 4*size in unused
488 // memory, due to the exponential growth strategy). 487 // memory, due to the exponential growth strategy).
489 // Unfortunately, this captures behaviour of the underlying allocator as 488 // Unfortunately, this captures behaviour of the underlying allocator as
490 // well as this container, so we're pretty loose here. This constant may 489 // well as this container, so we're pretty loose here. This constant may
491 // need to be adjusted. 490 // need to be adjusted.
492 const size_t maxWasteFactor = 8; 491 const size_t maxWasteFactor = 8;
493 492
494 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize, initialCap acity); 493 ContiguousContainer<Point2D> list(kMaxPointSize, initialCapacity);
495 494
496 // The capacity should grow with the list. 495 // The capacity should grow with the list.
497 for (int i = 0; i < iterations; i++) { 496 for (int i = 0; i < iterations; i++) {
498 size_t capacity = list.capacityInBytes(); 497 size_t capacity = list.capacityInBytes();
499 ASSERT_GE(capacity, list.size() * sizeof(Point2D)); 498 ASSERT_GE(capacity, list.size() * sizeof(Point2D));
500 ASSERT_LE(capacity, 499 ASSERT_LE(capacity,
501 std::max(list.size() * sizeof(Point2D), upperBoundOnMinCapacity) * m axWasteFactor); 500 std::max(list.size() * sizeof(Point2D), upperBoundOnMinCapacity) * m axWasteFactor);
502 list.allocateAndConstruct<Point2D>(); 501 list.allocateAndConstruct<Point2D>();
503 } 502 }
504 503
505 // The capacity should shrink with the list. 504 // The capacity should shrink with the list.
506 for (int i = 0; i < iterations; i++) { 505 for (int i = 0; i < iterations; i++) {
507 size_t capacity = list.capacityInBytes(); 506 size_t capacity = list.capacityInBytes();
508 ASSERT_GE(capacity, list.size() * sizeof(Point2D)); 507 ASSERT_GE(capacity, list.size() * sizeof(Point2D));
509 ASSERT_LE(capacity, 508 ASSERT_LE(capacity,
510 std::max(list.size() * sizeof(Point2D), upperBoundOnMinCapacity) * m axWasteFactor); 509 std::max(list.size() * sizeof(Point2D), upperBoundOnMinCapacity) * m axWasteFactor);
511 list.removeLast(); 510 list.removeLast();
512 } 511 }
513 } 512 }
514 513
515 TEST(ContiguousContainerTest, CapacityInBytesAfterClear) 514 TEST(ContiguousContainerTest, CapacityInBytesAfterClear)
516 { 515 {
517 // Clearing should restore the capacity of the container to the same as a 516 // Clearing should restore the capacity of the container to the same as a
518 // newly allocated one (without reserved capacity requested). 517 // newly allocated one (without reserved capacity requested).
519 ContiguousContainer<Point2D, kPointAlignment> list(kMaxPointSize); 518 ContiguousContainer<Point2D> list(kMaxPointSize);
520 size_t emptyCapacity = list.capacityInBytes(); 519 size_t emptyCapacity = list.capacityInBytes();
521 list.allocateAndConstruct<Point2D>(); 520 list.allocateAndConstruct<Point2D>();
522 list.allocateAndConstruct<Point2D>(); 521 list.allocateAndConstruct<Point2D>();
523 list.clear(); 522 list.clear();
524 EXPECT_EQ(emptyCapacity, list.capacityInBytes()); 523 EXPECT_EQ(emptyCapacity, list.capacityInBytes());
525 } 524 }
526 525
527 } // namespace 526 TEST(ContiguousContainerTest, Alignment)
527 {
528 ContiguousContainer<char> container(64, 64);
529 void* item1 = container.allocate(21, 4); // alignment 16
530 ASSERT_TRUE(item1);
531 EXPECT_EQ(0u, reinterpret_cast<size_t>(item1) & 0x0F);
532 EXPECT_GE(21u, container.usedCapacityInBytes());
533 // The initial gap may not be consistent among runs.
534 // |--------21-------|-------------------43-----------------------|
535 // | item1 | unused |
536
537 void* item2 = container.allocate(9, 3); // alignment 8
538 ASSERT_TRUE(item2);
539 EXPECT_EQ(0u, reinterpret_cast<size_t>(item2) & 7);
540 // |---------24--------|---9---|----------------31----------------|
541 // | item1 | | item2 | unused |
542 EXPECT_EQ(24u + 9u, container.usedCapacityInBytes());
543
544 void* item3 = container.allocate(3, 2); // alignment 4
545 ASSERT_TRUE(item3);
546 EXPECT_EQ(0u, reinterpret_cast<size_t>(item3) & 3);
547 // |---------24--------|----12----|--3--|----------25-------------|
548 // | item1 | | item2 | |item3| unused |
549 EXPECT_EQ(24u + 12u + 3u, container.usedCapacityInBytes());
550
551 void* item4 = container.allocate(11, 0);
552 ASSERT_TRUE(item4);
553 // |---------24--------|----12----|--3--|---11---|-------14-------|
554 // | item1 | | item2 | |item3| item4 | unused |
555 EXPECT_EQ(24u + 12u + 3u + 11u, container.usedCapacityInBytes());
556
557 // All of the above allocations should be in the initial buffer.
558 EXPECT_EQ(64u, container.capacityInBytes());
559
560 // The initial buffer can't hold another object aligned at 16 bytes.
561 void* item5 = container.allocate(8, 4);
562 ASSERT_TRUE(item5);
563 EXPECT_EQ(0u, reinterpret_cast<size_t>(item5) & 0x0F);
564 EXPECT_GT(container.capacityInBytes(), 64u);
565
566 container.removeLast(); // item5
567 // The container should retain the last empty buffer to avoid reallocation o f
568 // buffer for new item allocations.
569 EXPECT_GT(container.capacityInBytes(), 64u);
570
571 container.removeLast(); // item4
572 EXPECT_EQ(24u + 12u + 3u, container.usedCapacityInBytes());
573 container.removeLast(); // item3
574 EXPECT_EQ(24u + 12u, container.usedCapacityInBytes());
575 container.removeLast(); // item2
576 EXPECT_EQ(24u, container.usedCapacityInBytes());
577 container.removeLast(); // item1
578 EXPECT_EQ(0u, container.usedCapacityInBytes());
579 }
580
528 } // namespace blink 581 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698