1 //===- llvm/unittest/ADT/SmallVectorTest.cpp ------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // SmallVector unit tests. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/ADT/SmallVector.h" 15 #include "llvm/Support/Compiler.h" 16 #include "gtest/gtest.h" 17 #include <list> 18 #include <stdarg.h> 19 20 using namespace llvm; 21 22 namespace { 23 24 /// A helper class that counts the total number of constructor and 25 /// destructor calls. 26 class Constructable { 27 private: 28 static int numConstructorCalls; 29 static int numMoveConstructorCalls; 30 static int numCopyConstructorCalls; 31 static int numDestructorCalls; 32 static int numAssignmentCalls; 33 static int numMoveAssignmentCalls; 34 static int numCopyAssignmentCalls; 35 36 bool constructed; 37 int value; 38 39 public: 40 Constructable() : constructed(true), value(0) { 41 ++numConstructorCalls; 42 } 43 44 Constructable(int val) : constructed(true), value(val) { 45 ++numConstructorCalls; 46 } 47 48 Constructable(const Constructable & src) : constructed(true) { 49 value = src.value; 50 ++numConstructorCalls; 51 ++numCopyConstructorCalls; 52 } 53 54 Constructable(Constructable && src) : constructed(true) { 55 value = src.value; 56 ++numConstructorCalls; 57 ++numMoveConstructorCalls; 58 } 59 60 ~Constructable() { 61 EXPECT_TRUE(constructed); 62 ++numDestructorCalls; 63 constructed = false; 64 } 65 66 Constructable & operator=(const Constructable & src) { 67 EXPECT_TRUE(constructed); 68 value = src.value; 69 ++numAssignmentCalls; 70 ++numCopyAssignmentCalls; 71 return *this; 72 } 73 74 Constructable & operator=(Constructable && src) { 75 EXPECT_TRUE(constructed); 76 value = src.value; 77 ++numAssignmentCalls; 78 ++numMoveAssignmentCalls; 79 return *this; 80 } 81 82 int getValue() const { 83 return abs(value); 84 } 85 86 static void reset() { 87 numConstructorCalls = 0; 88 numMoveConstructorCalls = 0; 89 numCopyConstructorCalls = 0; 90 numDestructorCalls = 0; 91 numAssignmentCalls = 0; 92 numMoveAssignmentCalls = 0; 93 numCopyAssignmentCalls = 0; 94 } 95 96 static int getNumConstructorCalls() { 97 return numConstructorCalls; 98 } 99 100 static int getNumMoveConstructorCalls() { 101 return numMoveConstructorCalls; 102 } 103 104 static int getNumCopyConstructorCalls() { 105 return numCopyConstructorCalls; 106 } 107 108 static int getNumDestructorCalls() { 109 return numDestructorCalls; 110 } 111 112 static int getNumAssignmentCalls() { 113 return numAssignmentCalls; 114 } 115 116 static int getNumMoveAssignmentCalls() { 117 return numMoveAssignmentCalls; 118 } 119 120 static int getNumCopyAssignmentCalls() { 121 return numCopyAssignmentCalls; 122 } 123 124 friend bool operator==(const Constructable & c0, const Constructable & c1) { 125 return c0.getValue() == c1.getValue(); 126 } 127 128 friend bool LLVM_ATTRIBUTE_UNUSED 129 operator!=(const Constructable & c0, const Constructable & c1) { 130 return c0.getValue() != c1.getValue(); 131 } 132 }; 133 134 int Constructable::numConstructorCalls; 135 int Constructable::numCopyConstructorCalls; 136 int Constructable::numMoveConstructorCalls; 137 int Constructable::numDestructorCalls; 138 int Constructable::numAssignmentCalls; 139 int Constructable::numCopyAssignmentCalls; 140 int Constructable::numMoveAssignmentCalls; 141 142 struct NonCopyable { 143 NonCopyable() {} 144 NonCopyable(NonCopyable &&) {} 145 NonCopyable &operator=(NonCopyable &&) { return *this; } 146 private: 147 NonCopyable(const NonCopyable &) LLVM_DELETED_FUNCTION; 148 NonCopyable &operator=(const NonCopyable &) LLVM_DELETED_FUNCTION; 149 }; 150 151 LLVM_ATTRIBUTE_USED void CompileTest() { 152 SmallVector<NonCopyable, 0> V; 153 V.resize(42); 154 } 155 156 // Test fixture class 157 template <typename VectorT> 158 class SmallVectorTest : public testing::Test { 159 protected: 160 VectorT theVector; 161 VectorT otherVector; 162 163 void SetUp() { 164 Constructable::reset(); 165 } 166 167 void assertEmpty(VectorT & v) { 168 // Size tests 169 EXPECT_EQ(0u, v.size()); 170 EXPECT_TRUE(v.empty()); 171 172 // Iterator tests 173 EXPECT_TRUE(v.begin() == v.end()); 174 } 175 176 // Assert that theVector contains the specified values, in order. 177 void assertValuesInOrder(VectorT & v, size_t size, ...) { 178 EXPECT_EQ(size, v.size()); 179 180 va_list ap; 181 va_start(ap, size); 182 for (size_t i = 0; i < size; ++i) { 183 int value = va_arg(ap, int); 184 EXPECT_EQ(value, v[i].getValue()); 185 } 186 187 va_end(ap); 188 } 189 190 // Generate a sequence of values to initialize the vector. 191 void makeSequence(VectorT & v, int start, int end) { 192 for (int i = start; i <= end; ++i) { 193 v.push_back(Constructable(i)); 194 } 195 } 196 }; 197 198 typedef ::testing::Types<SmallVector<Constructable, 0>, 199 SmallVector<Constructable, 1>, 200 SmallVector<Constructable, 2>, 201 SmallVector<Constructable, 4>, 202 SmallVector<Constructable, 5> 203 > SmallVectorTestTypes; 204 TYPED_TEST_CASE(SmallVectorTest, SmallVectorTestTypes); 205 206 // New vector test. 207 TYPED_TEST(SmallVectorTest, EmptyVectorTest) { 208 SCOPED_TRACE("EmptyVectorTest"); 209 this->assertEmpty(this->theVector); 210 EXPECT_TRUE(this->theVector.rbegin() == this->theVector.rend()); 211 EXPECT_EQ(0, Constructable::getNumConstructorCalls()); 212 EXPECT_EQ(0, Constructable::getNumDestructorCalls()); 213 } 214 215 // Simple insertions and deletions. 216 TYPED_TEST(SmallVectorTest, PushPopTest) { 217 SCOPED_TRACE("PushPopTest"); 218 219 // Track whether the vector will potentially have to grow. 220 bool RequiresGrowth = this->theVector.capacity() < 3; 221 222 // Push an element 223 this->theVector.push_back(Constructable(1)); 224 225 // Size tests 226 this->assertValuesInOrder(this->theVector, 1u, 1); 227 EXPECT_FALSE(this->theVector.begin() == this->theVector.end()); 228 EXPECT_FALSE(this->theVector.empty()); 229 230 // Push another element 231 this->theVector.push_back(Constructable(2)); 232 this->assertValuesInOrder(this->theVector, 2u, 1, 2); 233 234 // Insert at beginning 235 this->theVector.insert(this->theVector.begin(), this->theVector[1]); 236 this->assertValuesInOrder(this->theVector, 3u, 2, 1, 2); 237 238 // Pop one element 239 this->theVector.pop_back(); 240 this->assertValuesInOrder(this->theVector, 2u, 2, 1); 241 242 // Pop remaining elements 243 this->theVector.pop_back(); 244 this->theVector.pop_back(); 245 this->assertEmpty(this->theVector); 246 247 // Check number of constructor calls. Should be 2 for each list element, 248 // one for the argument to push_back, one for the argument to insert, 249 // and one for the list element itself. 250 if (!RequiresGrowth) { 251 EXPECT_EQ(5, Constructable::getNumConstructorCalls()); 252 EXPECT_EQ(5, Constructable::getNumDestructorCalls()); 253 } else { 254 // If we had to grow the vector, these only have a lower bound, but should 255 // always be equal. 256 EXPECT_LE(5, Constructable::getNumConstructorCalls()); 257 EXPECT_EQ(Constructable::getNumConstructorCalls(), 258 Constructable::getNumDestructorCalls()); 259 } 260 } 261 262 // Clear test. 263 TYPED_TEST(SmallVectorTest, ClearTest) { 264 SCOPED_TRACE("ClearTest"); 265 266 this->theVector.reserve(2); 267 this->makeSequence(this->theVector, 1, 2); 268 this->theVector.clear(); 269 270 this->assertEmpty(this->theVector); 271 EXPECT_EQ(4, Constructable::getNumConstructorCalls()); 272 EXPECT_EQ(4, Constructable::getNumDestructorCalls()); 273 } 274 275 // Resize smaller test. 276 TYPED_TEST(SmallVectorTest, ResizeShrinkTest) { 277 SCOPED_TRACE("ResizeShrinkTest"); 278 279 this->theVector.reserve(3); 280 this->makeSequence(this->theVector, 1, 3); 281 this->theVector.resize(1); 282 283 this->assertValuesInOrder(this->theVector, 1u, 1); 284 EXPECT_EQ(6, Constructable::getNumConstructorCalls()); 285 EXPECT_EQ(5, Constructable::getNumDestructorCalls()); 286 } 287 288 // Resize bigger test. 289 TYPED_TEST(SmallVectorTest, ResizeGrowTest) { 290 SCOPED_TRACE("ResizeGrowTest"); 291 292 this->theVector.resize(2); 293 294 EXPECT_EQ(2, Constructable::getNumConstructorCalls()); 295 EXPECT_EQ(0, Constructable::getNumDestructorCalls()); 296 EXPECT_EQ(2u, this->theVector.size()); 297 } 298 299 TYPED_TEST(SmallVectorTest, ResizeWithElementsTest) { 300 this->theVector.resize(2); 301 302 Constructable::reset(); 303 304 this->theVector.resize(4); 305 306 size_t Ctors = Constructable::getNumConstructorCalls(); 307 EXPECT_TRUE(Ctors == 2 || Ctors == 4); 308 size_t MoveCtors = Constructable::getNumMoveConstructorCalls(); 309 EXPECT_TRUE(MoveCtors == 0 || MoveCtors == 2); 310 size_t Dtors = Constructable::getNumDestructorCalls(); 311 EXPECT_TRUE(Dtors == 0 || Dtors == 2); 312 } 313 314 // Resize with fill value. 315 TYPED_TEST(SmallVectorTest, ResizeFillTest) { 316 SCOPED_TRACE("ResizeFillTest"); 317 318 this->theVector.resize(3, Constructable(77)); 319 this->assertValuesInOrder(this->theVector, 3u, 77, 77, 77); 320 } 321 322 // Overflow past fixed size. 323 TYPED_TEST(SmallVectorTest, OverflowTest) { 324 SCOPED_TRACE("OverflowTest"); 325 326 // Push more elements than the fixed size. 327 this->makeSequence(this->theVector, 1, 10); 328 329 // Test size and values. 330 EXPECT_EQ(10u, this->theVector.size()); 331 for (int i = 0; i < 10; ++i) { 332 EXPECT_EQ(i+1, this->theVector[i].getValue()); 333 } 334 335 // Now resize back to fixed size. 336 this->theVector.resize(1); 337 338 this->assertValuesInOrder(this->theVector, 1u, 1); 339 } 340 341 // Iteration tests. 342 TYPED_TEST(SmallVectorTest, IterationTest) { 343 this->makeSequence(this->theVector, 1, 2); 344 345 // Forward Iteration 346 typename TypeParam::iterator it = this->theVector.begin(); 347 EXPECT_TRUE(*it == this->theVector.front()); 348 EXPECT_TRUE(*it == this->theVector[0]); 349 EXPECT_EQ(1, it->getValue()); 350 ++it; 351 EXPECT_TRUE(*it == this->theVector[1]); 352 EXPECT_TRUE(*it == this->theVector.back()); 353 EXPECT_EQ(2, it->getValue()); 354 ++it; 355 EXPECT_TRUE(it == this->theVector.end()); 356 --it; 357 EXPECT_TRUE(*it == this->theVector[1]); 358 EXPECT_EQ(2, it->getValue()); 359 --it; 360 EXPECT_TRUE(*it == this->theVector[0]); 361 EXPECT_EQ(1, it->getValue()); 362 363 // Reverse Iteration 364 typename TypeParam::reverse_iterator rit = this->theVector.rbegin(); 365 EXPECT_TRUE(*rit == this->theVector[1]); 366 EXPECT_EQ(2, rit->getValue()); 367 ++rit; 368 EXPECT_TRUE(*rit == this->theVector[0]); 369 EXPECT_EQ(1, rit->getValue()); 370 ++rit; 371 EXPECT_TRUE(rit == this->theVector.rend()); 372 --rit; 373 EXPECT_TRUE(*rit == this->theVector[0]); 374 EXPECT_EQ(1, rit->getValue()); 375 --rit; 376 EXPECT_TRUE(*rit == this->theVector[1]); 377 EXPECT_EQ(2, rit->getValue()); 378 } 379 380 // Swap test. 381 TYPED_TEST(SmallVectorTest, SwapTest) { 382 SCOPED_TRACE("SwapTest"); 383 384 this->makeSequence(this->theVector, 1, 2); 385 std::swap(this->theVector, this->otherVector); 386 387 this->assertEmpty(this->theVector); 388 this->assertValuesInOrder(this->otherVector, 2u, 1, 2); 389 } 390 391 // Append test 392 TYPED_TEST(SmallVectorTest, AppendTest) { 393 SCOPED_TRACE("AppendTest"); 394 395 this->makeSequence(this->otherVector, 2, 3); 396 397 this->theVector.push_back(Constructable(1)); 398 this->theVector.append(this->otherVector.begin(), this->otherVector.end()); 399 400 this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3); 401 } 402 403 // Append repeated test 404 TYPED_TEST(SmallVectorTest, AppendRepeatedTest) { 405 SCOPED_TRACE("AppendRepeatedTest"); 406 407 this->theVector.push_back(Constructable(1)); 408 this->theVector.append(2, Constructable(77)); 409 this->assertValuesInOrder(this->theVector, 3u, 1, 77, 77); 410 } 411 412 // Assign test 413 TYPED_TEST(SmallVectorTest, AssignTest) { 414 SCOPED_TRACE("AssignTest"); 415 416 this->theVector.push_back(Constructable(1)); 417 this->theVector.assign(2, Constructable(77)); 418 this->assertValuesInOrder(this->theVector, 2u, 77, 77); 419 } 420 421 // Move-assign test 422 TYPED_TEST(SmallVectorTest, MoveAssignTest) { 423 SCOPED_TRACE("MoveAssignTest"); 424 425 // Set up our vector with a single element, but enough capacity for 4. 426 this->theVector.reserve(4); 427 this->theVector.push_back(Constructable(1)); 428 429 // Set up the other vector with 2 elements. 430 this->otherVector.push_back(Constructable(2)); 431 this->otherVector.push_back(Constructable(3)); 432 433 // Move-assign from the other vector. 434 this->theVector = std::move(this->otherVector); 435 436 // Make sure we have the right result. 437 this->assertValuesInOrder(this->theVector, 2u, 2, 3); 438 439 // Make sure the # of constructor/destructor calls line up. There 440 // are two live objects after clearing the other vector. 441 this->otherVector.clear(); 442 EXPECT_EQ(Constructable::getNumConstructorCalls()-2, 443 Constructable::getNumDestructorCalls()); 444 445 // There shouldn't be any live objects any more. 446 this->theVector.clear(); 447 EXPECT_EQ(Constructable::getNumConstructorCalls(), 448 Constructable::getNumDestructorCalls()); 449 } 450 451 // Erase a single element 452 TYPED_TEST(SmallVectorTest, EraseTest) { 453 SCOPED_TRACE("EraseTest"); 454 455 this->makeSequence(this->theVector, 1, 3); 456 this->theVector.erase(this->theVector.begin()); 457 this->assertValuesInOrder(this->theVector, 2u, 2, 3); 458 } 459 460 // Erase a range of elements 461 TYPED_TEST(SmallVectorTest, EraseRangeTest) { 462 SCOPED_TRACE("EraseRangeTest"); 463 464 this->makeSequence(this->theVector, 1, 3); 465 this->theVector.erase(this->theVector.begin(), this->theVector.begin() + 2); 466 this->assertValuesInOrder(this->theVector, 1u, 3); 467 } 468 469 // Insert a single element. 470 TYPED_TEST(SmallVectorTest, InsertTest) { 471 SCOPED_TRACE("InsertTest"); 472 473 this->makeSequence(this->theVector, 1, 3); 474 typename TypeParam::iterator I = 475 this->theVector.insert(this->theVector.begin() + 1, Constructable(77)); 476 EXPECT_EQ(this->theVector.begin() + 1, I); 477 this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3); 478 } 479 480 // Insert a copy of a single element. 481 TYPED_TEST(SmallVectorTest, InsertCopy) { 482 SCOPED_TRACE("InsertTest"); 483 484 this->makeSequence(this->theVector, 1, 3); 485 Constructable C(77); 486 typename TypeParam::iterator I = 487 this->theVector.insert(this->theVector.begin() + 1, C); 488 EXPECT_EQ(this->theVector.begin() + 1, I); 489 this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3); 490 } 491 492 // Insert repeated elements. 493 TYPED_TEST(SmallVectorTest, InsertRepeatedTest) { 494 SCOPED_TRACE("InsertRepeatedTest"); 495 496 this->makeSequence(this->theVector, 1, 4); 497 Constructable::reset(); 498 auto I = 499 this->theVector.insert(this->theVector.begin() + 1, 2, Constructable(16)); 500 // Move construct the top element into newly allocated space, and optionally 501 // reallocate the whole buffer, move constructing into it. 502 // FIXME: This is inefficient, we shouldn't move things into newly allocated 503 // space, then move them up/around, there should only be 2 or 4 move 504 // constructions here. 505 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 || 506 Constructable::getNumMoveConstructorCalls() == 6); 507 // Move assign the next two to shift them up and make a gap. 508 EXPECT_EQ(1, Constructable::getNumMoveAssignmentCalls()); 509 // Copy construct the two new elements from the parameter. 510 EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls()); 511 // All without any copy construction. 512 EXPECT_EQ(0, Constructable::getNumCopyConstructorCalls()); 513 EXPECT_EQ(this->theVector.begin() + 1, I); 514 this->assertValuesInOrder(this->theVector, 6u, 1, 16, 16, 2, 3, 4); 515 } 516 517 518 TYPED_TEST(SmallVectorTest, InsertRepeatedAtEndTest) { 519 SCOPED_TRACE("InsertRepeatedTest"); 520 521 this->makeSequence(this->theVector, 1, 4); 522 Constructable::reset(); 523 auto I = this->theVector.insert(this->theVector.end(), 2, Constructable(16)); 524 // Just copy construct them into newly allocated space 525 EXPECT_EQ(2, Constructable::getNumCopyConstructorCalls()); 526 // Move everything across if reallocation is needed. 527 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 || 528 Constructable::getNumMoveConstructorCalls() == 4); 529 // Without ever moving or copying anything else. 530 EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls()); 531 EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls()); 532 533 EXPECT_EQ(this->theVector.begin() + 4, I); 534 this->assertValuesInOrder(this->theVector, 6u, 1, 2, 3, 4, 16, 16); 535 } 536 537 TYPED_TEST(SmallVectorTest, InsertRepeatedEmptyTest) { 538 SCOPED_TRACE("InsertRepeatedTest"); 539 540 this->makeSequence(this->theVector, 10, 15); 541 542 // Empty insert. 543 EXPECT_EQ(this->theVector.end(), 544 this->theVector.insert(this->theVector.end(), 545 0, Constructable(42))); 546 EXPECT_EQ(this->theVector.begin() + 1, 547 this->theVector.insert(this->theVector.begin() + 1, 548 0, Constructable(42))); 549 } 550 551 // Insert range. 552 TYPED_TEST(SmallVectorTest, InsertRangeTest) { 553 SCOPED_TRACE("InsertRangeTest"); 554 555 Constructable Arr[3] = 556 { Constructable(77), Constructable(77), Constructable(77) }; 557 558 this->makeSequence(this->theVector, 1, 3); 559 Constructable::reset(); 560 auto I = this->theVector.insert(this->theVector.begin() + 1, Arr, Arr + 3); 561 // Move construct the top 3 elements into newly allocated space. 562 // Possibly move the whole sequence into new space first. 563 // FIXME: This is inefficient, we shouldn't move things into newly allocated 564 // space, then move them up/around, there should only be 2 or 3 move 565 // constructions here. 566 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 || 567 Constructable::getNumMoveConstructorCalls() == 5); 568 // Copy assign the lower 2 new elements into existing space. 569 EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls()); 570 // Copy construct the third element into newly allocated space. 571 EXPECT_EQ(1, Constructable::getNumCopyConstructorCalls()); 572 EXPECT_EQ(this->theVector.begin() + 1, I); 573 this->assertValuesInOrder(this->theVector, 6u, 1, 77, 77, 77, 2, 3); 574 } 575 576 577 TYPED_TEST(SmallVectorTest, InsertRangeAtEndTest) { 578 SCOPED_TRACE("InsertRangeTest"); 579 580 Constructable Arr[3] = 581 { Constructable(77), Constructable(77), Constructable(77) }; 582 583 this->makeSequence(this->theVector, 1, 3); 584 585 // Insert at end. 586 Constructable::reset(); 587 auto I = this->theVector.insert(this->theVector.end(), Arr, Arr+3); 588 // Copy construct the 3 elements into new space at the top. 589 EXPECT_EQ(3, Constructable::getNumCopyConstructorCalls()); 590 // Don't copy/move anything else. 591 EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls()); 592 // Reallocation might occur, causing all elements to be moved into the new 593 // buffer. 594 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 || 595 Constructable::getNumMoveConstructorCalls() == 3); 596 EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls()); 597 EXPECT_EQ(this->theVector.begin() + 3, I); 598 this->assertValuesInOrder(this->theVector, 6u, 599 1, 2, 3, 77, 77, 77); 600 } 601 602 TYPED_TEST(SmallVectorTest, InsertEmptyRangeTest) { 603 SCOPED_TRACE("InsertRangeTest"); 604 605 this->makeSequence(this->theVector, 1, 3); 606 607 // Empty insert. 608 EXPECT_EQ(this->theVector.end(), 609 this->theVector.insert(this->theVector.end(), 610 this->theVector.begin(), 611 this->theVector.begin())); 612 EXPECT_EQ(this->theVector.begin() + 1, 613 this->theVector.insert(this->theVector.begin() + 1, 614 this->theVector.begin(), 615 this->theVector.begin())); 616 } 617 618 // Comparison tests. 619 TYPED_TEST(SmallVectorTest, ComparisonTest) { 620 SCOPED_TRACE("ComparisonTest"); 621 622 this->makeSequence(this->theVector, 1, 3); 623 this->makeSequence(this->otherVector, 1, 3); 624 625 EXPECT_TRUE(this->theVector == this->otherVector); 626 EXPECT_FALSE(this->theVector != this->otherVector); 627 628 this->otherVector.clear(); 629 this->makeSequence(this->otherVector, 2, 4); 630 631 EXPECT_FALSE(this->theVector == this->otherVector); 632 EXPECT_TRUE(this->theVector != this->otherVector); 633 } 634 635 // Constant vector tests. 636 TYPED_TEST(SmallVectorTest, ConstVectorTest) { 637 const TypeParam constVector; 638 639 EXPECT_EQ(0u, constVector.size()); 640 EXPECT_TRUE(constVector.empty()); 641 EXPECT_TRUE(constVector.begin() == constVector.end()); 642 } 643 644 // Direct array access. 645 TYPED_TEST(SmallVectorTest, DirectVectorTest) { 646 EXPECT_EQ(0u, this->theVector.size()); 647 this->theVector.reserve(4); 648 EXPECT_LE(4u, this->theVector.capacity()); 649 EXPECT_EQ(0, Constructable::getNumConstructorCalls()); 650 this->theVector.push_back(1); 651 this->theVector.push_back(2); 652 this->theVector.push_back(3); 653 this->theVector.push_back(4); 654 EXPECT_EQ(4u, this->theVector.size()); 655 EXPECT_EQ(8, Constructable::getNumConstructorCalls()); 656 EXPECT_EQ(1, this->theVector[0].getValue()); 657 EXPECT_EQ(2, this->theVector[1].getValue()); 658 EXPECT_EQ(3, this->theVector[2].getValue()); 659 EXPECT_EQ(4, this->theVector[3].getValue()); 660 } 661 662 TYPED_TEST(SmallVectorTest, IteratorTest) { 663 std::list<int> L; 664 this->theVector.insert(this->theVector.end(), L.begin(), L.end()); 665 } 666 667 struct notassignable { 668 int &x; 669 notassignable(int &x) : x(x) {} 670 }; 671 672 TEST(SmallVectorCustomTest, NoAssignTest) { 673 int x = 0; 674 SmallVector<notassignable, 2> vec; 675 vec.push_back(notassignable(x)); 676 x = 42; 677 EXPECT_EQ(42, vec.pop_back_val().x); 678 } 679 680 struct MovedFrom { 681 bool hasValue; 682 MovedFrom() : hasValue(true) { 683 } 684 MovedFrom(MovedFrom&& m) : hasValue(m.hasValue) { 685 m.hasValue = false; 686 } 687 MovedFrom &operator=(MovedFrom&& m) { 688 hasValue = m.hasValue; 689 m.hasValue = false; 690 return *this; 691 } 692 }; 693 694 TEST(SmallVectorTest, MidInsert) { 695 SmallVector<MovedFrom, 3> v; 696 v.push_back(MovedFrom()); 697 v.insert(v.begin(), MovedFrom()); 698 for (MovedFrom &m : v) 699 EXPECT_TRUE(m.hasValue); 700 } 701 702 } 703