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 numDestructorCalls;
     30   static int numAssignmentCalls;
     31 
     32   int value;
     33 
     34 public:
     35   Constructable() : value(0) {
     36     ++numConstructorCalls;
     37   }
     38 
     39   Constructable(int val) : value(val) {
     40     ++numConstructorCalls;
     41   }
     42 
     43   Constructable(const Constructable & src) {
     44     value = src.value;
     45     ++numConstructorCalls;
     46   }
     47 
     48   ~Constructable() {
     49     ++numDestructorCalls;
     50   }
     51 
     52   Constructable & operator=(const Constructable & src) {
     53     value = src.value;
     54     ++numAssignmentCalls;
     55     return *this;
     56   }
     57 
     58   int getValue() const {
     59     return abs(value);
     60   }
     61 
     62   static void reset() {
     63     numConstructorCalls = 0;
     64     numDestructorCalls = 0;
     65     numAssignmentCalls = 0;
     66   }
     67 
     68   static int getNumConstructorCalls() {
     69     return numConstructorCalls;
     70   }
     71 
     72   static int getNumDestructorCalls() {
     73     return numDestructorCalls;
     74   }
     75 
     76   friend bool operator==(const Constructable & c0, const Constructable & c1) {
     77     return c0.getValue() == c1.getValue();
     78   }
     79 
     80   friend bool LLVM_ATTRIBUTE_UNUSED
     81   operator!=(const Constructable & c0, const Constructable & c1) {
     82     return c0.getValue() != c1.getValue();
     83   }
     84 };
     85 
     86 int Constructable::numConstructorCalls;
     87 int Constructable::numDestructorCalls;
     88 int Constructable::numAssignmentCalls;
     89 
     90 // Test fixture class
     91 template <typename VectorT>
     92 class SmallVectorTest : public testing::Test {
     93 protected:
     94   VectorT theVector;
     95   VectorT otherVector;
     96 
     97   void SetUp() {
     98     Constructable::reset();
     99   }
    100 
    101   void assertEmpty(VectorT & v) {
    102     // Size tests
    103     EXPECT_EQ(0u, v.size());
    104     EXPECT_TRUE(v.empty());
    105 
    106     // Iterator tests
    107     EXPECT_TRUE(v.begin() == v.end());
    108   }
    109 
    110   // Assert that theVector contains the specified values, in order.
    111   void assertValuesInOrder(VectorT & v, size_t size, ...) {
    112     EXPECT_EQ(size, v.size());
    113 
    114     va_list ap;
    115     va_start(ap, size);
    116     for (size_t i = 0; i < size; ++i) {
    117       int value = va_arg(ap, int);
    118       EXPECT_EQ(value, v[i].getValue());
    119     }
    120 
    121     va_end(ap);
    122   }
    123 
    124   // Generate a sequence of values to initialize the vector.
    125   void makeSequence(VectorT & v, int start, int end) {
    126     for (int i = start; i <= end; ++i) {
    127       v.push_back(Constructable(i));
    128     }
    129   }
    130 };
    131 
    132 typedef ::testing::Types<SmallVector<Constructable, 0>,
    133                          SmallVector<Constructable, 1>,
    134                          SmallVector<Constructable, 2>,
    135                          SmallVector<Constructable, 4>
    136                          > SmallVectorTestTypes;
    137 TYPED_TEST_CASE(SmallVectorTest, SmallVectorTestTypes);
    138 
    139 // New vector test.
    140 TYPED_TEST(SmallVectorTest, EmptyVectorTest) {
    141   SCOPED_TRACE("EmptyVectorTest");
    142   this->assertEmpty(this->theVector);
    143   EXPECT_TRUE(this->theVector.rbegin() == this->theVector.rend());
    144   EXPECT_EQ(0, Constructable::getNumConstructorCalls());
    145   EXPECT_EQ(0, Constructable::getNumDestructorCalls());
    146 }
    147 
    148 // Simple insertions and deletions.
    149 TYPED_TEST(SmallVectorTest, PushPopTest) {
    150   SCOPED_TRACE("PushPopTest");
    151 
    152   // Track whether the vector will potentially have to grow.
    153   bool RequiresGrowth = this->theVector.capacity() < 3;
    154 
    155   // Push an element
    156   this->theVector.push_back(Constructable(1));
    157 
    158   // Size tests
    159   this->assertValuesInOrder(this->theVector, 1u, 1);
    160   EXPECT_FALSE(this->theVector.begin() == this->theVector.end());
    161   EXPECT_FALSE(this->theVector.empty());
    162 
    163   // Push another element
    164   this->theVector.push_back(Constructable(2));
    165   this->assertValuesInOrder(this->theVector, 2u, 1, 2);
    166 
    167   // Insert at beginning
    168   this->theVector.insert(this->theVector.begin(), this->theVector[1]);
    169   this->assertValuesInOrder(this->theVector, 3u, 2, 1, 2);
    170 
    171   // Pop one element
    172   this->theVector.pop_back();
    173   this->assertValuesInOrder(this->theVector, 2u, 2, 1);
    174 
    175   // Pop remaining elements
    176   this->theVector.pop_back();
    177   this->theVector.pop_back();
    178   this->assertEmpty(this->theVector);
    179 
    180   // Check number of constructor calls. Should be 2 for each list element,
    181   // one for the argument to push_back, one for the argument to insert,
    182   // and one for the list element itself.
    183   if (!RequiresGrowth) {
    184     EXPECT_EQ(5, Constructable::getNumConstructorCalls());
    185     EXPECT_EQ(5, Constructable::getNumDestructorCalls());
    186   } else {
    187     // If we had to grow the vector, these only have a lower bound, but should
    188     // always be equal.
    189     EXPECT_LE(5, Constructable::getNumConstructorCalls());
    190     EXPECT_EQ(Constructable::getNumConstructorCalls(),
    191               Constructable::getNumDestructorCalls());
    192   }
    193 }
    194 
    195 // Clear test.
    196 TYPED_TEST(SmallVectorTest, ClearTest) {
    197   SCOPED_TRACE("ClearTest");
    198 
    199   this->theVector.reserve(2);
    200   this->makeSequence(this->theVector, 1, 2);
    201   this->theVector.clear();
    202 
    203   this->assertEmpty(this->theVector);
    204   EXPECT_EQ(4, Constructable::getNumConstructorCalls());
    205   EXPECT_EQ(4, Constructable::getNumDestructorCalls());
    206 }
    207 
    208 // Resize smaller test.
    209 TYPED_TEST(SmallVectorTest, ResizeShrinkTest) {
    210   SCOPED_TRACE("ResizeShrinkTest");
    211 
    212   this->theVector.reserve(3);
    213   this->makeSequence(this->theVector, 1, 3);
    214   this->theVector.resize(1);
    215 
    216   this->assertValuesInOrder(this->theVector, 1u, 1);
    217   EXPECT_EQ(6, Constructable::getNumConstructorCalls());
    218   EXPECT_EQ(5, Constructable::getNumDestructorCalls());
    219 }
    220 
    221 // Resize bigger test.
    222 TYPED_TEST(SmallVectorTest, ResizeGrowTest) {
    223   SCOPED_TRACE("ResizeGrowTest");
    224 
    225   this->theVector.resize(2);
    226 
    227   // The extra constructor/destructor calls come from the temporary object used
    228   // to initialize the contents of the resized array (via copy construction).
    229   EXPECT_EQ(3, Constructable::getNumConstructorCalls());
    230   EXPECT_EQ(1, Constructable::getNumDestructorCalls());
    231   EXPECT_EQ(2u, this->theVector.size());
    232 }
    233 
    234 // Resize with fill value.
    235 TYPED_TEST(SmallVectorTest, ResizeFillTest) {
    236   SCOPED_TRACE("ResizeFillTest");
    237 
    238   this->theVector.resize(3, Constructable(77));
    239   this->assertValuesInOrder(this->theVector, 3u, 77, 77, 77);
    240 }
    241 
    242 // Overflow past fixed size.
    243 TYPED_TEST(SmallVectorTest, OverflowTest) {
    244   SCOPED_TRACE("OverflowTest");
    245 
    246   // Push more elements than the fixed size.
    247   this->makeSequence(this->theVector, 1, 10);
    248 
    249   // Test size and values.
    250   EXPECT_EQ(10u, this->theVector.size());
    251   for (int i = 0; i < 10; ++i) {
    252     EXPECT_EQ(i+1, this->theVector[i].getValue());
    253   }
    254 
    255   // Now resize back to fixed size.
    256   this->theVector.resize(1);
    257 
    258   this->assertValuesInOrder(this->theVector, 1u, 1);
    259 }
    260 
    261 // Iteration tests.
    262 TYPED_TEST(SmallVectorTest, IterationTest) {
    263   this->makeSequence(this->theVector, 1, 2);
    264 
    265   // Forward Iteration
    266   typename TypeParam::iterator it = this->theVector.begin();
    267   EXPECT_TRUE(*it == this->theVector.front());
    268   EXPECT_TRUE(*it == this->theVector[0]);
    269   EXPECT_EQ(1, it->getValue());
    270   ++it;
    271   EXPECT_TRUE(*it == this->theVector[1]);
    272   EXPECT_TRUE(*it == this->theVector.back());
    273   EXPECT_EQ(2, it->getValue());
    274   ++it;
    275   EXPECT_TRUE(it == this->theVector.end());
    276   --it;
    277   EXPECT_TRUE(*it == this->theVector[1]);
    278   EXPECT_EQ(2, it->getValue());
    279   --it;
    280   EXPECT_TRUE(*it == this->theVector[0]);
    281   EXPECT_EQ(1, it->getValue());
    282 
    283   // Reverse Iteration
    284   typename TypeParam::reverse_iterator rit = this->theVector.rbegin();
    285   EXPECT_TRUE(*rit == this->theVector[1]);
    286   EXPECT_EQ(2, rit->getValue());
    287   ++rit;
    288   EXPECT_TRUE(*rit == this->theVector[0]);
    289   EXPECT_EQ(1, rit->getValue());
    290   ++rit;
    291   EXPECT_TRUE(rit == this->theVector.rend());
    292   --rit;
    293   EXPECT_TRUE(*rit == this->theVector[0]);
    294   EXPECT_EQ(1, rit->getValue());
    295   --rit;
    296   EXPECT_TRUE(*rit == this->theVector[1]);
    297   EXPECT_EQ(2, rit->getValue());
    298 }
    299 
    300 // Swap test.
    301 TYPED_TEST(SmallVectorTest, SwapTest) {
    302   SCOPED_TRACE("SwapTest");
    303 
    304   this->makeSequence(this->theVector, 1, 2);
    305   std::swap(this->theVector, this->otherVector);
    306 
    307   this->assertEmpty(this->theVector);
    308   this->assertValuesInOrder(this->otherVector, 2u, 1, 2);
    309 }
    310 
    311 // Append test
    312 TYPED_TEST(SmallVectorTest, AppendTest) {
    313   SCOPED_TRACE("AppendTest");
    314 
    315   this->makeSequence(this->otherVector, 2, 3);
    316 
    317   this->theVector.push_back(Constructable(1));
    318   this->theVector.append(this->otherVector.begin(), this->otherVector.end());
    319 
    320   this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3);
    321 }
    322 
    323 // Append repeated test
    324 TYPED_TEST(SmallVectorTest, AppendRepeatedTest) {
    325   SCOPED_TRACE("AppendRepeatedTest");
    326 
    327   this->theVector.push_back(Constructable(1));
    328   this->theVector.append(2, Constructable(77));
    329   this->assertValuesInOrder(this->theVector, 3u, 1, 77, 77);
    330 }
    331 
    332 // Assign test
    333 TYPED_TEST(SmallVectorTest, AssignTest) {
    334   SCOPED_TRACE("AssignTest");
    335 
    336   this->theVector.push_back(Constructable(1));
    337   this->theVector.assign(2, Constructable(77));
    338   this->assertValuesInOrder(this->theVector, 2u, 77, 77);
    339 }
    340 
    341 // Erase a single element
    342 TYPED_TEST(SmallVectorTest, EraseTest) {
    343   SCOPED_TRACE("EraseTest");
    344 
    345   this->makeSequence(this->theVector, 1, 3);
    346   this->theVector.erase(this->theVector.begin());
    347   this->assertValuesInOrder(this->theVector, 2u, 2, 3);
    348 }
    349 
    350 // Erase a range of elements
    351 TYPED_TEST(SmallVectorTest, EraseRangeTest) {
    352   SCOPED_TRACE("EraseRangeTest");
    353 
    354   this->makeSequence(this->theVector, 1, 3);
    355   this->theVector.erase(this->theVector.begin(), this->theVector.begin() + 2);
    356   this->assertValuesInOrder(this->theVector, 1u, 3);
    357 }
    358 
    359 // Insert a single element.
    360 TYPED_TEST(SmallVectorTest, InsertTest) {
    361   SCOPED_TRACE("InsertTest");
    362 
    363   this->makeSequence(this->theVector, 1, 3);
    364   typename TypeParam::iterator I =
    365     this->theVector.insert(this->theVector.begin() + 1, Constructable(77));
    366   EXPECT_EQ(this->theVector.begin() + 1, I);
    367   this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3);
    368 }
    369 
    370 // Insert repeated elements.
    371 TYPED_TEST(SmallVectorTest, InsertRepeatedTest) {
    372   SCOPED_TRACE("InsertRepeatedTest");
    373 
    374   this->makeSequence(this->theVector, 10, 15);
    375   typename TypeParam::iterator I =
    376     this->theVector.insert(this->theVector.begin() + 1, 2, Constructable(16));
    377   EXPECT_EQ(this->theVector.begin() + 1, I);
    378   this->assertValuesInOrder(this->theVector, 8u,
    379                       10, 16, 16, 11, 12, 13, 14, 15);
    380 
    381   // Insert at end.
    382   I = this->theVector.insert(this->theVector.end(), 2, Constructable(16));
    383   EXPECT_EQ(this->theVector.begin() + 8, I);
    384   this->assertValuesInOrder(this->theVector, 10u,
    385                       10, 16, 16, 11, 12, 13, 14, 15, 16, 16);
    386 
    387   // Empty insert.
    388   EXPECT_EQ(this->theVector.end(),
    389             this->theVector.insert(this->theVector.end(),
    390                                    0, Constructable(42)));
    391   EXPECT_EQ(this->theVector.begin() + 1,
    392             this->theVector.insert(this->theVector.begin() + 1,
    393                                    0, Constructable(42)));
    394 }
    395 
    396 // Insert range.
    397 TYPED_TEST(SmallVectorTest, InsertRangeTest) {
    398   SCOPED_TRACE("InsertRangeTest");
    399 
    400   Constructable Arr[3] =
    401     { Constructable(77), Constructable(77), Constructable(77) };
    402 
    403   this->makeSequence(this->theVector, 1, 3);
    404   typename TypeParam::iterator I =
    405     this->theVector.insert(this->theVector.begin() + 1, Arr, Arr+3);
    406   EXPECT_EQ(this->theVector.begin() + 1, I);
    407   this->assertValuesInOrder(this->theVector, 6u, 1, 77, 77, 77, 2, 3);
    408 
    409   // Insert at end.
    410   I = this->theVector.insert(this->theVector.end(), Arr, Arr+3);
    411   EXPECT_EQ(this->theVector.begin() + 6, I);
    412   this->assertValuesInOrder(this->theVector, 9u,
    413                             1, 77, 77, 77, 2, 3, 77, 77, 77);
    414 
    415   // Empty insert.
    416   EXPECT_EQ(this->theVector.end(),
    417             this->theVector.insert(this->theVector.end(),
    418                                    this->theVector.begin(),
    419                                    this->theVector.begin()));
    420   EXPECT_EQ(this->theVector.begin() + 1,
    421             this->theVector.insert(this->theVector.begin() + 1,
    422                                    this->theVector.begin(),
    423                                    this->theVector.begin()));
    424 }
    425 
    426 // Comparison tests.
    427 TYPED_TEST(SmallVectorTest, ComparisonTest) {
    428   SCOPED_TRACE("ComparisonTest");
    429 
    430   this->makeSequence(this->theVector, 1, 3);
    431   this->makeSequence(this->otherVector, 1, 3);
    432 
    433   EXPECT_TRUE(this->theVector == this->otherVector);
    434   EXPECT_FALSE(this->theVector != this->otherVector);
    435 
    436   this->otherVector.clear();
    437   this->makeSequence(this->otherVector, 2, 4);
    438 
    439   EXPECT_FALSE(this->theVector == this->otherVector);
    440   EXPECT_TRUE(this->theVector != this->otherVector);
    441 }
    442 
    443 // Constant vector tests.
    444 TYPED_TEST(SmallVectorTest, ConstVectorTest) {
    445   const TypeParam constVector;
    446 
    447   EXPECT_EQ(0u, constVector.size());
    448   EXPECT_TRUE(constVector.empty());
    449   EXPECT_TRUE(constVector.begin() == constVector.end());
    450 }
    451 
    452 // Direct array access.
    453 TYPED_TEST(SmallVectorTest, DirectVectorTest) {
    454   EXPECT_EQ(0u, this->theVector.size());
    455   this->theVector.reserve(4);
    456   EXPECT_LE(4u, this->theVector.capacity());
    457   EXPECT_EQ(0, Constructable::getNumConstructorCalls());
    458   this->theVector.end()[0] = 1;
    459   this->theVector.end()[1] = 2;
    460   this->theVector.end()[2] = 3;
    461   this->theVector.end()[3] = 4;
    462   this->theVector.set_size(4);
    463   EXPECT_EQ(4u, this->theVector.size());
    464   EXPECT_EQ(4, Constructable::getNumConstructorCalls());
    465   EXPECT_EQ(1, this->theVector[0].getValue());
    466   EXPECT_EQ(2, this->theVector[1].getValue());
    467   EXPECT_EQ(3, this->theVector[2].getValue());
    468   EXPECT_EQ(4, this->theVector[3].getValue());
    469 }
    470 
    471 TYPED_TEST(SmallVectorTest, IteratorTest) {
    472   std::list<int> L;
    473   this->theVector.insert(this->theVector.end(), L.begin(), L.end());
    474 }
    475 
    476 struct notassignable {
    477   int &x;
    478   notassignable(int &x) : x(x) {}
    479 };
    480 
    481 TEST(SmallVectorCustomTest, NoAssignTest) {
    482   int x = 0;
    483   SmallVector<notassignable, 2> vec;
    484   vec.push_back(notassignable(x));
    485   x = 42;
    486   EXPECT_EQ(42, vec.pop_back_val().x);
    487 }
    488 
    489 }
    490