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 "gtest/gtest.h"
     15 #include "llvm/ADT/SmallVector.h"
     16 #include "llvm/Support/Compiler.h"
     17 #include <stdarg.h>
     18 #include <list>
     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 class SmallVectorTest : public testing::Test {
     92 protected:
     93   typedef SmallVector<Constructable, 4> VectorType;
     94 
     95   VectorType theVector;
     96   VectorType otherVector;
     97 
     98   void SetUp() {
     99     Constructable::reset();
    100   }
    101 
    102   void assertEmpty(VectorType & v) {
    103     // Size tests
    104     EXPECT_EQ(0u, v.size());
    105     EXPECT_TRUE(v.empty());
    106 
    107     // Iterator tests
    108     EXPECT_TRUE(v.begin() == v.end());
    109   }
    110 
    111   // Assert that theVector contains the specified values, in order.
    112   void assertValuesInOrder(VectorType & v, size_t size, ...) {
    113     EXPECT_EQ(size, v.size());
    114 
    115     va_list ap;
    116     va_start(ap, size);
    117     for (size_t i = 0; i < size; ++i) {
    118       int value = va_arg(ap, int);
    119       EXPECT_EQ(value, v[i].getValue());
    120     }
    121 
    122     va_end(ap);
    123   }
    124 
    125   // Generate a sequence of values to initialize the vector.
    126   void makeSequence(VectorType & v, int start, int end) {
    127     for (int i = start; i <= end; ++i) {
    128       v.push_back(Constructable(i));
    129     }
    130   }
    131 };
    132 
    133 // New vector test.
    134 TEST_F(SmallVectorTest, EmptyVectorTest) {
    135   SCOPED_TRACE("EmptyVectorTest");
    136   assertEmpty(theVector);
    137   EXPECT_TRUE(theVector.rbegin() == theVector.rend());
    138   EXPECT_EQ(0, Constructable::getNumConstructorCalls());
    139   EXPECT_EQ(0, Constructable::getNumDestructorCalls());
    140 }
    141 
    142 // Simple insertions and deletions.
    143 TEST_F(SmallVectorTest, PushPopTest) {
    144   SCOPED_TRACE("PushPopTest");
    145 
    146   // Push an element
    147   theVector.push_back(Constructable(1));
    148 
    149   // Size tests
    150   assertValuesInOrder(theVector, 1u, 1);
    151   EXPECT_FALSE(theVector.begin() == theVector.end());
    152   EXPECT_FALSE(theVector.empty());
    153 
    154   // Push another element
    155   theVector.push_back(Constructable(2));
    156   assertValuesInOrder(theVector, 2u, 1, 2);
    157 
    158   // Insert at beginning
    159   theVector.insert(theVector.begin(), theVector[1]);
    160   assertValuesInOrder(theVector, 3u, 2, 1, 2);
    161 
    162   // Pop one element
    163   theVector.pop_back();
    164   assertValuesInOrder(theVector, 2u, 2, 1);
    165 
    166   // Pop remaining elements
    167   theVector.pop_back();
    168   theVector.pop_back();
    169   assertEmpty(theVector);
    170 
    171   // Check number of constructor calls. Should be 2 for each list element,
    172   // one for the argument to push_back, one for the argument to insert,
    173   // and one for the list element itself.
    174   EXPECT_EQ(5, Constructable::getNumConstructorCalls());
    175   EXPECT_EQ(5, Constructable::getNumDestructorCalls());
    176 }
    177 
    178 // Clear test.
    179 TEST_F(SmallVectorTest, ClearTest) {
    180   SCOPED_TRACE("ClearTest");
    181 
    182   makeSequence(theVector, 1, 2);
    183   theVector.clear();
    184 
    185   assertEmpty(theVector);
    186   EXPECT_EQ(4, Constructable::getNumConstructorCalls());
    187   EXPECT_EQ(4, Constructable::getNumDestructorCalls());
    188 }
    189 
    190 // Resize smaller test.
    191 TEST_F(SmallVectorTest, ResizeShrinkTest) {
    192   SCOPED_TRACE("ResizeShrinkTest");
    193 
    194   makeSequence(theVector, 1, 3);
    195   theVector.resize(1);
    196 
    197   assertValuesInOrder(theVector, 1u, 1);
    198   EXPECT_EQ(6, Constructable::getNumConstructorCalls());
    199   EXPECT_EQ(5, Constructable::getNumDestructorCalls());
    200 }
    201 
    202 // Resize bigger test.
    203 TEST_F(SmallVectorTest, ResizeGrowTest) {
    204   SCOPED_TRACE("ResizeGrowTest");
    205 
    206   theVector.resize(2);
    207 
    208   // The extra constructor/destructor calls come from the temporary object used
    209   // to initialize the contents of the resized array (via copy construction).
    210   EXPECT_EQ(3, Constructable::getNumConstructorCalls());
    211   EXPECT_EQ(1, Constructable::getNumDestructorCalls());
    212   EXPECT_EQ(2u, theVector.size());
    213 }
    214 
    215 // Resize with fill value.
    216 TEST_F(SmallVectorTest, ResizeFillTest) {
    217   SCOPED_TRACE("ResizeFillTest");
    218 
    219   theVector.resize(3, Constructable(77));
    220   assertValuesInOrder(theVector, 3u, 77, 77, 77);
    221 }
    222 
    223 // Overflow past fixed size.
    224 TEST_F(SmallVectorTest, OverflowTest) {
    225   SCOPED_TRACE("OverflowTest");
    226 
    227   // Push more elements than the fixed size.
    228   makeSequence(theVector, 1, 10);
    229 
    230   // Test size and values.
    231   EXPECT_EQ(10u, theVector.size());
    232   for (int i = 0; i < 10; ++i) {
    233     EXPECT_EQ(i+1, theVector[i].getValue());
    234   }
    235 
    236   // Now resize back to fixed size.
    237   theVector.resize(1);
    238 
    239   assertValuesInOrder(theVector, 1u, 1);
    240 }
    241 
    242 // Iteration tests.
    243 TEST_F(SmallVectorTest, IterationTest) {
    244   makeSequence(theVector, 1, 2);
    245 
    246   // Forward Iteration
    247   VectorType::iterator it = theVector.begin();
    248   EXPECT_TRUE(*it == theVector.front());
    249   EXPECT_TRUE(*it == theVector[0]);
    250   EXPECT_EQ(1, it->getValue());
    251   ++it;
    252   EXPECT_TRUE(*it == theVector[1]);
    253   EXPECT_TRUE(*it == theVector.back());
    254   EXPECT_EQ(2, it->getValue());
    255   ++it;
    256   EXPECT_TRUE(it == theVector.end());
    257   --it;
    258   EXPECT_TRUE(*it == theVector[1]);
    259   EXPECT_EQ(2, it->getValue());
    260   --it;
    261   EXPECT_TRUE(*it == theVector[0]);
    262   EXPECT_EQ(1, it->getValue());
    263 
    264   // Reverse Iteration
    265   VectorType::reverse_iterator rit = theVector.rbegin();
    266   EXPECT_TRUE(*rit == theVector[1]);
    267   EXPECT_EQ(2, rit->getValue());
    268   ++rit;
    269   EXPECT_TRUE(*rit == theVector[0]);
    270   EXPECT_EQ(1, rit->getValue());
    271   ++rit;
    272   EXPECT_TRUE(rit == theVector.rend());
    273   --rit;
    274   EXPECT_TRUE(*rit == theVector[0]);
    275   EXPECT_EQ(1, rit->getValue());
    276   --rit;
    277   EXPECT_TRUE(*rit == theVector[1]);
    278   EXPECT_EQ(2, rit->getValue());
    279 }
    280 
    281 // Swap test.
    282 TEST_F(SmallVectorTest, SwapTest) {
    283   SCOPED_TRACE("SwapTest");
    284 
    285   makeSequence(theVector, 1, 2);
    286   std::swap(theVector, otherVector);
    287 
    288   assertEmpty(theVector);
    289   assertValuesInOrder(otherVector, 2u, 1, 2);
    290 }
    291 
    292 // Append test
    293 TEST_F(SmallVectorTest, AppendTest) {
    294   SCOPED_TRACE("AppendTest");
    295 
    296   makeSequence(otherVector, 2, 3);
    297 
    298   theVector.push_back(Constructable(1));
    299   theVector.append(otherVector.begin(), otherVector.end());
    300 
    301   assertValuesInOrder(theVector, 3u, 1, 2, 3);
    302 }
    303 
    304 // Append repeated test
    305 TEST_F(SmallVectorTest, AppendRepeatedTest) {
    306   SCOPED_TRACE("AppendRepeatedTest");
    307 
    308   theVector.push_back(Constructable(1));
    309   theVector.append(2, Constructable(77));
    310   assertValuesInOrder(theVector, 3u, 1, 77, 77);
    311 }
    312 
    313 // Assign test
    314 TEST_F(SmallVectorTest, AssignTest) {
    315   SCOPED_TRACE("AssignTest");
    316 
    317   theVector.push_back(Constructable(1));
    318   theVector.assign(2, Constructable(77));
    319   assertValuesInOrder(theVector, 2u, 77, 77);
    320 }
    321 
    322 // Erase a single element
    323 TEST_F(SmallVectorTest, EraseTest) {
    324   SCOPED_TRACE("EraseTest");
    325 
    326   makeSequence(theVector, 1, 3);
    327   theVector.erase(theVector.begin());
    328   assertValuesInOrder(theVector, 2u, 2, 3);
    329 }
    330 
    331 // Erase a range of elements
    332 TEST_F(SmallVectorTest, EraseRangeTest) {
    333   SCOPED_TRACE("EraseRangeTest");
    334 
    335   makeSequence(theVector, 1, 3);
    336   theVector.erase(theVector.begin(), theVector.begin() + 2);
    337   assertValuesInOrder(theVector, 1u, 3);
    338 }
    339 
    340 // Insert a single element.
    341 TEST_F(SmallVectorTest, InsertTest) {
    342   SCOPED_TRACE("InsertTest");
    343 
    344   makeSequence(theVector, 1, 3);
    345   theVector.insert(theVector.begin() + 1, Constructable(77));
    346   assertValuesInOrder(theVector, 4u, 1, 77, 2, 3);
    347 }
    348 
    349 // Insert repeated elements.
    350 TEST_F(SmallVectorTest, InsertRepeatedTest) {
    351   SCOPED_TRACE("InsertRepeatedTest");
    352 
    353   makeSequence(theVector, 10, 15);
    354   theVector.insert(theVector.begin() + 1, 2, Constructable(16));
    355   assertValuesInOrder(theVector, 8u, 10, 16, 16, 11, 12, 13, 14, 15);
    356 }
    357 
    358 // Insert range.
    359 TEST_F(SmallVectorTest, InsertRangeTest) {
    360   SCOPED_TRACE("InsertRepeatedTest");
    361 
    362   makeSequence(theVector, 1, 3);
    363   theVector.insert(theVector.begin() + 1, 3, Constructable(77));
    364   assertValuesInOrder(theVector, 6u, 1, 77, 77, 77, 2, 3);
    365 }
    366 
    367 // Comparison tests.
    368 TEST_F(SmallVectorTest, ComparisonTest) {
    369   SCOPED_TRACE("ComparisonTest");
    370 
    371   makeSequence(theVector, 1, 3);
    372   makeSequence(otherVector, 1, 3);
    373 
    374   EXPECT_TRUE(theVector == otherVector);
    375   EXPECT_FALSE(theVector != otherVector);
    376 
    377   otherVector.clear();
    378   makeSequence(otherVector, 2, 4);
    379 
    380   EXPECT_FALSE(theVector == otherVector);
    381   EXPECT_TRUE(theVector != otherVector);
    382 }
    383 
    384 // Constant vector tests.
    385 TEST_F(SmallVectorTest, ConstVectorTest) {
    386   VectorType constVector;
    387 
    388   EXPECT_EQ(0u, constVector.size());
    389   EXPECT_TRUE(constVector.empty());
    390   EXPECT_TRUE(constVector.begin() == constVector.end());
    391 }
    392 
    393 // Direct array access.
    394 TEST_F(SmallVectorTest, DirectVectorTest) {
    395   EXPECT_EQ(0u, theVector.size());
    396   EXPECT_LE(4u, theVector.capacity());
    397   EXPECT_EQ(0, Constructable::getNumConstructorCalls());
    398   theVector.end()[0] = 1;
    399   theVector.end()[1] = 2;
    400   theVector.end()[2] = 3;
    401   theVector.end()[3] = 4;
    402   theVector.set_size(4);
    403   EXPECT_EQ(4u, theVector.size());
    404   EXPECT_EQ(4, Constructable::getNumConstructorCalls());
    405   EXPECT_EQ(1, theVector[0].getValue());
    406   EXPECT_EQ(2, theVector[1].getValue());
    407   EXPECT_EQ(3, theVector[2].getValue());
    408   EXPECT_EQ(4, theVector[3].getValue());
    409 }
    410 
    411 TEST_F(SmallVectorTest, IteratorTest) {
    412   std::list<int> L;
    413   theVector.insert(theVector.end(), L.begin(), L.end());
    414 }
    415 
    416 }
    417