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