1 //===- llvm/unittest/ADT/SmallVectorTest.cpp ------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // SmallVector unit tests.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/Support/Compiler.h"
17 #include "gtest/gtest.h"
25 /// A helper class that counts the total number of constructor and
29 static int numConstructorCalls
;
30 static int numMoveConstructorCalls
;
31 static int numCopyConstructorCalls
;
32 static int numDestructorCalls
;
33 static int numAssignmentCalls
;
34 static int numMoveAssignmentCalls
;
35 static int numCopyAssignmentCalls
;
41 Constructable() : constructed(true), value(0) {
42 ++numConstructorCalls
;
45 Constructable(int val
) : constructed(true), value(val
) {
46 ++numConstructorCalls
;
49 Constructable(const Constructable
& src
) : constructed(true) {
51 ++numConstructorCalls
;
52 ++numCopyConstructorCalls
;
55 Constructable(Constructable
&& src
) : constructed(true) {
57 ++numConstructorCalls
;
58 ++numMoveConstructorCalls
;
62 EXPECT_TRUE(constructed
);
67 Constructable
& operator=(const Constructable
& src
) {
68 EXPECT_TRUE(constructed
);
71 ++numCopyAssignmentCalls
;
75 Constructable
& operator=(Constructable
&& src
) {
76 EXPECT_TRUE(constructed
);
79 ++numMoveAssignmentCalls
;
83 int getValue() const {
88 numConstructorCalls
= 0;
89 numMoveConstructorCalls
= 0;
90 numCopyConstructorCalls
= 0;
91 numDestructorCalls
= 0;
92 numAssignmentCalls
= 0;
93 numMoveAssignmentCalls
= 0;
94 numCopyAssignmentCalls
= 0;
97 static int getNumConstructorCalls() {
98 return numConstructorCalls
;
101 static int getNumMoveConstructorCalls() {
102 return numMoveConstructorCalls
;
105 static int getNumCopyConstructorCalls() {
106 return numCopyConstructorCalls
;
109 static int getNumDestructorCalls() {
110 return numDestructorCalls
;
113 static int getNumAssignmentCalls() {
114 return numAssignmentCalls
;
117 static int getNumMoveAssignmentCalls() {
118 return numMoveAssignmentCalls
;
121 static int getNumCopyAssignmentCalls() {
122 return numCopyAssignmentCalls
;
125 friend bool operator==(const Constructable
& c0
, const Constructable
& c1
) {
126 return c0
.getValue() == c1
.getValue();
129 friend bool LLVM_ATTRIBUTE_UNUSED
130 operator!=(const Constructable
& c0
, const Constructable
& c1
) {
131 return c0
.getValue() != c1
.getValue();
135 int Constructable::numConstructorCalls
;
136 int Constructable::numCopyConstructorCalls
;
137 int Constructable::numMoveConstructorCalls
;
138 int Constructable::numDestructorCalls
;
139 int Constructable::numAssignmentCalls
;
140 int Constructable::numCopyAssignmentCalls
;
141 int Constructable::numMoveAssignmentCalls
;
145 NonCopyable(NonCopyable
&&) {}
146 NonCopyable
&operator=(NonCopyable
&&) { return *this; }
148 NonCopyable(const NonCopyable
&) = delete;
149 NonCopyable
&operator=(const NonCopyable
&) = delete;
152 LLVM_ATTRIBUTE_USED
void CompileTest() {
153 SmallVector
<NonCopyable
, 0> V
;
157 class SmallVectorTestBase
: public testing::Test
{
159 void SetUp() override
{ Constructable::reset(); }
161 template <typename VectorT
>
162 void assertEmpty(VectorT
& v
) {
164 EXPECT_EQ(0u, v
.size());
165 EXPECT_TRUE(v
.empty());
168 EXPECT_TRUE(v
.begin() == v
.end());
171 // Assert that v contains the specified values, in order.
172 template <typename VectorT
>
173 void assertValuesInOrder(VectorT
& v
, size_t size
, ...) {
174 EXPECT_EQ(size
, v
.size());
178 for (size_t i
= 0; i
< size
; ++i
) {
179 int value
= va_arg(ap
, int);
180 EXPECT_EQ(value
, v
[i
].getValue());
186 // Generate a sequence of values to initialize the vector.
187 template <typename VectorT
>
188 void makeSequence(VectorT
& v
, int start
, int end
) {
189 for (int i
= start
; i
<= end
; ++i
) {
190 v
.push_back(Constructable(i
));
195 // Test fixture class
196 template <typename VectorT
>
197 class SmallVectorTest
: public SmallVectorTestBase
{
204 typedef ::testing::Types
<SmallVector
<Constructable
, 0>,
205 SmallVector
<Constructable
, 1>,
206 SmallVector
<Constructable
, 2>,
207 SmallVector
<Constructable
, 4>,
208 SmallVector
<Constructable
, 5>
209 > SmallVectorTestTypes
;
210 TYPED_TEST_CASE(SmallVectorTest
, SmallVectorTestTypes
);
213 TYPED_TEST(SmallVectorTest
, ConstructorNonIterTest
) {
214 SCOPED_TRACE("ConstructorTest");
215 this->theVector
= SmallVector
<Constructable
, 2>(2, 2);
216 this->assertValuesInOrder(this->theVector
, 2u, 2, 2);
220 TYPED_TEST(SmallVectorTest
, ConstructorIterTest
) {
221 SCOPED_TRACE("ConstructorTest");
222 int arr
[] = {1, 2, 3};
224 SmallVector
<Constructable
, 4>(std::begin(arr
), std::end(arr
));
225 this->assertValuesInOrder(this->theVector
, 3u, 1, 2, 3);
229 TYPED_TEST(SmallVectorTest
, EmptyVectorTest
) {
230 SCOPED_TRACE("EmptyVectorTest");
231 this->assertEmpty(this->theVector
);
232 EXPECT_TRUE(this->theVector
.rbegin() == this->theVector
.rend());
233 EXPECT_EQ(0, Constructable::getNumConstructorCalls());
234 EXPECT_EQ(0, Constructable::getNumDestructorCalls());
237 // Simple insertions and deletions.
238 TYPED_TEST(SmallVectorTest
, PushPopTest
) {
239 SCOPED_TRACE("PushPopTest");
241 // Track whether the vector will potentially have to grow.
242 bool RequiresGrowth
= this->theVector
.capacity() < 3;
245 this->theVector
.push_back(Constructable(1));
248 this->assertValuesInOrder(this->theVector
, 1u, 1);
249 EXPECT_FALSE(this->theVector
.begin() == this->theVector
.end());
250 EXPECT_FALSE(this->theVector
.empty());
252 // Push another element
253 this->theVector
.push_back(Constructable(2));
254 this->assertValuesInOrder(this->theVector
, 2u, 1, 2);
256 // Insert at beginning
257 this->theVector
.insert(this->theVector
.begin(), this->theVector
[1]);
258 this->assertValuesInOrder(this->theVector
, 3u, 2, 1, 2);
261 this->theVector
.pop_back();
262 this->assertValuesInOrder(this->theVector
, 2u, 2, 1);
264 // Pop remaining elements
265 this->theVector
.pop_back();
266 this->theVector
.pop_back();
267 this->assertEmpty(this->theVector
);
269 // Check number of constructor calls. Should be 2 for each list element,
270 // one for the argument to push_back, one for the argument to insert,
271 // and one for the list element itself.
272 if (!RequiresGrowth
) {
273 EXPECT_EQ(5, Constructable::getNumConstructorCalls());
274 EXPECT_EQ(5, Constructable::getNumDestructorCalls());
276 // If we had to grow the vector, these only have a lower bound, but should
278 EXPECT_LE(5, Constructable::getNumConstructorCalls());
279 EXPECT_EQ(Constructable::getNumConstructorCalls(),
280 Constructable::getNumDestructorCalls());
285 TYPED_TEST(SmallVectorTest
, ClearTest
) {
286 SCOPED_TRACE("ClearTest");
288 this->theVector
.reserve(2);
289 this->makeSequence(this->theVector
, 1, 2);
290 this->theVector
.clear();
292 this->assertEmpty(this->theVector
);
293 EXPECT_EQ(4, Constructable::getNumConstructorCalls());
294 EXPECT_EQ(4, Constructable::getNumDestructorCalls());
297 // Resize smaller test.
298 TYPED_TEST(SmallVectorTest
, ResizeShrinkTest
) {
299 SCOPED_TRACE("ResizeShrinkTest");
301 this->theVector
.reserve(3);
302 this->makeSequence(this->theVector
, 1, 3);
303 this->theVector
.resize(1);
305 this->assertValuesInOrder(this->theVector
, 1u, 1);
306 EXPECT_EQ(6, Constructable::getNumConstructorCalls());
307 EXPECT_EQ(5, Constructable::getNumDestructorCalls());
310 // Resize bigger test.
311 TYPED_TEST(SmallVectorTest
, ResizeGrowTest
) {
312 SCOPED_TRACE("ResizeGrowTest");
314 this->theVector
.resize(2);
316 EXPECT_EQ(2, Constructable::getNumConstructorCalls());
317 EXPECT_EQ(0, Constructable::getNumDestructorCalls());
318 EXPECT_EQ(2u, this->theVector
.size());
321 TYPED_TEST(SmallVectorTest
, ResizeWithElementsTest
) {
322 this->theVector
.resize(2);
324 Constructable::reset();
326 this->theVector
.resize(4);
328 size_t Ctors
= Constructable::getNumConstructorCalls();
329 EXPECT_TRUE(Ctors
== 2 || Ctors
== 4);
330 size_t MoveCtors
= Constructable::getNumMoveConstructorCalls();
331 EXPECT_TRUE(MoveCtors
== 0 || MoveCtors
== 2);
332 size_t Dtors
= Constructable::getNumDestructorCalls();
333 EXPECT_TRUE(Dtors
== 0 || Dtors
== 2);
336 // Resize with fill value.
337 TYPED_TEST(SmallVectorTest
, ResizeFillTest
) {
338 SCOPED_TRACE("ResizeFillTest");
340 this->theVector
.resize(3, Constructable(77));
341 this->assertValuesInOrder(this->theVector
, 3u, 77, 77, 77);
344 // Overflow past fixed size.
345 TYPED_TEST(SmallVectorTest
, OverflowTest
) {
346 SCOPED_TRACE("OverflowTest");
348 // Push more elements than the fixed size.
349 this->makeSequence(this->theVector
, 1, 10);
351 // Test size and values.
352 EXPECT_EQ(10u, this->theVector
.size());
353 for (int i
= 0; i
< 10; ++i
) {
354 EXPECT_EQ(i
+1, this->theVector
[i
].getValue());
357 // Now resize back to fixed size.
358 this->theVector
.resize(1);
360 this->assertValuesInOrder(this->theVector
, 1u, 1);
364 TYPED_TEST(SmallVectorTest
, IterationTest
) {
365 this->makeSequence(this->theVector
, 1, 2);
368 typename
TypeParam::iterator it
= this->theVector
.begin();
369 EXPECT_TRUE(*it
== this->theVector
.front());
370 EXPECT_TRUE(*it
== this->theVector
[0]);
371 EXPECT_EQ(1, it
->getValue());
373 EXPECT_TRUE(*it
== this->theVector
[1]);
374 EXPECT_TRUE(*it
== this->theVector
.back());
375 EXPECT_EQ(2, it
->getValue());
377 EXPECT_TRUE(it
== this->theVector
.end());
379 EXPECT_TRUE(*it
== this->theVector
[1]);
380 EXPECT_EQ(2, it
->getValue());
382 EXPECT_TRUE(*it
== this->theVector
[0]);
383 EXPECT_EQ(1, it
->getValue());
386 typename
TypeParam::reverse_iterator rit
= this->theVector
.rbegin();
387 EXPECT_TRUE(*rit
== this->theVector
[1]);
388 EXPECT_EQ(2, rit
->getValue());
390 EXPECT_TRUE(*rit
== this->theVector
[0]);
391 EXPECT_EQ(1, rit
->getValue());
393 EXPECT_TRUE(rit
== this->theVector
.rend());
395 EXPECT_TRUE(*rit
== this->theVector
[0]);
396 EXPECT_EQ(1, rit
->getValue());
398 EXPECT_TRUE(*rit
== this->theVector
[1]);
399 EXPECT_EQ(2, rit
->getValue());
403 TYPED_TEST(SmallVectorTest
, SwapTest
) {
404 SCOPED_TRACE("SwapTest");
406 this->makeSequence(this->theVector
, 1, 2);
407 std::swap(this->theVector
, this->otherVector
);
409 this->assertEmpty(this->theVector
);
410 this->assertValuesInOrder(this->otherVector
, 2u, 1, 2);
414 TYPED_TEST(SmallVectorTest
, AppendTest
) {
415 SCOPED_TRACE("AppendTest");
417 this->makeSequence(this->otherVector
, 2, 3);
419 this->theVector
.push_back(Constructable(1));
420 this->theVector
.append(this->otherVector
.begin(), this->otherVector
.end());
422 this->assertValuesInOrder(this->theVector
, 3u, 1, 2, 3);
425 // Append repeated test
426 TYPED_TEST(SmallVectorTest
, AppendRepeatedTest
) {
427 SCOPED_TRACE("AppendRepeatedTest");
429 this->theVector
.push_back(Constructable(1));
430 this->theVector
.append(2, Constructable(77));
431 this->assertValuesInOrder(this->theVector
, 3u, 1, 77, 77);
435 TYPED_TEST(SmallVectorTest
, AppendNonIterTest
) {
436 SCOPED_TRACE("AppendRepeatedTest");
438 this->theVector
.push_back(Constructable(1));
439 this->theVector
.append(2, 7);
440 this->assertValuesInOrder(this->theVector
, 3u, 1, 7, 7);
443 struct output_iterator
{
444 typedef std::output_iterator_tag iterator_category
;
445 typedef int value_type
;
446 typedef int difference_type
;
447 typedef value_type
*pointer
;
448 typedef value_type
&reference
;
449 operator int() { return 2; }
450 operator Constructable() { return 7; }
453 TYPED_TEST(SmallVectorTest
, AppendRepeatedNonForwardIterator
) {
454 SCOPED_TRACE("AppendRepeatedTest");
456 this->theVector
.push_back(Constructable(1));
457 this->theVector
.append(output_iterator(), output_iterator());
458 this->assertValuesInOrder(this->theVector
, 3u, 1, 7, 7);
462 TYPED_TEST(SmallVectorTest
, AssignTest
) {
463 SCOPED_TRACE("AssignTest");
465 this->theVector
.push_back(Constructable(1));
466 this->theVector
.assign(2, Constructable(77));
467 this->assertValuesInOrder(this->theVector
, 2u, 77, 77);
471 TYPED_TEST(SmallVectorTest
, AssignRangeTest
) {
472 SCOPED_TRACE("AssignTest");
474 this->theVector
.push_back(Constructable(1));
475 int arr
[] = {1, 2, 3};
476 this->theVector
.assign(std::begin(arr
), std::end(arr
));
477 this->assertValuesInOrder(this->theVector
, 3u, 1, 2, 3);
481 TYPED_TEST(SmallVectorTest
, AssignNonIterTest
) {
482 SCOPED_TRACE("AssignTest");
484 this->theVector
.push_back(Constructable(1));
485 this->theVector
.assign(2, 7);
486 this->assertValuesInOrder(this->theVector
, 2u, 7, 7);
490 TYPED_TEST(SmallVectorTest
, MoveAssignTest
) {
491 SCOPED_TRACE("MoveAssignTest");
493 // Set up our vector with a single element, but enough capacity for 4.
494 this->theVector
.reserve(4);
495 this->theVector
.push_back(Constructable(1));
497 // Set up the other vector with 2 elements.
498 this->otherVector
.push_back(Constructable(2));
499 this->otherVector
.push_back(Constructable(3));
501 // Move-assign from the other vector.
502 this->theVector
= std::move(this->otherVector
);
504 // Make sure we have the right result.
505 this->assertValuesInOrder(this->theVector
, 2u, 2, 3);
507 // Make sure the # of constructor/destructor calls line up. There
508 // are two live objects after clearing the other vector.
509 this->otherVector
.clear();
510 EXPECT_EQ(Constructable::getNumConstructorCalls()-2,
511 Constructable::getNumDestructorCalls());
513 // There shouldn't be any live objects any more.
514 this->theVector
.clear();
515 EXPECT_EQ(Constructable::getNumConstructorCalls(),
516 Constructable::getNumDestructorCalls());
519 // Erase a single element
520 TYPED_TEST(SmallVectorTest
, EraseTest
) {
521 SCOPED_TRACE("EraseTest");
523 this->makeSequence(this->theVector
, 1, 3);
524 const auto &theConstVector
= this->theVector
;
525 this->theVector
.erase(theConstVector
.begin());
526 this->assertValuesInOrder(this->theVector
, 2u, 2, 3);
529 // Erase a range of elements
530 TYPED_TEST(SmallVectorTest
, EraseRangeTest
) {
531 SCOPED_TRACE("EraseRangeTest");
533 this->makeSequence(this->theVector
, 1, 3);
534 const auto &theConstVector
= this->theVector
;
535 this->theVector
.erase(theConstVector
.begin(), theConstVector
.begin() + 2);
536 this->assertValuesInOrder(this->theVector
, 1u, 3);
539 // Insert a single element.
540 TYPED_TEST(SmallVectorTest
, InsertTest
) {
541 SCOPED_TRACE("InsertTest");
543 this->makeSequence(this->theVector
, 1, 3);
544 typename
TypeParam::iterator I
=
545 this->theVector
.insert(this->theVector
.begin() + 1, Constructable(77));
546 EXPECT_EQ(this->theVector
.begin() + 1, I
);
547 this->assertValuesInOrder(this->theVector
, 4u, 1, 77, 2, 3);
550 // Insert a copy of a single element.
551 TYPED_TEST(SmallVectorTest
, InsertCopy
) {
552 SCOPED_TRACE("InsertTest");
554 this->makeSequence(this->theVector
, 1, 3);
556 typename
TypeParam::iterator I
=
557 this->theVector
.insert(this->theVector
.begin() + 1, C
);
558 EXPECT_EQ(this->theVector
.begin() + 1, I
);
559 this->assertValuesInOrder(this->theVector
, 4u, 1, 77, 2, 3);
562 // Insert repeated elements.
563 TYPED_TEST(SmallVectorTest
, InsertRepeatedTest
) {
564 SCOPED_TRACE("InsertRepeatedTest");
566 this->makeSequence(this->theVector
, 1, 4);
567 Constructable::reset();
569 this->theVector
.insert(this->theVector
.begin() + 1, 2, Constructable(16));
570 // Move construct the top element into newly allocated space, and optionally
571 // reallocate the whole buffer, move constructing into it.
572 // FIXME: This is inefficient, we shouldn't move things into newly allocated
573 // space, then move them up/around, there should only be 2 or 4 move
574 // constructions here.
575 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
576 Constructable::getNumMoveConstructorCalls() == 6);
577 // Move assign the next two to shift them up and make a gap.
578 EXPECT_EQ(1, Constructable::getNumMoveAssignmentCalls());
579 // Copy construct the two new elements from the parameter.
580 EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
581 // All without any copy construction.
582 EXPECT_EQ(0, Constructable::getNumCopyConstructorCalls());
583 EXPECT_EQ(this->theVector
.begin() + 1, I
);
584 this->assertValuesInOrder(this->theVector
, 6u, 1, 16, 16, 2, 3, 4);
587 TYPED_TEST(SmallVectorTest
, InsertRepeatedNonIterTest
) {
588 SCOPED_TRACE("InsertRepeatedTest");
590 this->makeSequence(this->theVector
, 1, 4);
591 Constructable::reset();
592 auto I
= this->theVector
.insert(this->theVector
.begin() + 1, 2, 7);
593 EXPECT_EQ(this->theVector
.begin() + 1, I
);
594 this->assertValuesInOrder(this->theVector
, 6u, 1, 7, 7, 2, 3, 4);
597 TYPED_TEST(SmallVectorTest
, InsertRepeatedAtEndTest
) {
598 SCOPED_TRACE("InsertRepeatedTest");
600 this->makeSequence(this->theVector
, 1, 4);
601 Constructable::reset();
602 auto I
= this->theVector
.insert(this->theVector
.end(), 2, Constructable(16));
603 // Just copy construct them into newly allocated space
604 EXPECT_EQ(2, Constructable::getNumCopyConstructorCalls());
605 // Move everything across if reallocation is needed.
606 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
607 Constructable::getNumMoveConstructorCalls() == 4);
608 // Without ever moving or copying anything else.
609 EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
610 EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
612 EXPECT_EQ(this->theVector
.begin() + 4, I
);
613 this->assertValuesInOrder(this->theVector
, 6u, 1, 2, 3, 4, 16, 16);
616 TYPED_TEST(SmallVectorTest
, InsertRepeatedEmptyTest
) {
617 SCOPED_TRACE("InsertRepeatedTest");
619 this->makeSequence(this->theVector
, 10, 15);
622 EXPECT_EQ(this->theVector
.end(),
623 this->theVector
.insert(this->theVector
.end(),
624 0, Constructable(42)));
625 EXPECT_EQ(this->theVector
.begin() + 1,
626 this->theVector
.insert(this->theVector
.begin() + 1,
627 0, Constructable(42)));
631 TYPED_TEST(SmallVectorTest
, InsertRangeTest
) {
632 SCOPED_TRACE("InsertRangeTest");
634 Constructable Arr
[3] =
635 { Constructable(77), Constructable(77), Constructable(77) };
637 this->makeSequence(this->theVector
, 1, 3);
638 Constructable::reset();
639 auto I
= this->theVector
.insert(this->theVector
.begin() + 1, Arr
, Arr
+ 3);
640 // Move construct the top 3 elements into newly allocated space.
641 // Possibly move the whole sequence into new space first.
642 // FIXME: This is inefficient, we shouldn't move things into newly allocated
643 // space, then move them up/around, there should only be 2 or 3 move
644 // constructions here.
645 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
646 Constructable::getNumMoveConstructorCalls() == 5);
647 // Copy assign the lower 2 new elements into existing space.
648 EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
649 // Copy construct the third element into newly allocated space.
650 EXPECT_EQ(1, Constructable::getNumCopyConstructorCalls());
651 EXPECT_EQ(this->theVector
.begin() + 1, I
);
652 this->assertValuesInOrder(this->theVector
, 6u, 1, 77, 77, 77, 2, 3);
656 TYPED_TEST(SmallVectorTest
, InsertRangeAtEndTest
) {
657 SCOPED_TRACE("InsertRangeTest");
659 Constructable Arr
[3] =
660 { Constructable(77), Constructable(77), Constructable(77) };
662 this->makeSequence(this->theVector
, 1, 3);
665 Constructable::reset();
666 auto I
= this->theVector
.insert(this->theVector
.end(), Arr
, Arr
+3);
667 // Copy construct the 3 elements into new space at the top.
668 EXPECT_EQ(3, Constructable::getNumCopyConstructorCalls());
669 // Don't copy/move anything else.
670 EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
671 // Reallocation might occur, causing all elements to be moved into the new
673 EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
674 Constructable::getNumMoveConstructorCalls() == 3);
675 EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
676 EXPECT_EQ(this->theVector
.begin() + 3, I
);
677 this->assertValuesInOrder(this->theVector
, 6u,
678 1, 2, 3, 77, 77, 77);
681 TYPED_TEST(SmallVectorTest
, InsertEmptyRangeTest
) {
682 SCOPED_TRACE("InsertRangeTest");
684 this->makeSequence(this->theVector
, 1, 3);
687 EXPECT_EQ(this->theVector
.end(),
688 this->theVector
.insert(this->theVector
.end(),
689 this->theVector
.begin(),
690 this->theVector
.begin()));
691 EXPECT_EQ(this->theVector
.begin() + 1,
692 this->theVector
.insert(this->theVector
.begin() + 1,
693 this->theVector
.begin(),
694 this->theVector
.begin()));
698 TYPED_TEST(SmallVectorTest
, ComparisonTest
) {
699 SCOPED_TRACE("ComparisonTest");
701 this->makeSequence(this->theVector
, 1, 3);
702 this->makeSequence(this->otherVector
, 1, 3);
704 EXPECT_TRUE(this->theVector
== this->otherVector
);
705 EXPECT_FALSE(this->theVector
!= this->otherVector
);
707 this->otherVector
.clear();
708 this->makeSequence(this->otherVector
, 2, 4);
710 EXPECT_FALSE(this->theVector
== this->otherVector
);
711 EXPECT_TRUE(this->theVector
!= this->otherVector
);
714 // Constant vector tests.
715 TYPED_TEST(SmallVectorTest
, ConstVectorTest
) {
716 const TypeParam constVector
;
718 EXPECT_EQ(0u, constVector
.size());
719 EXPECT_TRUE(constVector
.empty());
720 EXPECT_TRUE(constVector
.begin() == constVector
.end());
723 // Direct array access.
724 TYPED_TEST(SmallVectorTest
, DirectVectorTest
) {
725 EXPECT_EQ(0u, this->theVector
.size());
726 this->theVector
.reserve(4);
727 EXPECT_LE(4u, this->theVector
.capacity());
728 EXPECT_EQ(0, Constructable::getNumConstructorCalls());
729 this->theVector
.push_back(1);
730 this->theVector
.push_back(2);
731 this->theVector
.push_back(3);
732 this->theVector
.push_back(4);
733 EXPECT_EQ(4u, this->theVector
.size());
734 EXPECT_EQ(8, Constructable::getNumConstructorCalls());
735 EXPECT_EQ(1, this->theVector
[0].getValue());
736 EXPECT_EQ(2, this->theVector
[1].getValue());
737 EXPECT_EQ(3, this->theVector
[2].getValue());
738 EXPECT_EQ(4, this->theVector
[3].getValue());
741 TYPED_TEST(SmallVectorTest
, IteratorTest
) {
743 this->theVector
.insert(this->theVector
.end(), L
.begin(), L
.end());
746 template <typename InvalidType
> class DualSmallVectorsTest
;
748 template <typename VectorT1
, typename VectorT2
>
749 class DualSmallVectorsTest
<std::pair
<VectorT1
, VectorT2
>> : public SmallVectorTestBase
{
752 VectorT2 otherVector
;
754 template <typename T
, unsigned N
>
755 static unsigned NumBuiltinElts(const SmallVector
<T
, N
>&) { return N
; }
758 typedef ::testing::Types
<
759 // Small mode -> Small mode.
760 std::pair
<SmallVector
<Constructable
, 4>, SmallVector
<Constructable
, 4>>,
761 // Small mode -> Big mode.
762 std::pair
<SmallVector
<Constructable
, 4>, SmallVector
<Constructable
, 2>>,
763 // Big mode -> Small mode.
764 std::pair
<SmallVector
<Constructable
, 2>, SmallVector
<Constructable
, 4>>,
765 // Big mode -> Big mode.
766 std::pair
<SmallVector
<Constructable
, 2>, SmallVector
<Constructable
, 2>>
767 > DualSmallVectorTestTypes
;
769 TYPED_TEST_CASE(DualSmallVectorsTest
, DualSmallVectorTestTypes
);
771 TYPED_TEST(DualSmallVectorsTest
, MoveAssignment
) {
772 SCOPED_TRACE("MoveAssignTest-DualVectorTypes");
774 // Set up our vector with four elements.
775 for (unsigned I
= 0; I
< 4; ++I
)
776 this->otherVector
.push_back(Constructable(I
));
778 const Constructable
*OrigDataPtr
= this->otherVector
.data();
780 // Move-assign from the other vector.
782 std::move(static_cast<SmallVectorImpl
<Constructable
>&>(this->otherVector
));
784 // Make sure we have the right result.
785 this->assertValuesInOrder(this->theVector
, 4u, 0, 1, 2, 3);
787 // Make sure the # of constructor/destructor calls line up. There
788 // are two live objects after clearing the other vector.
789 this->otherVector
.clear();
790 EXPECT_EQ(Constructable::getNumConstructorCalls()-4,
791 Constructable::getNumDestructorCalls());
793 // If the source vector (otherVector) was in small-mode, assert that we just
794 // moved the data pointer over.
795 EXPECT_TRUE(this->NumBuiltinElts(this->otherVector
) == 4 ||
796 this->theVector
.data() == OrigDataPtr
);
798 // There shouldn't be any live objects any more.
799 this->theVector
.clear();
800 EXPECT_EQ(Constructable::getNumConstructorCalls(),
801 Constructable::getNumDestructorCalls());
803 // We shouldn't have copied anything in this whole process.
804 EXPECT_EQ(Constructable::getNumCopyConstructorCalls(), 0);
807 struct notassignable
{
809 notassignable(int &x
) : x(x
) {}
812 TEST(SmallVectorCustomTest
, NoAssignTest
) {
814 SmallVector
<notassignable
, 2> vec
;
815 vec
.push_back(notassignable(x
));
817 EXPECT_EQ(42, vec
.pop_back_val().x
);
822 MovedFrom() : hasValue(true) {
824 MovedFrom(MovedFrom
&& m
) : hasValue(m
.hasValue
) {
827 MovedFrom
&operator=(MovedFrom
&& m
) {
828 hasValue
= m
.hasValue
;
834 TEST(SmallVectorTest
, MidInsert
) {
835 SmallVector
<MovedFrom
, 3> v
;
836 v
.push_back(MovedFrom());
837 v
.insert(v
.begin(), MovedFrom());
838 for (MovedFrom
&m
: v
)
839 EXPECT_TRUE(m
.hasValue
);
842 enum EmplaceableArgState
{
849 template <int I
> struct EmplaceableArg
{
850 EmplaceableArgState State
;
851 EmplaceableArg() : State(EAS_Defaulted
) {}
852 EmplaceableArg(EmplaceableArg
&&X
)
853 : State(X
.State
== EAS_Arg
? EAS_RValue
: EAS_Failure
) {}
854 EmplaceableArg(EmplaceableArg
&X
)
855 : State(X
.State
== EAS_Arg
? EAS_LValue
: EAS_Failure
) {}
857 explicit EmplaceableArg(bool) : State(EAS_Arg
) {}
860 EmplaceableArg
&operator=(EmplaceableArg
&&) = delete;
861 EmplaceableArg
&operator=(const EmplaceableArg
&) = delete;
864 enum EmplaceableState
{ ES_Emplaced
, ES_Moved
};
866 EmplaceableArg
<0> A0
;
867 EmplaceableArg
<1> A1
;
868 EmplaceableArg
<2> A2
;
869 EmplaceableArg
<3> A3
;
870 EmplaceableState State
;
872 Emplaceable() : State(ES_Emplaced
) {}
874 template <class A0Ty
>
875 explicit Emplaceable(A0Ty
&&A0
)
876 : A0(std::forward
<A0Ty
>(A0
)), State(ES_Emplaced
) {}
878 template <class A0Ty
, class A1Ty
>
879 Emplaceable(A0Ty
&&A0
, A1Ty
&&A1
)
880 : A0(std::forward
<A0Ty
>(A0
)), A1(std::forward
<A1Ty
>(A1
)),
881 State(ES_Emplaced
) {}
883 template <class A0Ty
, class A1Ty
, class A2Ty
>
884 Emplaceable(A0Ty
&&A0
, A1Ty
&&A1
, A2Ty
&&A2
)
885 : A0(std::forward
<A0Ty
>(A0
)), A1(std::forward
<A1Ty
>(A1
)),
886 A2(std::forward
<A2Ty
>(A2
)), State(ES_Emplaced
) {}
888 template <class A0Ty
, class A1Ty
, class A2Ty
, class A3Ty
>
889 Emplaceable(A0Ty
&&A0
, A1Ty
&&A1
, A2Ty
&&A2
, A3Ty
&&A3
)
890 : A0(std::forward
<A0Ty
>(A0
)), A1(std::forward
<A1Ty
>(A1
)),
891 A2(std::forward
<A2Ty
>(A2
)), A3(std::forward
<A3Ty
>(A3
)),
892 State(ES_Emplaced
) {}
894 Emplaceable(Emplaceable
&&) : State(ES_Moved
) {}
895 Emplaceable
&operator=(Emplaceable
&&) {
901 Emplaceable(const Emplaceable
&) = delete;
902 Emplaceable
&operator=(const Emplaceable
&) = delete;
905 TEST(SmallVectorTest
, EmplaceBack
) {
906 EmplaceableArg
<0> A0(true);
907 EmplaceableArg
<1> A1(true);
908 EmplaceableArg
<2> A2(true);
909 EmplaceableArg
<3> A3(true);
911 SmallVector
<Emplaceable
, 3> V
;
913 EXPECT_TRUE(V
.size() == 1);
914 EXPECT_TRUE(V
.back().State
== ES_Emplaced
);
915 EXPECT_TRUE(V
.back().A0
.State
== EAS_Defaulted
);
916 EXPECT_TRUE(V
.back().A1
.State
== EAS_Defaulted
);
917 EXPECT_TRUE(V
.back().A2
.State
== EAS_Defaulted
);
918 EXPECT_TRUE(V
.back().A3
.State
== EAS_Defaulted
);
921 SmallVector
<Emplaceable
, 3> V
;
922 V
.emplace_back(std::move(A0
));
923 EXPECT_TRUE(V
.size() == 1);
924 EXPECT_TRUE(V
.back().State
== ES_Emplaced
);
925 EXPECT_TRUE(V
.back().A0
.State
== EAS_RValue
);
926 EXPECT_TRUE(V
.back().A1
.State
== EAS_Defaulted
);
927 EXPECT_TRUE(V
.back().A2
.State
== EAS_Defaulted
);
928 EXPECT_TRUE(V
.back().A3
.State
== EAS_Defaulted
);
931 SmallVector
<Emplaceable
, 3> V
;
933 EXPECT_TRUE(V
.size() == 1);
934 EXPECT_TRUE(V
.back().State
== ES_Emplaced
);
935 EXPECT_TRUE(V
.back().A0
.State
== EAS_LValue
);
936 EXPECT_TRUE(V
.back().A1
.State
== EAS_Defaulted
);
937 EXPECT_TRUE(V
.back().A2
.State
== EAS_Defaulted
);
938 EXPECT_TRUE(V
.back().A3
.State
== EAS_Defaulted
);
941 SmallVector
<Emplaceable
, 3> V
;
942 V
.emplace_back(A0
, A1
);
943 EXPECT_TRUE(V
.size() == 1);
944 EXPECT_TRUE(V
.back().State
== ES_Emplaced
);
945 EXPECT_TRUE(V
.back().A0
.State
== EAS_LValue
);
946 EXPECT_TRUE(V
.back().A1
.State
== EAS_LValue
);
947 EXPECT_TRUE(V
.back().A2
.State
== EAS_Defaulted
);
948 EXPECT_TRUE(V
.back().A3
.State
== EAS_Defaulted
);
951 SmallVector
<Emplaceable
, 3> V
;
952 V
.emplace_back(std::move(A0
), std::move(A1
));
953 EXPECT_TRUE(V
.size() == 1);
954 EXPECT_TRUE(V
.back().State
== ES_Emplaced
);
955 EXPECT_TRUE(V
.back().A0
.State
== EAS_RValue
);
956 EXPECT_TRUE(V
.back().A1
.State
== EAS_RValue
);
957 EXPECT_TRUE(V
.back().A2
.State
== EAS_Defaulted
);
958 EXPECT_TRUE(V
.back().A3
.State
== EAS_Defaulted
);
961 SmallVector
<Emplaceable
, 3> V
;
962 V
.emplace_back(std::move(A0
), A1
, std::move(A2
), A3
);
963 EXPECT_TRUE(V
.size() == 1);
964 EXPECT_TRUE(V
.back().State
== ES_Emplaced
);
965 EXPECT_TRUE(V
.back().A0
.State
== EAS_RValue
);
966 EXPECT_TRUE(V
.back().A1
.State
== EAS_LValue
);
967 EXPECT_TRUE(V
.back().A2
.State
== EAS_RValue
);
968 EXPECT_TRUE(V
.back().A3
.State
== EAS_LValue
);
971 SmallVector
<int, 1> V
;
974 EXPECT_EQ(2U, V
.size());
980 TEST(SmallVectorTest
, InitializerList
) {
981 SmallVector
<int, 2> V1
= {};
982 EXPECT_TRUE(V1
.empty());
984 EXPECT_TRUE(makeArrayRef(V1
).equals({0, 0}));
986 EXPECT_TRUE(makeArrayRef(V1
).equals({-1, -1}));
988 SmallVector
<int, 2> V2
= {1, 2, 3, 4};
989 EXPECT_TRUE(makeArrayRef(V2
).equals({1, 2, 3, 4}));
991 EXPECT_TRUE(makeArrayRef(V2
).equals({4}));
993 EXPECT_TRUE(makeArrayRef(V2
).equals({4, 3, 2}));
994 V2
.insert(V2
.begin() + 1, 5);
995 EXPECT_TRUE(makeArrayRef(V2
).equals({4, 5, 3, 2}));