SmallVectorTest.cpp revision 614be08dd6ae0755d8a4c32ad49f5f580602cc78
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 <stdarg.h>
17
18using namespace llvm;
19
20namespace {
21
22/// A helper class that counts the total number of constructor and
23/// destructor calls.
24class Constructable {
25private:
26  static int numConstructorCalls;
27  static int numDestructorCalls;
28  static int numAssignmentCalls;
29
30  int value;
31
32public:
33  Constructable() : value(0) {
34    ++numConstructorCalls;
35  }
36
37  Constructable(int val) : value(val) {
38    ++numConstructorCalls;
39  }
40
41  Constructable(const Constructable & src) {
42    value = src.value;
43    ++numConstructorCalls;
44  }
45
46  ~Constructable() {
47    ++numDestructorCalls;
48  }
49
50  Constructable & operator=(const Constructable & src) {
51    value = src.value;
52    ++numAssignmentCalls;
53    return *this;
54  }
55
56  int getValue() const {
57    return abs(value);
58  }
59
60  static void reset() {
61    numConstructorCalls = 0;
62    numDestructorCalls = 0;
63    numAssignmentCalls = 0;
64  }
65
66  static int getNumConstructorCalls() {
67    return numConstructorCalls;
68  }
69
70  static int getNumDestructorCalls() {
71    return numDestructorCalls;
72  }
73
74  friend bool operator==(const Constructable & c0, const Constructable & c1) {
75    return c0.getValue() == c1.getValue();
76  }
77
78  friend bool operator!=(const Constructable & c0, const Constructable & c1) {
79    return c0.getValue() != c1.getValue();
80  }
81};
82
83int Constructable::numConstructorCalls;
84int Constructable::numDestructorCalls;
85int Constructable::numAssignmentCalls;
86
87// Test fixture class
88class SmallVectorTest : public testing::Test {
89protected:
90  typedef SmallVector<Constructable, 4> VectorType;
91
92  VectorType theVector;
93  VectorType otherVector;
94
95  void SetUp() {
96    Constructable::reset();
97  }
98
99  void assertEmpty(VectorType & v) {
100    // Size tests
101    EXPECT_EQ(0u, v.size());
102    EXPECT_TRUE(v.empty());
103
104    // Iterator tests
105    EXPECT_TRUE(v.begin() == v.end());
106  }
107
108  // Assert that theVector contains the specified values, in order.
109  void assertValuesInOrder(VectorType & v, size_t size, ...) {
110    EXPECT_EQ(size, v.size());
111
112    va_list ap;
113    va_start(ap, size);
114    for (size_t i = 0; i < size; ++i) {
115      int value = va_arg(ap, int);
116      EXPECT_EQ(value, v[i].getValue());
117    }
118
119    va_end(ap);
120  }
121
122  // Generate a sequence of values to initialize the vector.
123  void makeSequence(VectorType & v, int start, int end) {
124    for (int i = start; i <= end; ++i) {
125      v.push_back(Constructable(i));
126    }
127  }
128};
129
130// New vector test.
131TEST_F(SmallVectorTest, EmptyVectorTest) {
132  SCOPED_TRACE("EmptyVectorTest");
133  assertEmpty(theVector);
134  EXPECT_TRUE(theVector.rbegin() == theVector.rend());
135  EXPECT_EQ(0, Constructable::getNumConstructorCalls());
136  EXPECT_EQ(0, Constructable::getNumDestructorCalls());
137}
138
139// Simple insertions and deletions.
140TEST_F(SmallVectorTest, PushPopTest) {
141  SCOPED_TRACE("PushPopTest");
142
143  // Push an element
144  theVector.push_back(Constructable(1));
145
146  // Size tests
147  assertValuesInOrder(theVector, 1u, 1);
148  EXPECT_FALSE(theVector.begin() == theVector.end());
149  EXPECT_FALSE(theVector.empty());
150
151  // Push another element
152  theVector.push_back(Constructable(2));
153  assertValuesInOrder(theVector, 2u, 1, 2);
154
155  // Pop one element
156  theVector.pop_back();
157  assertValuesInOrder(theVector, 1u, 1);
158
159  // Pop another element
160  theVector.pop_back();
161  assertEmpty(theVector);
162
163  // Check number of constructor calls. Should be 2 for each list element,
164  // one for the argument to push_back, and one for the list element itself.
165  EXPECT_EQ(4, Constructable::getNumConstructorCalls());
166  EXPECT_EQ(4, Constructable::getNumDestructorCalls());
167}
168
169// Clear test.
170TEST_F(SmallVectorTest, ClearTest) {
171  SCOPED_TRACE("ClearTest");
172
173  makeSequence(theVector, 1, 2);
174  theVector.clear();
175
176  assertEmpty(theVector);
177  EXPECT_EQ(4, Constructable::getNumConstructorCalls());
178  EXPECT_EQ(4, Constructable::getNumDestructorCalls());
179}
180
181// Resize smaller test.
182TEST_F(SmallVectorTest, ResizeShrinkTest) {
183  SCOPED_TRACE("ResizeShrinkTest");
184
185  makeSequence(theVector, 1, 3);
186  theVector.resize(1);
187
188  assertValuesInOrder(theVector, 1u, 1);
189  EXPECT_EQ(6, Constructable::getNumConstructorCalls());
190  EXPECT_EQ(5, Constructable::getNumDestructorCalls());
191}
192
193// Resize bigger test.
194TEST_F(SmallVectorTest, ResizeGrowTest) {
195  SCOPED_TRACE("ResizeGrowTest");
196
197  theVector.resize(2);
198
199  // The extra constructor/destructor calls come from the temporary object used
200  // to initialize the contents of the resized array (via copy construction).
201  EXPECT_EQ(3, Constructable::getNumConstructorCalls());
202  EXPECT_EQ(1, Constructable::getNumDestructorCalls());
203  EXPECT_EQ(2u, theVector.size());
204}
205
206// Resize with fill value.
207TEST_F(SmallVectorTest, ResizeFillTest) {
208  SCOPED_TRACE("ResizeFillTest");
209
210  theVector.resize(3, Constructable(77));
211  assertValuesInOrder(theVector, 3u, 77, 77, 77);
212}
213
214// Overflow past fixed size.
215TEST_F(SmallVectorTest, OverflowTest) {
216  SCOPED_TRACE("OverflowTest");
217
218  // Push more elements than the fixed size.
219  makeSequence(theVector, 1, 10);
220
221  // Test size and values.
222  EXPECT_EQ(10u, theVector.size());
223  for (int i = 0; i < 10; ++i) {
224    EXPECT_EQ(i+1, theVector[i].getValue());
225  }
226
227  // Now resize back to fixed size.
228  theVector.resize(1);
229
230  assertValuesInOrder(theVector, 1u, 1);
231}
232
233// Iteration tests.
234TEST_F(SmallVectorTest, IterationTest) {
235  makeSequence(theVector, 1, 2);
236
237  // Forward Iteration
238  VectorType::iterator it = theVector.begin();
239  EXPECT_TRUE(*it == theVector.front());
240  EXPECT_TRUE(*it == theVector[0]);
241  EXPECT_EQ(1, it->getValue());
242  ++it;
243  EXPECT_TRUE(*it == theVector[1]);
244  EXPECT_TRUE(*it == theVector.back());
245  EXPECT_EQ(2, it->getValue());
246  ++it;
247  EXPECT_TRUE(it == theVector.end());
248  --it;
249  EXPECT_TRUE(*it == theVector[1]);
250  EXPECT_EQ(2, it->getValue());
251  --it;
252  EXPECT_TRUE(*it == theVector[0]);
253  EXPECT_EQ(1, it->getValue());
254
255  // Reverse Iteration
256  VectorType::reverse_iterator rit = theVector.rbegin();
257  EXPECT_TRUE(*rit == theVector[1]);
258  EXPECT_EQ(2, rit->getValue());
259  ++rit;
260  EXPECT_TRUE(*rit == theVector[0]);
261  EXPECT_EQ(1, rit->getValue());
262  ++rit;
263  EXPECT_TRUE(rit == theVector.rend());
264  --rit;
265  EXPECT_TRUE(*rit == theVector[0]);
266  EXPECT_EQ(1, rit->getValue());
267  --rit;
268  EXPECT_TRUE(*rit == theVector[1]);
269  EXPECT_EQ(2, rit->getValue());
270}
271
272// Swap test.
273TEST_F(SmallVectorTest, SwapTest) {
274  SCOPED_TRACE("SwapTest");
275
276  makeSequence(theVector, 1, 2);
277  std::swap(theVector, otherVector);
278
279  assertEmpty(theVector);
280  assertValuesInOrder(otherVector, 2u, 1, 2);
281}
282
283// Append test
284TEST_F(SmallVectorTest, AppendTest) {
285  SCOPED_TRACE("AppendTest");
286
287  makeSequence(otherVector, 2, 3);
288
289  theVector.push_back(Constructable(1));
290  theVector.append(otherVector.begin(), otherVector.end());
291
292  assertValuesInOrder(theVector, 3u, 1, 2, 3);
293}
294
295// Append repeated test
296TEST_F(SmallVectorTest, AppendRepeatedTest) {
297  SCOPED_TRACE("AppendRepeatedTest");
298
299  theVector.push_back(Constructable(1));
300  theVector.append(2, Constructable(77));
301  assertValuesInOrder(theVector, 3u, 1, 77, 77);
302}
303
304// Assign test
305TEST_F(SmallVectorTest, AssignTest) {
306  SCOPED_TRACE("AssignTest");
307
308  theVector.push_back(Constructable(1));
309  theVector.assign(2, Constructable(77));
310  assertValuesInOrder(theVector, 2u, 77, 77);
311}
312
313// Erase a single element
314TEST_F(SmallVectorTest, EraseTest) {
315  SCOPED_TRACE("EraseTest");
316
317  makeSequence(theVector, 1, 3);
318  theVector.erase(theVector.begin());
319  assertValuesInOrder(theVector, 2u, 2, 3);
320}
321
322// Erase a range of elements
323TEST_F(SmallVectorTest, EraseRangeTest) {
324  SCOPED_TRACE("EraseRangeTest");
325
326  makeSequence(theVector, 1, 3);
327  theVector.erase(theVector.begin(), theVector.begin() + 2);
328  assertValuesInOrder(theVector, 1u, 3);
329}
330
331// Insert a single element.
332TEST_F(SmallVectorTest, InsertTest) {
333  SCOPED_TRACE("InsertTest");
334
335  makeSequence(theVector, 1, 3);
336  theVector.insert(theVector.begin() + 1, Constructable(77));
337  assertValuesInOrder(theVector, 4u, 1, 77, 2, 3);
338}
339
340// Insert repeated elements.
341TEST_F(SmallVectorTest, InsertRepeatedTest) {
342  SCOPED_TRACE("InsertRepeatedTest");
343
344  makeSequence(theVector, 10, 15);
345  theVector.insert(theVector.begin() + 1, 2, Constructable(16));
346  assertValuesInOrder(theVector, 8u, 10, 16, 16, 11, 12, 13, 14, 15);
347}
348
349// Insert range.
350TEST_F(SmallVectorTest, InsertRangeTest) {
351  SCOPED_TRACE("InsertRepeatedTest");
352
353  makeSequence(theVector, 1, 3);
354  theVector.insert(theVector.begin() + 1, 3, Constructable(77));
355  assertValuesInOrder(theVector, 6u, 1, 77, 77, 77, 2, 3);
356}
357
358// Comparison tests.
359TEST_F(SmallVectorTest, ComparisonTest) {
360  SCOPED_TRACE("ComparisonTest");
361
362  makeSequence(theVector, 1, 3);
363  makeSequence(otherVector, 1, 3);
364
365  EXPECT_TRUE(theVector == otherVector);
366  EXPECT_FALSE(theVector != otherVector);
367
368  otherVector.clear();
369  makeSequence(otherVector, 2, 4);
370
371  EXPECT_FALSE(theVector == otherVector);
372  EXPECT_TRUE(theVector != otherVector);
373}
374
375// Constant vector tests.
376TEST_F(SmallVectorTest, ConstVectorTest) {
377  const VectorType constVector;
378
379  EXPECT_EQ(0u, constVector.size());
380  EXPECT_TRUE(constVector.empty());
381  EXPECT_TRUE(constVector.begin() == constVector.end());
382}
383
384}
385