2 * Copyright 2017 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <folly/small_vector.h>
27 #include <boost/algorithm/string.hpp>
29 #include <folly/Conv.h>
30 #include <folly/portability/GTest.h>
31 #include <folly/portability/TypeTraits.h>
33 using folly::small_vector;
34 using namespace folly::small_vector_policy;
36 #if FOLLY_X64 || FOLLY_PPC64
38 static_assert(sizeof(small_vector<int>) == 16,
39 "Object size is not what we expect for small_vector<int>");
40 static_assert(sizeof(small_vector<int32_t,2>) == 16,
41 "Object size is not what we expect for "
42 "small_vector<int32_t,2>");
43 static_assert(sizeof(small_vector<int,10>) ==
44 10 * sizeof(int) + sizeof(std::size_t),
45 "Object size is not what we expect for small_vector<int,10>");
47 static_assert(sizeof(small_vector<int32_t,1,uint32_t>) ==
49 "small_vector<int32_t,1,uint32_t> is wrong size");
50 static_assert(sizeof(small_vector<int32_t,1,uint16_t>) ==
52 "small_vector<int32_t,1,uint32_t> is wrong size");
53 static_assert(sizeof(small_vector<int32_t,1,uint8_t>) ==
55 "small_vector<int32_t,1,uint32_t> is wrong size");
57 static_assert(sizeof(small_vector<int16_t,4,uint16_t>) == 10,
58 "Sizeof unexpectedly large");
62 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(std::unique_ptr<int>),
63 "std::unique_ptr<> is trivially copyable");
67 struct NontrivialType {
69 explicit NontrivialType() : a(0) {}
71 /* implicit */ NontrivialType(int a) : a(a) {
75 NontrivialType(NontrivialType const& /* s */) { ++ctored; }
77 NontrivialType& operator=(NontrivialType const& o) {
84 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(NontrivialType),
85 "NontrivialType is trivially copyable");
87 int NontrivialType::ctored = 0;
89 struct TestException {};
93 if (!--throwCounter) {
94 throw TestException();
98 const int kMagic = 0xdeadbeef;
102 Thrower() : magic(kMagic) {
103 EXPECT_EQ(magic, kMagic);
107 Thrower(Thrower const& other) : magic(other.magic) {
108 EXPECT_EQ(magic, kMagic);
112 ~Thrower() noexcept {
113 EXPECT_EQ(magic, kMagic);
118 Thrower& operator=(Thrower const& /* other */) {
119 EXPECT_EQ(magic, kMagic);
124 // This is just to try to make sure we don't get our member
125 // functions called on uninitialized memory.
129 int Thrower::alive = 0;
131 // Type that counts how many exist and doesn't support copy
133 struct NoncopyableCounter {
135 NoncopyableCounter() {
138 ~NoncopyableCounter() {
141 NoncopyableCounter(NoncopyableCounter&&) noexcept { ++alive; }
142 NoncopyableCounter(NoncopyableCounter const&) = delete;
143 NoncopyableCounter& operator=(NoncopyableCounter const&) const = delete;
144 NoncopyableCounter& operator=(NoncopyableCounter&&) { return *this; }
146 int NoncopyableCounter::alive = 0;
148 static_assert(!FOLLY_IS_TRIVIALLY_COPYABLE(NoncopyableCounter),
149 "NoncopyableCounter is trivially copyable");
151 // Check that throws don't break the basic guarantee for some cases.
152 // Uses the method for testing exception safety described at
153 // http://www.boost.org/community/exception_safety.html, to force all
154 // throwing code paths to occur.
155 struct TestBasicGuarantee {
156 folly::small_vector<Thrower,3> vec;
157 int const prepopulate;
159 explicit TestBasicGuarantee(int prepopulate)
160 : prepopulate(prepopulate)
163 for (int i = 0; i < prepopulate; ++i) {
168 ~TestBasicGuarantee() {
172 template<class Operation>
173 void operator()(int insertCount, Operation const& op) {
176 std::unique_ptr<folly::small_vector<Thrower,3> > workingVec;
177 for (int counter = 1; !done; ++counter) {
179 workingVec.reset(new folly::small_vector<Thrower,3>(vec));
180 throwCounter = counter;
181 EXPECT_EQ(Thrower::alive, prepopulate * 2);
186 // Note that the size of the vector can change if we were
187 // inserting somewhere other than the end (it's a basic only
188 // guarantee). All we're testing here is that we have the
189 // right amount of uninitialized vs initialized memory.
190 EXPECT_EQ(Thrower::alive, workingVec->size() + vec.size());
194 // If things succeeded.
195 EXPECT_EQ(workingVec->size(), prepopulate + insertCount);
196 EXPECT_EQ(Thrower::alive, prepopulate * 2 + insertCount);
203 TEST(small_vector, BasicGuarantee) {
204 for (int prepop = 1; prepop < 30; ++prepop) {
205 (TestBasicGuarantee(prepop))( // parens or a mildly vexing parse :(
207 [&] (folly::small_vector<Thrower,3>& v) {
212 EXPECT_EQ(Thrower::alive, 0);
214 (TestBasicGuarantee(prepop))(
216 [&] (folly::small_vector<Thrower,3>& v) {
217 v.insert(v.begin(), Thrower());
221 EXPECT_EQ(Thrower::alive, 0);
223 (TestBasicGuarantee(prepop))(
225 [&] (folly::small_vector<Thrower,3>& v) {
226 v.insert(v.begin() + 1, Thrower());
230 EXPECT_EQ(Thrower::alive, 0);
233 TestBasicGuarantee(4)(
235 [&] (folly::small_vector<Thrower,3>& v) {
236 std::vector<Thrower> b;
242 * Apparently if you do the following initializer_list instead
243 * of the above push_back's, and one of the Throwers throws,
244 * g++4.6 doesn't destruct the previous ones. Heh.
246 //b = { Thrower(), Thrower(), Thrower() };
247 v.insert(v.begin() + 1, b.begin(), b.end());
251 TestBasicGuarantee(2)(
253 [&] (folly::small_vector<Thrower,3>& v) {
254 std::vector<Thrower> b;
255 for (int i = 0; i < 6; ++i) {
259 v.insert(v.begin() + 1, b.begin(), b.end());
263 EXPECT_EQ(Thrower::alive, 0);
266 folly::small_vector<Thrower,1> p(14, Thrower());
269 EXPECT_EQ(Thrower::alive, 0);
273 // MALLOC_CONF=prof_leak:true
274 // LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.2
275 // LD_PRELOAD="$LD_PRELOAD:"${UNWIND_PATH}/lib/libunwind.so.7
276 TEST(small_vector, leak_test) {
277 for (int j = 0; j < 1000; ++j) {
278 folly::small_vector<int, 10> someVec(300);
279 for (int i = 0; i < 10000; ++i) {
280 someVec.push_back(12);
285 TEST(small_vector, Insert) {
286 folly::small_vector<int> someVec(3, 3);
287 someVec.insert(someVec.begin(), 12, 12);
288 EXPECT_EQ(someVec.size(), 15);
289 for (size_t i = 0; i < someVec.size(); ++i) {
291 EXPECT_EQ(someVec[i], 12);
293 EXPECT_EQ(someVec[i], 3);
297 auto oldSize = someVec.size();
298 someVec.insert(someVec.begin() + 1, 12, 12);
299 EXPECT_EQ(someVec.size(), oldSize + 12);
301 folly::small_vector<std::string> v1(6, "asd"), v2(7, "wat");
302 v1.insert(v1.begin() + 1, v2.begin(), v2.end());
303 EXPECT_TRUE(v1.size() == 6 + 7);
304 EXPECT_EQ(v1.front(), "asd");
305 EXPECT_EQ(v1[1], "wat");
308 TEST(small_vector, Swap) {
309 folly::small_vector<int,10> somethingVec, emptyVec;
310 somethingVec.push_back(1);
311 somethingVec.push_back(2);
312 somethingVec.push_back(3);
313 somethingVec.push_back(4);
315 // Swapping intern'd with intern'd.
316 auto vec = somethingVec;
317 EXPECT_TRUE(vec == somethingVec);
318 EXPECT_FALSE(vec == emptyVec);
319 EXPECT_FALSE(somethingVec == emptyVec);
321 // Swapping a heap vector with an intern vector.
322 folly::small_vector<int,10> junkVec;
323 junkVec.assign(12, 12);
324 EXPECT_EQ(junkVec.size(), 12);
325 for (auto i : junkVec) {
329 EXPECT_TRUE(junkVec == somethingVec);
330 EXPECT_EQ(vec.size(), 12);
335 // Swapping two heap vectors.
336 folly::small_vector<int,10> moreJunk(15, 15);
337 EXPECT_EQ(moreJunk.size(), 15);
338 for (auto i : moreJunk) {
342 EXPECT_EQ(moreJunk.size(), 12);
343 for (auto i : moreJunk) {
346 EXPECT_EQ(vec.size(), 15);
351 // Making a vector heap, then smaller than another non-heap vector,
353 folly::small_vector<int,5> shrinker, other(4, 10);
354 shrinker = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
355 shrinker.erase(shrinker.begin() + 2, shrinker.end());
356 EXPECT_LT(shrinker.size(), other.size());
357 swap(shrinker, other);
358 EXPECT_EQ(shrinker.size(), 4);
359 EXPECT_TRUE(boost::all(shrinker, boost::is_any_of(std::vector<int>{10})));
360 EXPECT_TRUE((other == small_vector<int,5>{ 0, 1 }));
363 TEST(small_vector, Emplace) {
364 NontrivialType::ctored = 0;
366 folly::small_vector<NontrivialType> vec;
368 vec.emplace_back(12);
369 EXPECT_EQ(NontrivialType::ctored, 1);
370 EXPECT_EQ(vec.front().a, 12);
371 vec.emplace_back(13);
372 EXPECT_EQ(vec.front().a, 12);
373 EXPECT_EQ(vec.back().a, 13);
374 EXPECT_EQ(NontrivialType::ctored, 2);
376 NontrivialType::ctored = 0;
377 for (int i = 0; i < 120; ++i) {
380 EXPECT_EQ(NontrivialType::ctored, 120);
381 EXPECT_EQ(vec[0].a, 12);
382 EXPECT_EQ(vec[1].a, 13);
383 EXPECT_EQ(vec.back().a, 119);
385 // We implement emplace() with a temporary (see the implementation
386 // for a comment about why), so this should make 2 ctor calls.
387 NontrivialType::ctored = 0;
388 vec.emplace(vec.begin(), 12);
389 EXPECT_EQ(NontrivialType::ctored, 2);
392 TEST(small_vector, Erase) {
393 folly::small_vector<int,4> notherVec = { 1, 2, 3, 4, 5 };
394 EXPECT_EQ(notherVec.front(), 1);
395 EXPECT_EQ(notherVec.size(), 5);
396 notherVec.erase(notherVec.begin());
397 EXPECT_EQ(notherVec.front(), 2);
398 EXPECT_EQ(notherVec.size(), 4);
399 EXPECT_EQ(notherVec[2], 4);
400 EXPECT_EQ(notherVec[3], 5);
401 notherVec.erase(notherVec.begin() + 2);
402 EXPECT_EQ(notherVec.size(), 3);
403 EXPECT_EQ(notherVec[2], 5);
405 folly::small_vector<int,2> vec2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
406 vec2.erase(vec2.begin() + 1, vec2.end() - 1);
407 folly::small_vector<int,2> expected = { 1, 10 };
408 EXPECT_TRUE(vec2 == expected);
410 folly::small_vector<std::string,3> v(102, "ASD");
412 EXPECT_EQ(v.size(), 1024);
413 EXPECT_EQ(v.back(), "D");
414 EXPECT_EQ(v.front(), "ASD");
416 EXPECT_EQ(v.front(), "ASD");
417 EXPECT_EQ(v.size(), 1);
419 EXPECT_TRUE(v.empty());
422 TEST(small_vector, GrowShrinkGrow) {
423 folly::small_vector<NontrivialType,7> vec = { 1, 2, 3, 4, 5 };
424 std::generate_n(std::back_inserter(vec), 102, std::rand);
426 auto capacity = vec.capacity();
428 auto oldSize = vec.size();
429 for (size_t i = 0; i < oldSize; ++i) {
430 vec.erase(vec.begin() + (std::rand() % vec.size()));
431 EXPECT_EQ(vec.capacity(), capacity);
433 EXPECT_TRUE(vec.empty());
435 EXPECT_EQ(vec.capacity(), capacity);
436 std::generate_n(std::back_inserter(vec), 102, std::rand);
437 EXPECT_EQ(vec.capacity(), capacity);
439 std::generate_n(std::back_inserter(vec), 4096, std::rand);
440 EXPECT_GT(vec.capacity(), capacity);
444 EXPECT_LT(vec.capacity(), capacity);
447 EXPECT_EQ(vec.capacity(), 7); // in situ size
450 TEST(small_vector, Iteration) {
451 folly::small_vector<std::string,3> vec = { "foo", "bar" };
452 vec.push_back("blah");
453 vec.push_back("blah2");
454 vec.push_back("blah3");
455 vec.erase(vec.begin() + 2);
457 std::vector<std::string> otherVec;
458 for (auto& s : vec) {
459 otherVec.push_back(s);
461 EXPECT_EQ(otherVec.size(), vec.size());
462 if (otherVec.size() == vec.size()) {
463 EXPECT_TRUE(std::equal(otherVec.begin(), otherVec.end(), vec.begin()));
466 std::reverse(otherVec.begin(), otherVec.end());
467 auto oit = otherVec.begin();
468 auto rit = vec.crbegin();
469 for (; rit != vec.crend(); ++oit, ++rit) {
470 EXPECT_EQ(*oit, *rit);
474 TEST(small_vector, NonCopyableType) {
475 folly::small_vector<NontrivialType,2> vec;
477 for (int i = 0; i < 10; ++i) {
478 vec.emplace(vec.begin(), 13);
480 EXPECT_EQ(vec.size(), 10);
481 auto vec2 = std::move(vec);
482 EXPECT_EQ(vec.size(), 0);
483 EXPECT_EQ(vec2.size(), 10);
486 folly::small_vector<NoncopyableCounter,3> vec3;
487 for (int i = 0; i < 10; ++i) {
488 EXPECT_EQ(vec3.size(), i);
489 EXPECT_EQ(NoncopyableCounter::alive, i);
490 vec3.insert(vec3.begin(), NoncopyableCounter());
492 EXPECT_EQ(vec3.size(), 10);
493 EXPECT_EQ(NoncopyableCounter::alive, 10);
495 vec3.insert(vec3.begin() + 3, NoncopyableCounter());
496 EXPECT_EQ(NoncopyableCounter::alive, 11);
497 auto vec4 = std::move(vec3);
498 EXPECT_EQ(NoncopyableCounter::alive, 11);
500 EXPECT_EQ(NoncopyableCounter::alive, 30);
501 vec4.erase(vec4.begin(), vec4.end());
502 EXPECT_EQ(vec4.size(), 0);
503 EXPECT_EQ(NoncopyableCounter::alive, 0);
506 TEST(small_vector, MoveConstructor) {
507 folly::small_vector<std::string,10> v1;
510 auto v2 = std::move(v1);
511 EXPECT_EQ(v2.size(), 2);
512 EXPECT_EQ(v2[0], "asd");
513 EXPECT_EQ(v2[1], "bsd");
516 EXPECT_EQ(v1.size(), 2);
517 EXPECT_EQ(v1[0], "asd");
518 EXPECT_EQ(v1[1], "bsd");
521 TEST(small_vector, NoHeap) {
522 typedef folly::small_vector<std::string,10,
523 std::size_t,folly::small_vector_policy::NoHeap> Vector;
526 static_assert(v.max_size() == 10, "max_size is incorrect");
528 for (int i = 0; i < 10; ++i) {
529 v.push_back(folly::to<std::string>(i));
530 EXPECT_EQ(v.size(), i + 1);
535 v.insert(v.begin(), "ha");
536 } catch (const std::length_error&) {
541 // Check max_size works right with various policy combinations.
542 folly::small_vector<std::string,32,uint32_t> v4;
543 EXPECT_EQ(v4.max_size(), (1ul << 31) - 1);
546 * Test that even when we ask for a small number inlined it'll still
547 * inline at least as much as it takes to store the value_type
550 folly::small_vector<char,1,NoHeap> notsosmall;
551 static_assert(notsosmall.max_size() == sizeof(char*),
552 "max_size is incorrect");
555 notsosmall.push_back(12);
556 notsosmall.push_back(13);
557 notsosmall.push_back(14);
558 } catch (const std::length_error&) {
561 EXPECT_FALSE(caught);
564 TEST(small_vector, MaxSize) {
565 folly::small_vector<int,2,uint8_t> vec;
566 EXPECT_EQ(vec.max_size(), 127);
567 folly::small_vector<int,2,uint16_t> vec2;
568 EXPECT_EQ(vec2.max_size(), (1 << 15) - 1);
571 TEST(small_vector, AllHeap) {
572 // Use something bigger than the pointer so it can't get inlined.
574 double a, b, c, d, e; int val;
575 SomeObj(int val) : val(val) {}
576 bool operator==(SomeObj const& o) const {
581 folly::small_vector<SomeObj,0> vec = { 1 };
582 EXPECT_EQ(vec.size(), 1);
584 EXPECT_TRUE(vec[0] == 1);
586 vec.insert(vec.begin(), { 0, 1, 2, 3 });
587 EXPECT_EQ(vec.size(), 5);
588 EXPECT_TRUE((vec == folly::small_vector<SomeObj,0>{ 0, 1, 2, 3, 1 }));
591 TEST(small_vector, Basic) {
592 typedef folly::small_vector<int,3,uint32_t
598 EXPECT_EQ(a.front(), 12);
599 EXPECT_EQ(a.size(), 1);
601 EXPECT_EQ(a.size(), 2);
602 EXPECT_EQ(a.front(), 12);
603 EXPECT_EQ(a.back(), 13);
605 a.emplace(a.end(), 32);
606 EXPECT_EQ(a.back(), 32);
608 a.emplace(a.begin(), 12);
609 EXPECT_EQ(a.front(), 12);
610 EXPECT_EQ(a.back(), 32);
611 a.erase(a.end() - 1);
612 EXPECT_EQ(a.back(), 13);
615 EXPECT_EQ(a.back(), 12);
617 EXPECT_EQ(a.back(), 13);
620 a.push_back(s); // lvalue reference
627 EXPECT_TRUE(c != b && b != a);
629 EXPECT_GT(c.size(), 0);
631 EXPECT_EQ(c.size(), 1);
636 TEST(small_vector, Capacity) {
637 folly::small_vector<uint64_t, 1> vec;
638 EXPECT_EQ(vec.size(), 0);
639 EXPECT_EQ(vec.capacity(), 1);
642 EXPECT_EQ(vec.size(), 1);
643 EXPECT_EQ(vec.capacity(), 1);
646 EXPECT_EQ(vec.size(), 2);
647 EXPECT_GT(vec.capacity(), 1);
649 folly::small_vector<uint64_t, 2> vec2;
650 EXPECT_EQ(vec2.size(), 0);
651 EXPECT_EQ(vec2.capacity(), 2);
655 EXPECT_EQ(vec2.size(), 2);
656 EXPECT_EQ(vec2.capacity(), 2);
659 EXPECT_EQ(vec2.size(), 3);
660 EXPECT_GT(vec2.capacity(), 2);
662 // Test capacity heapifying logic
663 folly::small_vector<unsigned char, 1> vec3;
664 const size_t hc_size = 100000;
665 for (size_t i = 0; i < hc_size; ++i) {
666 auto v = (unsigned char)i;
668 EXPECT_EQ(vec3[i], v);
669 EXPECT_EQ(vec3.size(), i + 1);
670 EXPECT_GT(vec3.capacity(), i);
672 for (auto i = hc_size; i > 0; --i) {
673 auto v = (unsigned char)(i - 1);
674 EXPECT_EQ(vec3.back(), v);
676 EXPECT_EQ(vec3.size(), i - 1);
680 TEST(small_vector, SelfPushBack) {
681 for (int i = 1; i < 33; ++i) {
682 folly::small_vector<std::string> vec;
683 for (int j = 0; j < i; ++j) {
684 vec.push_back("abc");
686 EXPECT_EQ(vec.size(), i);
687 vec.push_back(std::move(vec[0]));
688 EXPECT_EQ(vec.size(), i + 1);
690 EXPECT_EQ(vec[i], "abc");
694 TEST(small_vector, SelfEmplaceBack) {
695 for (int i = 1; i < 33; ++i) {
696 folly::small_vector<std::string> vec;
697 for (int j = 0; j < i; ++j) {
698 vec.emplace_back("abc");
700 EXPECT_EQ(vec.size(), i);
701 vec.emplace_back(std::move(vec[0]));
702 EXPECT_EQ(vec.size(), i + 1);
704 EXPECT_EQ(vec[i], "abc");
708 TEST(small_vector, SelfInsert) {
710 for (int i = 1; i < 33; ++i) {
711 folly::small_vector<std::string> vec;
712 for (int j = 0; j < i; ++j) {
713 vec.push_back("abc");
715 EXPECT_EQ(vec.size(), i);
716 vec.insert(vec.end(), std::move(vec[0]));
717 EXPECT_EQ(vec.size(), i + 1);
719 EXPECT_EQ(vec[i], "abc");
720 EXPECT_EQ(vec[vec.size() - 1], "abc");
724 for (int i = 2; i < 33; ++i) {
725 folly::small_vector<std::string> vec;
726 for (int j = 0; j < i; ++j) {
727 vec.push_back("abc");
729 EXPECT_EQ(vec.size(), i);
730 vec.insert(vec.end()-1, std::move(vec[0]));
731 EXPECT_EQ(vec.size(), i + 1);
733 EXPECT_EQ(vec[i-1], "abc");
734 EXPECT_EQ(vec[i], "abc");
739 static const int DEFAULT_VALUE = (int)0xdeadbeef;
740 CheckedInt(): value(DEFAULT_VALUE) {}
741 explicit CheckedInt(int value): value(value) {}
742 CheckedInt(const CheckedInt& rhs): value(rhs.value) {}
743 CheckedInt(CheckedInt&& rhs) noexcept: value(rhs.value) {
744 rhs.value = DEFAULT_VALUE;
746 CheckedInt& operator= (const CheckedInt& rhs) {
750 CheckedInt& operator= (CheckedInt&& rhs) noexcept {
752 rhs.value = DEFAULT_VALUE;
759 TEST(small_vector, LVEmplaceInsideVector) {
760 folly::small_vector<CheckedInt> v;
761 v.push_back(CheckedInt(1));
762 for (int i = 1; i < 20; ++i) {
763 v.emplace_back(v[0]);
764 ASSERT_EQ(1, v.back().value);
768 TEST(small_vector, CLVEmplaceInsideVector) {
769 folly::small_vector<CheckedInt> v;
770 const folly::small_vector<CheckedInt>& cv = v;
771 v.push_back(CheckedInt(1));
772 for (int i = 1; i < 20; ++i) {
773 v.emplace_back(cv[0]);
774 ASSERT_EQ(1, v.back().value);
778 TEST(small_vector, RVEmplaceInsideVector) {
779 folly::small_vector<CheckedInt> v;
780 v.push_back(CheckedInt(0));
781 for (int i = 1; i < 20; ++i) {
782 v[0] = CheckedInt(1);
783 v.emplace_back(std::move(v[0]));
784 ASSERT_EQ(1, v.back().value);
788 TEST(small_vector, LVPushValueInsideVector) {
789 folly::small_vector<CheckedInt> v;
790 v.push_back(CheckedInt(1));
791 for (int i = 1; i < 20; ++i) {
793 ASSERT_EQ(1, v.back().value);
797 TEST(small_vector, RVPushValueInsideVector) {
798 folly::small_vector<CheckedInt> v;
799 v.push_back(CheckedInt(0));
800 for (int i = 1; i < 20; ++i) {
801 v[0] = CheckedInt(1);
803 ASSERT_EQ(1, v.back().value);
807 TEST(small_vector, EmplaceIterCtor) {
808 std::vector<int*> v{new int(1), new int(2)};
809 std::vector<std::unique_ptr<int>> uv(v.begin(), v.end());
811 std::vector<int*> w{new int(1), new int(2)};
812 small_vector<std::unique_ptr<int>> uw(w.begin(), w.end());
815 TEST(small_vector, InputIterator) {
816 std::vector<int> expected{125, 320, 512, 750, 333};
817 std::string values = "125 320 512 750 333";
818 std::istringstream is1(values);
819 std::istringstream is2(values);
821 std::vector<int> stdV{std::istream_iterator<int>(is1),
822 std::istream_iterator<int>()};
823 ASSERT_EQ(stdV.size(), expected.size());
824 for (size_t i = 0; i < expected.size(); i++) {
825 ASSERT_EQ(stdV[i], expected[i]);
828 small_vector<int> smallV{std::istream_iterator<int>(is2),
829 std::istream_iterator<int>()};
830 ASSERT_EQ(smallV.size(), expected.size());
831 for (size_t i = 0; i < expected.size(); i++) {
832 ASSERT_EQ(smallV[i], expected[i]);
836 TEST(small_vector, NoCopyCtor) {
839 Test(const Test&) = delete;
840 Test(Test&&) = default;
845 small_vector<Test> test(10);
846 ASSERT_EQ(test.size(), 10);
847 for (const auto& element : test) {
848 EXPECT_EQ(element.field, 42);
852 TEST(small_vector, ZeroInitializable) {
853 small_vector<int> test(10);
854 ASSERT_EQ(test.size(), 10);
855 for (const auto& element : test) {
856 EXPECT_EQ(element, 0);