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