X86: support double extension of f16 type.
[oota-llvm.git] / unittests / ADT / SmallVectorTest.cpp
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 numMoveConstructorCalls;
30   static int numCopyConstructorCalls;
31   static int numDestructorCalls;
32   static int numAssignmentCalls;
33   static int numMoveAssignmentCalls;
34   static int numCopyAssignmentCalls;
35
36   bool constructed;
37   int value;
38
39 public:
40   Constructable() : constructed(true), value(0) {
41     ++numConstructorCalls;
42   }
43
44   Constructable(int val) : constructed(true), value(val) {
45     ++numConstructorCalls;
46   }
47
48   Constructable(const Constructable & src) : constructed(true) {
49     value = src.value;
50     ++numConstructorCalls;
51     ++numCopyConstructorCalls;
52   }
53
54   Constructable(Constructable && src) : constructed(true) {
55     value = src.value;
56     ++numConstructorCalls;
57     ++numMoveConstructorCalls;
58   }
59
60   ~Constructable() {
61     EXPECT_TRUE(constructed);
62     ++numDestructorCalls;
63     constructed = false;
64   }
65
66   Constructable & operator=(const Constructable & src) {
67     EXPECT_TRUE(constructed);
68     value = src.value;
69     ++numAssignmentCalls;
70     ++numCopyAssignmentCalls;
71     return *this;
72   }
73
74   Constructable & operator=(Constructable && src) {
75     EXPECT_TRUE(constructed);
76     value = src.value;
77     ++numAssignmentCalls;
78     ++numMoveAssignmentCalls;
79     return *this;
80   }
81
82   int getValue() const {
83     return abs(value);
84   }
85
86   static void reset() {
87     numConstructorCalls = 0;
88     numMoveConstructorCalls = 0;
89     numCopyConstructorCalls = 0;
90     numDestructorCalls = 0;
91     numAssignmentCalls = 0;
92     numMoveAssignmentCalls = 0;
93     numCopyAssignmentCalls = 0;
94   }
95
96   static int getNumConstructorCalls() {
97     return numConstructorCalls;
98   }
99
100   static int getNumMoveConstructorCalls() {
101     return numMoveConstructorCalls;
102   }
103
104   static int getNumCopyConstructorCalls() {
105     return numCopyConstructorCalls;
106   }
107
108   static int getNumDestructorCalls() {
109     return numDestructorCalls;
110   }
111
112   static int getNumAssignmentCalls() {
113     return numAssignmentCalls;
114   }
115
116   static int getNumMoveAssignmentCalls() {
117     return numMoveAssignmentCalls;
118   }
119
120   static int getNumCopyAssignmentCalls() {
121     return numCopyAssignmentCalls;
122   }
123
124   friend bool operator==(const Constructable & c0, const Constructable & c1) {
125     return c0.getValue() == c1.getValue();
126   }
127
128   friend bool LLVM_ATTRIBUTE_UNUSED
129   operator!=(const Constructable & c0, const Constructable & c1) {
130     return c0.getValue() != c1.getValue();
131   }
132 };
133
134 int Constructable::numConstructorCalls;
135 int Constructable::numCopyConstructorCalls;
136 int Constructable::numMoveConstructorCalls;
137 int Constructable::numDestructorCalls;
138 int Constructable::numAssignmentCalls;
139 int Constructable::numCopyAssignmentCalls;
140 int Constructable::numMoveAssignmentCalls;
141
142 struct NonCopyable {
143   NonCopyable() {}
144   NonCopyable(NonCopyable &&) {}
145   NonCopyable &operator=(NonCopyable &&) { return *this; }
146 private:
147   NonCopyable(const NonCopyable &) LLVM_DELETED_FUNCTION;
148   NonCopyable &operator=(const NonCopyable &) LLVM_DELETED_FUNCTION;
149 };
150
151 LLVM_ATTRIBUTE_USED void CompileTest() {
152   SmallVector<NonCopyable, 0> V;
153   V.resize(42);
154 }
155
156 // Test fixture class
157 template <typename VectorT>
158 class SmallVectorTest : public testing::Test {
159 protected:
160   VectorT theVector;
161   VectorT otherVector;
162
163   void SetUp() {
164     Constructable::reset();
165   }
166
167   void assertEmpty(VectorT & v) {
168     // Size tests
169     EXPECT_EQ(0u, v.size());
170     EXPECT_TRUE(v.empty());
171
172     // Iterator tests
173     EXPECT_TRUE(v.begin() == v.end());
174   }
175
176   // Assert that theVector contains the specified values, in order.
177   void assertValuesInOrder(VectorT & v, size_t size, ...) {
178     EXPECT_EQ(size, v.size());
179
180     va_list ap;
181     va_start(ap, size);
182     for (size_t i = 0; i < size; ++i) {
183       int value = va_arg(ap, int);
184       EXPECT_EQ(value, v[i].getValue());
185     }
186
187     va_end(ap);
188   }
189
190   // Generate a sequence of values to initialize the vector.
191   void makeSequence(VectorT & v, int start, int end) {
192     for (int i = start; i <= end; ++i) {
193       v.push_back(Constructable(i));
194     }
195   }
196 };
197
198 typedef ::testing::Types<SmallVector<Constructable, 0>,
199                          SmallVector<Constructable, 1>,
200                          SmallVector<Constructable, 2>,
201                          SmallVector<Constructable, 4>,
202                          SmallVector<Constructable, 5>
203                          > SmallVectorTestTypes;
204 TYPED_TEST_CASE(SmallVectorTest, SmallVectorTestTypes);
205
206 // New vector test.
207 TYPED_TEST(SmallVectorTest, EmptyVectorTest) {
208   SCOPED_TRACE("EmptyVectorTest");
209   this->assertEmpty(this->theVector);
210   EXPECT_TRUE(this->theVector.rbegin() == this->theVector.rend());
211   EXPECT_EQ(0, Constructable::getNumConstructorCalls());
212   EXPECT_EQ(0, Constructable::getNumDestructorCalls());
213 }
214
215 // Simple insertions and deletions.
216 TYPED_TEST(SmallVectorTest, PushPopTest) {
217   SCOPED_TRACE("PushPopTest");
218
219   // Track whether the vector will potentially have to grow.
220   bool RequiresGrowth = this->theVector.capacity() < 3;
221
222   // Push an element
223   this->theVector.push_back(Constructable(1));
224
225   // Size tests
226   this->assertValuesInOrder(this->theVector, 1u, 1);
227   EXPECT_FALSE(this->theVector.begin() == this->theVector.end());
228   EXPECT_FALSE(this->theVector.empty());
229
230   // Push another element
231   this->theVector.push_back(Constructable(2));
232   this->assertValuesInOrder(this->theVector, 2u, 1, 2);
233
234   // Insert at beginning
235   this->theVector.insert(this->theVector.begin(), this->theVector[1]);
236   this->assertValuesInOrder(this->theVector, 3u, 2, 1, 2);
237
238   // Pop one element
239   this->theVector.pop_back();
240   this->assertValuesInOrder(this->theVector, 2u, 2, 1);
241
242   // Pop remaining elements
243   this->theVector.pop_back();
244   this->theVector.pop_back();
245   this->assertEmpty(this->theVector);
246
247   // Check number of constructor calls. Should be 2 for each list element,
248   // one for the argument to push_back, one for the argument to insert,
249   // and one for the list element itself.
250   if (!RequiresGrowth) {
251     EXPECT_EQ(5, Constructable::getNumConstructorCalls());
252     EXPECT_EQ(5, Constructable::getNumDestructorCalls());
253   } else {
254     // If we had to grow the vector, these only have a lower bound, but should
255     // always be equal.
256     EXPECT_LE(5, Constructable::getNumConstructorCalls());
257     EXPECT_EQ(Constructable::getNumConstructorCalls(),
258               Constructable::getNumDestructorCalls());
259   }
260 }
261
262 // Clear test.
263 TYPED_TEST(SmallVectorTest, ClearTest) {
264   SCOPED_TRACE("ClearTest");
265
266   this->theVector.reserve(2);
267   this->makeSequence(this->theVector, 1, 2);
268   this->theVector.clear();
269
270   this->assertEmpty(this->theVector);
271   EXPECT_EQ(4, Constructable::getNumConstructorCalls());
272   EXPECT_EQ(4, Constructable::getNumDestructorCalls());
273 }
274
275 // Resize smaller test.
276 TYPED_TEST(SmallVectorTest, ResizeShrinkTest) {
277   SCOPED_TRACE("ResizeShrinkTest");
278
279   this->theVector.reserve(3);
280   this->makeSequence(this->theVector, 1, 3);
281   this->theVector.resize(1);
282
283   this->assertValuesInOrder(this->theVector, 1u, 1);
284   EXPECT_EQ(6, Constructable::getNumConstructorCalls());
285   EXPECT_EQ(5, Constructable::getNumDestructorCalls());
286 }
287
288 // Resize bigger test.
289 TYPED_TEST(SmallVectorTest, ResizeGrowTest) {
290   SCOPED_TRACE("ResizeGrowTest");
291
292   this->theVector.resize(2);
293
294   EXPECT_EQ(2, Constructable::getNumConstructorCalls());
295   EXPECT_EQ(0, Constructable::getNumDestructorCalls());
296   EXPECT_EQ(2u, this->theVector.size());
297 }
298
299 TYPED_TEST(SmallVectorTest, ResizeWithElementsTest) {
300   this->theVector.resize(2);
301
302   Constructable::reset();
303
304   this->theVector.resize(4);
305
306   size_t Ctors = Constructable::getNumConstructorCalls();
307   EXPECT_TRUE(Ctors == 2 || Ctors == 4);
308   size_t MoveCtors = Constructable::getNumMoveConstructorCalls();
309   EXPECT_TRUE(MoveCtors == 0 || MoveCtors == 2);
310   size_t Dtors = Constructable::getNumDestructorCalls();
311   EXPECT_TRUE(Dtors == 0 || Dtors == 2);
312 }
313
314 // Resize with fill value.
315 TYPED_TEST(SmallVectorTest, ResizeFillTest) {
316   SCOPED_TRACE("ResizeFillTest");
317
318   this->theVector.resize(3, Constructable(77));
319   this->assertValuesInOrder(this->theVector, 3u, 77, 77, 77);
320 }
321
322 // Overflow past fixed size.
323 TYPED_TEST(SmallVectorTest, OverflowTest) {
324   SCOPED_TRACE("OverflowTest");
325
326   // Push more elements than the fixed size.
327   this->makeSequence(this->theVector, 1, 10);
328
329   // Test size and values.
330   EXPECT_EQ(10u, this->theVector.size());
331   for (int i = 0; i < 10; ++i) {
332     EXPECT_EQ(i+1, this->theVector[i].getValue());
333   }
334
335   // Now resize back to fixed size.
336   this->theVector.resize(1);
337
338   this->assertValuesInOrder(this->theVector, 1u, 1);
339 }
340
341 // Iteration tests.
342 TYPED_TEST(SmallVectorTest, IterationTest) {
343   this->makeSequence(this->theVector, 1, 2);
344
345   // Forward Iteration
346   typename TypeParam::iterator it = this->theVector.begin();
347   EXPECT_TRUE(*it == this->theVector.front());
348   EXPECT_TRUE(*it == this->theVector[0]);
349   EXPECT_EQ(1, it->getValue());
350   ++it;
351   EXPECT_TRUE(*it == this->theVector[1]);
352   EXPECT_TRUE(*it == this->theVector.back());
353   EXPECT_EQ(2, it->getValue());
354   ++it;
355   EXPECT_TRUE(it == this->theVector.end());
356   --it;
357   EXPECT_TRUE(*it == this->theVector[1]);
358   EXPECT_EQ(2, it->getValue());
359   --it;
360   EXPECT_TRUE(*it == this->theVector[0]);
361   EXPECT_EQ(1, it->getValue());
362
363   // Reverse Iteration
364   typename TypeParam::reverse_iterator rit = this->theVector.rbegin();
365   EXPECT_TRUE(*rit == this->theVector[1]);
366   EXPECT_EQ(2, rit->getValue());
367   ++rit;
368   EXPECT_TRUE(*rit == this->theVector[0]);
369   EXPECT_EQ(1, rit->getValue());
370   ++rit;
371   EXPECT_TRUE(rit == this->theVector.rend());
372   --rit;
373   EXPECT_TRUE(*rit == this->theVector[0]);
374   EXPECT_EQ(1, rit->getValue());
375   --rit;
376   EXPECT_TRUE(*rit == this->theVector[1]);
377   EXPECT_EQ(2, rit->getValue());
378 }
379
380 // Swap test.
381 TYPED_TEST(SmallVectorTest, SwapTest) {
382   SCOPED_TRACE("SwapTest");
383
384   this->makeSequence(this->theVector, 1, 2);
385   std::swap(this->theVector, this->otherVector);
386
387   this->assertEmpty(this->theVector);
388   this->assertValuesInOrder(this->otherVector, 2u, 1, 2);
389 }
390
391 // Append test
392 TYPED_TEST(SmallVectorTest, AppendTest) {
393   SCOPED_TRACE("AppendTest");
394
395   this->makeSequence(this->otherVector, 2, 3);
396
397   this->theVector.push_back(Constructable(1));
398   this->theVector.append(this->otherVector.begin(), this->otherVector.end());
399
400   this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3);
401 }
402
403 // Append repeated test
404 TYPED_TEST(SmallVectorTest, AppendRepeatedTest) {
405   SCOPED_TRACE("AppendRepeatedTest");
406
407   this->theVector.push_back(Constructable(1));
408   this->theVector.append(2, Constructable(77));
409   this->assertValuesInOrder(this->theVector, 3u, 1, 77, 77);
410 }
411
412 // Assign test
413 TYPED_TEST(SmallVectorTest, AssignTest) {
414   SCOPED_TRACE("AssignTest");
415
416   this->theVector.push_back(Constructable(1));
417   this->theVector.assign(2, Constructable(77));
418   this->assertValuesInOrder(this->theVector, 2u, 77, 77);
419 }
420
421 // Move-assign test
422 TYPED_TEST(SmallVectorTest, MoveAssignTest) {
423   SCOPED_TRACE("MoveAssignTest");
424
425   // Set up our vector with a single element, but enough capacity for 4.
426   this->theVector.reserve(4);
427   this->theVector.push_back(Constructable(1));
428   
429   // Set up the other vector with 2 elements.
430   this->otherVector.push_back(Constructable(2));
431   this->otherVector.push_back(Constructable(3));
432
433   // Move-assign from the other vector.
434   this->theVector = std::move(this->otherVector);
435
436   // Make sure we have the right result.
437   this->assertValuesInOrder(this->theVector, 2u, 2, 3);
438
439   // Make sure the # of constructor/destructor calls line up. There
440   // are two live objects after clearing the other vector.
441   this->otherVector.clear();
442   EXPECT_EQ(Constructable::getNumConstructorCalls()-2, 
443             Constructable::getNumDestructorCalls());
444
445   // There shouldn't be any live objects any more.
446   this->theVector.clear();
447   EXPECT_EQ(Constructable::getNumConstructorCalls(), 
448             Constructable::getNumDestructorCalls());
449 }
450
451 // Erase a single element
452 TYPED_TEST(SmallVectorTest, EraseTest) {
453   SCOPED_TRACE("EraseTest");
454
455   this->makeSequence(this->theVector, 1, 3);
456   this->theVector.erase(this->theVector.begin());
457   this->assertValuesInOrder(this->theVector, 2u, 2, 3);
458 }
459
460 // Erase a range of elements
461 TYPED_TEST(SmallVectorTest, EraseRangeTest) {
462   SCOPED_TRACE("EraseRangeTest");
463
464   this->makeSequence(this->theVector, 1, 3);
465   this->theVector.erase(this->theVector.begin(), this->theVector.begin() + 2);
466   this->assertValuesInOrder(this->theVector, 1u, 3);
467 }
468
469 // Insert a single element.
470 TYPED_TEST(SmallVectorTest, InsertTest) {
471   SCOPED_TRACE("InsertTest");
472
473   this->makeSequence(this->theVector, 1, 3);
474   typename TypeParam::iterator I =
475     this->theVector.insert(this->theVector.begin() + 1, Constructable(77));
476   EXPECT_EQ(this->theVector.begin() + 1, I);
477   this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3);
478 }
479
480 // Insert a copy of a single element.
481 TYPED_TEST(SmallVectorTest, InsertCopy) {
482   SCOPED_TRACE("InsertTest");
483
484   this->makeSequence(this->theVector, 1, 3);
485   Constructable C(77);
486   typename TypeParam::iterator I =
487       this->theVector.insert(this->theVector.begin() + 1, C);
488   EXPECT_EQ(this->theVector.begin() + 1, I);
489   this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3);
490 }
491
492 // Insert repeated elements.
493 TYPED_TEST(SmallVectorTest, InsertRepeatedTest) {
494   SCOPED_TRACE("InsertRepeatedTest");
495
496   this->makeSequence(this->theVector, 1, 4);
497   Constructable::reset();
498   auto I =
499       this->theVector.insert(this->theVector.begin() + 1, 2, Constructable(16));
500   // Move construct the top element into newly allocated space, and optionally
501   // reallocate the whole buffer, move constructing into it.
502   // FIXME: This is inefficient, we shouldn't move things into newly allocated
503   // space, then move them up/around, there should only be 2 or 4 move
504   // constructions here.
505   EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
506               Constructable::getNumMoveConstructorCalls() == 6);
507   // Move assign the next two to shift them up and make a gap.
508   EXPECT_EQ(1, Constructable::getNumMoveAssignmentCalls());
509   // Copy construct the two new elements from the parameter.
510   EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
511   // All without any copy construction.
512   EXPECT_EQ(0, Constructable::getNumCopyConstructorCalls());
513   EXPECT_EQ(this->theVector.begin() + 1, I);
514   this->assertValuesInOrder(this->theVector, 6u, 1, 16, 16, 2, 3, 4);
515 }
516
517
518 TYPED_TEST(SmallVectorTest, InsertRepeatedAtEndTest) {
519   SCOPED_TRACE("InsertRepeatedTest");
520
521   this->makeSequence(this->theVector, 1, 4);
522   Constructable::reset();
523   auto I = this->theVector.insert(this->theVector.end(), 2, Constructable(16));
524   // Just copy construct them into newly allocated space
525   EXPECT_EQ(2, Constructable::getNumCopyConstructorCalls());
526   // Move everything across if reallocation is needed.
527   EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
528               Constructable::getNumMoveConstructorCalls() == 4);
529   // Without ever moving or copying anything else.
530   EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
531   EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
532
533   EXPECT_EQ(this->theVector.begin() + 4, I);
534   this->assertValuesInOrder(this->theVector, 6u, 1, 2, 3, 4, 16, 16);
535 }
536
537 TYPED_TEST(SmallVectorTest, InsertRepeatedEmptyTest) {
538   SCOPED_TRACE("InsertRepeatedTest");
539
540   this->makeSequence(this->theVector, 10, 15);
541
542   // Empty insert.
543   EXPECT_EQ(this->theVector.end(),
544             this->theVector.insert(this->theVector.end(),
545                                    0, Constructable(42)));
546   EXPECT_EQ(this->theVector.begin() + 1,
547             this->theVector.insert(this->theVector.begin() + 1,
548                                    0, Constructable(42)));
549 }
550
551 // Insert range.
552 TYPED_TEST(SmallVectorTest, InsertRangeTest) {
553   SCOPED_TRACE("InsertRangeTest");
554
555   Constructable Arr[3] =
556     { Constructable(77), Constructable(77), Constructable(77) };
557
558   this->makeSequence(this->theVector, 1, 3);
559   Constructable::reset();
560   auto I = this->theVector.insert(this->theVector.begin() + 1, Arr, Arr + 3);
561   // Move construct the top 3 elements into newly allocated space.
562   // Possibly move the whole sequence into new space first.
563   // FIXME: This is inefficient, we shouldn't move things into newly allocated
564   // space, then move them up/around, there should only be 2 or 3 move
565   // constructions here.
566   EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
567               Constructable::getNumMoveConstructorCalls() == 5);
568   // Copy assign the lower 2 new elements into existing space.
569   EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
570   // Copy construct the third element into newly allocated space.
571   EXPECT_EQ(1, Constructable::getNumCopyConstructorCalls());
572   EXPECT_EQ(this->theVector.begin() + 1, I);
573   this->assertValuesInOrder(this->theVector, 6u, 1, 77, 77, 77, 2, 3);
574 }
575
576
577 TYPED_TEST(SmallVectorTest, InsertRangeAtEndTest) {
578   SCOPED_TRACE("InsertRangeTest");
579
580   Constructable Arr[3] =
581     { Constructable(77), Constructable(77), Constructable(77) };
582
583   this->makeSequence(this->theVector, 1, 3);
584
585   // Insert at end.
586   Constructable::reset();
587   auto I = this->theVector.insert(this->theVector.end(), Arr, Arr+3);
588   // Copy construct the 3 elements into new space at the top.
589   EXPECT_EQ(3, Constructable::getNumCopyConstructorCalls());
590   // Don't copy/move anything else.
591   EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
592   // Reallocation might occur, causing all elements to be moved into the new
593   // buffer.
594   EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
595               Constructable::getNumMoveConstructorCalls() == 3);
596   EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
597   EXPECT_EQ(this->theVector.begin() + 3, I);
598   this->assertValuesInOrder(this->theVector, 6u,
599                             1, 2, 3, 77, 77, 77);
600 }
601
602 TYPED_TEST(SmallVectorTest, InsertEmptyRangeTest) {
603   SCOPED_TRACE("InsertRangeTest");
604
605   this->makeSequence(this->theVector, 1, 3);
606
607   // Empty insert.
608   EXPECT_EQ(this->theVector.end(),
609             this->theVector.insert(this->theVector.end(),
610                                    this->theVector.begin(),
611                                    this->theVector.begin()));
612   EXPECT_EQ(this->theVector.begin() + 1,
613             this->theVector.insert(this->theVector.begin() + 1,
614                                    this->theVector.begin(),
615                                    this->theVector.begin()));
616 }
617
618 // Comparison tests.
619 TYPED_TEST(SmallVectorTest, ComparisonTest) {
620   SCOPED_TRACE("ComparisonTest");
621
622   this->makeSequence(this->theVector, 1, 3);
623   this->makeSequence(this->otherVector, 1, 3);
624
625   EXPECT_TRUE(this->theVector == this->otherVector);
626   EXPECT_FALSE(this->theVector != this->otherVector);
627
628   this->otherVector.clear();
629   this->makeSequence(this->otherVector, 2, 4);
630
631   EXPECT_FALSE(this->theVector == this->otherVector);
632   EXPECT_TRUE(this->theVector != this->otherVector);
633 }
634
635 // Constant vector tests.
636 TYPED_TEST(SmallVectorTest, ConstVectorTest) {
637   const TypeParam constVector;
638
639   EXPECT_EQ(0u, constVector.size());
640   EXPECT_TRUE(constVector.empty());
641   EXPECT_TRUE(constVector.begin() == constVector.end());
642 }
643
644 // Direct array access.
645 TYPED_TEST(SmallVectorTest, DirectVectorTest) {
646   EXPECT_EQ(0u, this->theVector.size());
647   this->theVector.reserve(4);
648   EXPECT_LE(4u, this->theVector.capacity());
649   EXPECT_EQ(0, Constructable::getNumConstructorCalls());
650   this->theVector.push_back(1);
651   this->theVector.push_back(2);
652   this->theVector.push_back(3);
653   this->theVector.push_back(4);
654   EXPECT_EQ(4u, this->theVector.size());
655   EXPECT_EQ(8, Constructable::getNumConstructorCalls());
656   EXPECT_EQ(1, this->theVector[0].getValue());
657   EXPECT_EQ(2, this->theVector[1].getValue());
658   EXPECT_EQ(3, this->theVector[2].getValue());
659   EXPECT_EQ(4, this->theVector[3].getValue());
660 }
661
662 TYPED_TEST(SmallVectorTest, IteratorTest) {
663   std::list<int> L;
664   this->theVector.insert(this->theVector.end(), L.begin(), L.end());
665 }
666
667 struct notassignable {
668   int &x;
669   notassignable(int &x) : x(x) {}
670 };
671
672 TEST(SmallVectorCustomTest, NoAssignTest) {
673   int x = 0;
674   SmallVector<notassignable, 2> vec;
675   vec.push_back(notassignable(x));
676   x = 42;
677   EXPECT_EQ(42, vec.pop_back_val().x);
678 }
679
680 struct MovedFrom {
681   bool hasValue;
682   MovedFrom() : hasValue(true) {
683   }
684   MovedFrom(MovedFrom&& m) : hasValue(m.hasValue) {
685     m.hasValue = false;
686   }
687   MovedFrom &operator=(MovedFrom&& m) {
688     hasValue = m.hasValue;
689     m.hasValue = false;
690     return *this;
691   }
692 };
693
694 TEST(SmallVectorTest, MidInsert) {
695   SmallVector<MovedFrom, 3> v;
696   v.push_back(MovedFrom());
697   v.insert(v.begin(), MovedFrom());
698   for (MovedFrom &m : v)
699     EXPECT_TRUE(m.hasValue);
700 }
701
702 }