Home | History | Annotate | Download | only in ADT
      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