• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/container/inlined_vector.h"
16 
17 #include <algorithm>
18 #include <cstddef>
19 #include <forward_list>
20 #include <iterator>
21 #include <list>
22 #include <memory>
23 #include <scoped_allocator>
24 #include <sstream>
25 #include <stdexcept>
26 #include <string>
27 #include <utility>
28 #include <vector>
29 
30 #include "gmock/gmock.h"
31 #include "gtest/gtest.h"
32 #include "absl/base/attributes.h"
33 #include "absl/base/internal/exception_testing.h"
34 #include "absl/base/internal/raw_logging.h"
35 #include "absl/base/macros.h"
36 #include "absl/base/options.h"
37 #include "absl/container/internal/counting_allocator.h"
38 #include "absl/container/internal/test_instance_tracker.h"
39 #include "absl/hash/hash_testing.h"
40 #include "absl/memory/memory.h"
41 #include "absl/strings/str_cat.h"
42 
43 namespace {
44 
45 using absl::container_internal::CountingAllocator;
46 using absl::test_internal::CopyableMovableInstance;
47 using absl::test_internal::CopyableOnlyInstance;
48 using absl::test_internal::InstanceTracker;
49 using testing::AllOf;
50 using testing::Each;
51 using testing::ElementsAre;
52 using testing::ElementsAreArray;
53 using testing::Eq;
54 using testing::Gt;
55 using testing::Pointee;
56 using testing::Pointwise;
57 using testing::PrintToString;
58 using testing::SizeIs;
59 
60 using IntVec = absl::InlinedVector<int, 8>;
61 
62 MATCHER_P(CapacityIs, n, "") {
63   return testing::ExplainMatchResult(n, arg.capacity(), result_listener);
64 }
65 
66 MATCHER_P(ValueIs, e, "") {
67   return testing::ExplainMatchResult(e, arg.value(), result_listener);
68 }
69 
70 // TODO(bsamwel): Add support for movable-only types.
71 
72 // Test fixture for typed tests on BaseCountedInstance derived classes, see
73 // test_instance_tracker.h.
74 template <typename T>
75 class InstanceTest : public ::testing::Test {};
76 TYPED_TEST_SUITE_P(InstanceTest);
77 
78 // A simple reference counted class to make sure that the proper elements are
79 // destroyed in the erase(begin, end) test.
80 class RefCounted {
81  public:
RefCounted(int value,int * count)82   RefCounted(int value, int* count) : value_(value), count_(count) { Ref(); }
83 
RefCounted(const RefCounted & v)84   RefCounted(const RefCounted& v) : value_(v.value_), count_(v.count_) {
85     Ref();
86   }
87 
~RefCounted()88   ~RefCounted() {
89     Unref();
90     count_ = nullptr;
91   }
92 
swap(RefCounted & a,RefCounted & b)93   friend void swap(RefCounted& a, RefCounted& b) {
94     using std::swap;
95     swap(a.value_, b.value_);
96     swap(a.count_, b.count_);
97   }
98 
operator =(RefCounted v)99   RefCounted& operator=(RefCounted v) {
100     using std::swap;
101     swap(*this, v);
102     return *this;
103   }
104 
Ref() const105   void Ref() const {
106     ABSL_RAW_CHECK(count_ != nullptr, "");
107     ++(*count_);
108   }
109 
Unref() const110   void Unref() const {
111     --(*count_);
112     ABSL_RAW_CHECK(*count_ >= 0, "");
113   }
114 
115   int value_;
116   int* count_;
117 };
118 
119 using RefCountedVec = absl::InlinedVector<RefCounted, 8>;
120 
121 // A class with a vtable pointer
122 class Dynamic {
123  public:
~Dynamic()124   virtual ~Dynamic() {}
125 };
126 
127 using DynamicVec = absl::InlinedVector<Dynamic, 8>;
128 
129 // Append 0..len-1 to *v
130 template <typename Container>
Fill(Container * v,size_t len,int offset=0)131 static void Fill(Container* v, size_t len, int offset = 0) {
132   for (size_t i = 0; i < len; i++) {
133     v->push_back(static_cast<int>(i) + offset);
134   }
135 }
136 
Fill(size_t len,int offset=0)137 static IntVec Fill(size_t len, int offset = 0) {
138   IntVec v;
139   Fill(&v, len, offset);
140   return v;
141 }
142 
TEST(IntVec,SimpleOps)143 TEST(IntVec, SimpleOps) {
144   for (size_t len = 0; len < 20; len++) {
145     IntVec v;
146     const IntVec& cv = v;  // const alias
147 
148     Fill(&v, len);
149     EXPECT_EQ(len, v.size());
150     EXPECT_LE(len, v.capacity());
151 
152     for (size_t i = 0; i < len; i++) {
153       EXPECT_EQ(static_cast<int>(i), v[i]);
154       EXPECT_EQ(static_cast<int>(i), v.at(i));
155     }
156     EXPECT_EQ(v.begin(), v.data());
157     EXPECT_EQ(cv.begin(), cv.data());
158 
159     size_t counter = 0;
160     for (IntVec::iterator iter = v.begin(); iter != v.end(); ++iter) {
161       EXPECT_EQ(static_cast<int>(counter), *iter);
162       counter++;
163     }
164     EXPECT_EQ(counter, len);
165 
166     counter = 0;
167     for (IntVec::const_iterator iter = v.begin(); iter != v.end(); ++iter) {
168       EXPECT_EQ(static_cast<int>(counter), *iter);
169       counter++;
170     }
171     EXPECT_EQ(counter, len);
172 
173     counter = 0;
174     for (IntVec::const_iterator iter = v.cbegin(); iter != v.cend(); ++iter) {
175       EXPECT_EQ(static_cast<int>(counter), *iter);
176       counter++;
177     }
178     EXPECT_EQ(counter, len);
179 
180     if (len > 0) {
181       EXPECT_EQ(0, v.front());
182       EXPECT_EQ(static_cast<int>(len - 1), v.back());
183       v.pop_back();
184       EXPECT_EQ(len - 1, v.size());
185       for (size_t i = 0; i < v.size(); ++i) {
186         EXPECT_EQ(static_cast<int>(i), v[i]);
187         EXPECT_EQ(static_cast<int>(i), v.at(i));
188       }
189     }
190   }
191 }
192 
TEST(IntVec,PopBackNoOverflow)193 TEST(IntVec, PopBackNoOverflow) {
194   IntVec v = {1};
195   v.pop_back();
196   EXPECT_EQ(v.size(), 0u);
197 }
198 
TEST(IntVec,AtThrows)199 TEST(IntVec, AtThrows) {
200   IntVec v = {1, 2, 3};
201   EXPECT_EQ(v.at(2), 3);
202   ABSL_BASE_INTERNAL_EXPECT_FAIL(v.at(3), std::out_of_range,
203                                  "failed bounds check");
204 }
205 
TEST(IntVec,ReverseIterator)206 TEST(IntVec, ReverseIterator) {
207   for (size_t len = 0; len < 20; len++) {
208     IntVec v;
209     Fill(&v, len);
210 
211     size_t counter = len;
212     for (IntVec::reverse_iterator iter = v.rbegin(); iter != v.rend(); ++iter) {
213       counter--;
214       EXPECT_EQ(static_cast<int>(counter), *iter);
215     }
216     EXPECT_EQ(counter, 0u);
217 
218     counter = len;
219     for (IntVec::const_reverse_iterator iter = v.rbegin(); iter != v.rend();
220          ++iter) {
221       counter--;
222       EXPECT_EQ(static_cast<int>(counter), *iter);
223     }
224     EXPECT_EQ(counter, 0u);
225 
226     counter = len;
227     for (IntVec::const_reverse_iterator iter = v.crbegin(); iter != v.crend();
228          ++iter) {
229       counter--;
230       EXPECT_EQ(static_cast<int>(counter), *iter);
231     }
232     EXPECT_EQ(counter, 0u);
233   }
234 }
235 
TEST(IntVec,Erase)236 TEST(IntVec, Erase) {
237   for (size_t len = 1; len < 20; len++) {
238     for (size_t i = 0; i < len; ++i) {
239       IntVec v;
240       Fill(&v, len);
241       v.erase(v.begin() + i);
242       EXPECT_EQ(len - 1, v.size());
243       for (size_t j = 0; j < i; ++j) {
244         EXPECT_EQ(static_cast<int>(j), v[j]);
245       }
246       for (size_t j = i; j < len - 1; ++j) {
247         EXPECT_EQ(static_cast<int>(j + 1), v[j]);
248       }
249     }
250   }
251 }
252 
TEST(IntVec,Hardened)253 TEST(IntVec, Hardened) {
254   IntVec v;
255   Fill(&v, 10);
256   EXPECT_EQ(v[9], 9);
257 #if !defined(NDEBUG) || ABSL_OPTION_HARDENED
258   EXPECT_DEATH_IF_SUPPORTED(v[10], "");
259   EXPECT_DEATH_IF_SUPPORTED(v[static_cast<size_t>(-1)], "");
260   EXPECT_DEATH_IF_SUPPORTED(v.resize(v.max_size() + 1), "");
261 #endif
262 }
263 
264 // Move construction of a container of unique pointers should work fine, with no
265 // leaks, despite the fact that unique pointers are trivially relocatable but
266 // not trivially destructible.
TEST(UniquePtr,MoveConstruct)267 TEST(UniquePtr, MoveConstruct) {
268   for (size_t size = 0; size < 16; ++size) {
269     SCOPED_TRACE(size);
270 
271     absl::InlinedVector<std::unique_ptr<size_t>, 2> a;
272     for (size_t i = 0; i < size; ++i) {
273       a.push_back(std::make_unique<size_t>(i));
274     }
275 
276     absl::InlinedVector<std::unique_ptr<size_t>, 2> b(std::move(a));
277 
278     ASSERT_THAT(b, SizeIs(size));
279     for (size_t i = 0; i < size; ++i) {
280       ASSERT_THAT(b[i], Pointee(i));
281     }
282   }
283 }
284 
285 // Move assignment of a container of unique pointers should work fine, with no
286 // leaks, despite the fact that unique pointers are trivially relocatable but
287 // not trivially destructible.
TEST(UniquePtr,MoveAssign)288 TEST(UniquePtr, MoveAssign) {
289   for (size_t size = 0; size < 16; ++size) {
290     SCOPED_TRACE(size);
291 
292     absl::InlinedVector<std::unique_ptr<size_t>, 2> a;
293     for (size_t i = 0; i < size; ++i) {
294       a.push_back(std::make_unique<size_t>(i));
295     }
296 
297     absl::InlinedVector<std::unique_ptr<size_t>, 2> b;
298     b = std::move(a);
299 
300     ASSERT_THAT(b, SizeIs(size));
301     for (size_t i = 0; i < size; ++i) {
302       ASSERT_THAT(b[i], Pointee(i));
303     }
304   }
305 }
306 
307 // At the end of this test loop, the elements between [erase_begin, erase_end)
308 // should have reference counts == 0, and all others elements should have
309 // reference counts == 1.
TEST(RefCountedVec,EraseBeginEnd)310 TEST(RefCountedVec, EraseBeginEnd) {
311   for (size_t len = 1; len < 20; ++len) {
312     for (size_t erase_begin = 0; erase_begin < len; ++erase_begin) {
313       for (size_t erase_end = erase_begin; erase_end <= len; ++erase_end) {
314         std::vector<int> counts(len, 0);
315         RefCountedVec v;
316         for (size_t i = 0; i < len; ++i) {
317           v.push_back(RefCounted(static_cast<int>(i), &counts[i]));
318         }
319 
320         size_t erase_len = erase_end - erase_begin;
321 
322         v.erase(v.begin() + erase_begin, v.begin() + erase_end);
323 
324         EXPECT_EQ(len - erase_len, v.size());
325 
326         // Check the elements before the first element erased.
327         for (size_t i = 0; i < erase_begin; ++i) {
328           EXPECT_EQ(static_cast<int>(i), v[i].value_);
329         }
330 
331         // Check the elements after the first element erased.
332         for (size_t i = erase_begin; i < v.size(); ++i) {
333           EXPECT_EQ(static_cast<int>(i + erase_len), v[i].value_);
334         }
335 
336         // Check that the elements at the beginning are preserved.
337         for (size_t i = 0; i < erase_begin; ++i) {
338           EXPECT_EQ(1, counts[i]);
339         }
340 
341         // Check that the erased elements are destroyed
342         for (size_t i = erase_begin; i < erase_end; ++i) {
343           EXPECT_EQ(0, counts[i]);
344         }
345 
346         // Check that the elements at the end are preserved.
347         for (size_t i = erase_end; i < len; ++i) {
348           EXPECT_EQ(1, counts[i]);
349         }
350       }
351     }
352   }
353 }
354 
355 struct NoDefaultCtor {
NoDefaultCtor__anoned34ff230111::NoDefaultCtor356   explicit NoDefaultCtor(int) {}
357 };
358 struct NoCopy {
NoCopy__anoned34ff230111::NoCopy359   NoCopy() {}
360   NoCopy(const NoCopy&) = delete;
361 };
362 struct NoAssign {
NoAssign__anoned34ff230111::NoAssign363   NoAssign() {}
364   NoAssign& operator=(const NoAssign&) = delete;
365 };
366 struct MoveOnly {
MoveOnly__anoned34ff230111::MoveOnly367   MoveOnly() {}
368   MoveOnly(MoveOnly&&) = default;
369   MoveOnly& operator=(MoveOnly&&) = default;
370 };
TEST(InlinedVectorTest,NoDefaultCtor)371 TEST(InlinedVectorTest, NoDefaultCtor) {
372   absl::InlinedVector<NoDefaultCtor, 1> v(10, NoDefaultCtor(2));
373   (void)v;
374 }
TEST(InlinedVectorTest,NoCopy)375 TEST(InlinedVectorTest, NoCopy) {
376   absl::InlinedVector<NoCopy, 1> v(10);
377   (void)v;
378 }
TEST(InlinedVectorTest,NoAssign)379 TEST(InlinedVectorTest, NoAssign) {
380   absl::InlinedVector<NoAssign, 1> v(10);
381   (void)v;
382 }
TEST(InlinedVectorTest,MoveOnly)383 TEST(InlinedVectorTest, MoveOnly) {
384   absl::InlinedVector<MoveOnly, 2> v;
385   v.push_back(MoveOnly{});
386   v.push_back(MoveOnly{});
387   v.push_back(MoveOnly{});
388   v.erase(v.begin());
389   v.push_back(MoveOnly{});
390   v.erase(v.begin(), v.begin() + 1);
391   v.insert(v.begin(), MoveOnly{});
392   v.emplace(v.begin());
393   v.emplace(v.begin(), MoveOnly{});
394 }
TEST(InlinedVectorTest,Noexcept)395 TEST(InlinedVectorTest, Noexcept) {
396   EXPECT_TRUE(std::is_nothrow_move_constructible<IntVec>::value);
397   EXPECT_TRUE((std::is_nothrow_move_constructible<
398                absl::InlinedVector<MoveOnly, 2>>::value));
399 
400   struct MoveCanThrow {
401     MoveCanThrow(MoveCanThrow&&) {}
402   };
403   EXPECT_EQ(absl::default_allocator_is_nothrow::value,
404             (std::is_nothrow_move_constructible<
405                 absl::InlinedVector<MoveCanThrow, 2>>::value));
406 }
407 
TEST(InlinedVectorTest,EmplaceBack)408 TEST(InlinedVectorTest, EmplaceBack) {
409   absl::InlinedVector<std::pair<std::string, int>, 1> v;
410 
411   auto& inlined_element = v.emplace_back("answer", 42);
412   EXPECT_EQ(&inlined_element, &v[0]);
413   EXPECT_EQ(inlined_element.first, "answer");
414   EXPECT_EQ(inlined_element.second, 42);
415 
416   auto& allocated_element = v.emplace_back("taxicab", 1729);
417   EXPECT_EQ(&allocated_element, &v[1]);
418   EXPECT_EQ(allocated_element.first, "taxicab");
419   EXPECT_EQ(allocated_element.second, 1729);
420 }
421 
TEST(InlinedVectorTest,ShrinkToFitGrowingVector)422 TEST(InlinedVectorTest, ShrinkToFitGrowingVector) {
423   absl::InlinedVector<std::pair<std::string, int>, 1> v;
424 
425   v.shrink_to_fit();
426   EXPECT_EQ(v.capacity(), 1u);
427 
428   v.emplace_back("answer", 42);
429   v.shrink_to_fit();
430   EXPECT_EQ(v.capacity(), 1u);
431 
432   v.emplace_back("taxicab", 1729);
433   EXPECT_GE(v.capacity(), 2u);
434   v.shrink_to_fit();
435   EXPECT_EQ(v.capacity(), 2u);
436 
437   v.reserve(100);
438   EXPECT_GE(v.capacity(), 100u);
439   v.shrink_to_fit();
440   EXPECT_EQ(v.capacity(), 2u);
441 }
442 
TEST(InlinedVectorTest,ShrinkToFitEdgeCases)443 TEST(InlinedVectorTest, ShrinkToFitEdgeCases) {
444   {
445     absl::InlinedVector<std::pair<std::string, int>, 1> v;
446     v.emplace_back("answer", 42);
447     v.emplace_back("taxicab", 1729);
448     EXPECT_GE(v.capacity(), 2u);
449     v.pop_back();
450     v.shrink_to_fit();
451     EXPECT_EQ(v.capacity(), 1u);
452     EXPECT_EQ(v[0].first, "answer");
453     EXPECT_EQ(v[0].second, 42);
454   }
455 
456   {
457     absl::InlinedVector<std::string, 2> v(100);
458     v.resize(0);
459     v.shrink_to_fit();
460     EXPECT_EQ(v.capacity(), 2u);  // inlined capacity
461   }
462 
463   {
464     absl::InlinedVector<std::string, 2> v(100);
465     v.resize(1);
466     v.shrink_to_fit();
467     EXPECT_EQ(v.capacity(), 2u);  // inlined capacity
468   }
469 
470   {
471     absl::InlinedVector<std::string, 2> v(100);
472     v.resize(2);
473     v.shrink_to_fit();
474     EXPECT_EQ(v.capacity(), 2u);
475   }
476 
477   {
478     absl::InlinedVector<std::string, 2> v(100);
479     v.resize(3);
480     v.shrink_to_fit();
481     EXPECT_EQ(v.capacity(), 3u);
482   }
483 }
484 
TEST(IntVec,Insert)485 TEST(IntVec, Insert) {
486   for (size_t len = 0; len < 20; len++) {
487     for (ptrdiff_t pos = 0; pos <= static_cast<ptrdiff_t>(len); pos++) {
488       {
489         // Single element
490         std::vector<int> std_v;
491         Fill(&std_v, len);
492         IntVec v;
493         Fill(&v, len);
494 
495         std_v.insert(std_v.begin() + pos, 9999);
496         IntVec::iterator it = v.insert(v.cbegin() + pos, 9999);
497         EXPECT_THAT(v, ElementsAreArray(std_v));
498         EXPECT_EQ(it, v.cbegin() + pos);
499       }
500       {
501         // n elements
502         std::vector<int> std_v;
503         Fill(&std_v, len);
504         IntVec v;
505         Fill(&v, len);
506 
507         IntVec::size_type n = 5;
508         std_v.insert(std_v.begin() + pos, n, 9999);
509         IntVec::iterator it = v.insert(v.cbegin() + pos, n, 9999);
510         EXPECT_THAT(v, ElementsAreArray(std_v));
511         EXPECT_EQ(it, v.cbegin() + pos);
512       }
513       {
514         // Iterator range (random access iterator)
515         std::vector<int> std_v;
516         Fill(&std_v, len);
517         IntVec v;
518         Fill(&v, len);
519 
520         const std::vector<int> input = {9999, 8888, 7777};
521         std_v.insert(std_v.begin() + pos, input.cbegin(), input.cend());
522         IntVec::iterator it =
523             v.insert(v.cbegin() + pos, input.cbegin(), input.cend());
524         EXPECT_THAT(v, ElementsAreArray(std_v));
525         EXPECT_EQ(it, v.cbegin() + pos);
526       }
527       {
528         // Iterator range (forward iterator)
529         std::vector<int> std_v;
530         Fill(&std_v, len);
531         IntVec v;
532         Fill(&v, len);
533 
534         const std::forward_list<int> input = {9999, 8888, 7777};
535         std_v.insert(std_v.begin() + pos, input.cbegin(), input.cend());
536         IntVec::iterator it =
537             v.insert(v.cbegin() + pos, input.cbegin(), input.cend());
538         EXPECT_THAT(v, ElementsAreArray(std_v));
539         EXPECT_EQ(it, v.cbegin() + pos);
540       }
541       {
542         // Iterator range (input iterator)
543         std::vector<int> std_v;
544         Fill(&std_v, len);
545         IntVec v;
546         Fill(&v, len);
547 
548         std_v.insert(std_v.begin() + pos, {9999, 8888, 7777});
549         std::istringstream input("9999 8888 7777");
550         IntVec::iterator it =
551             v.insert(v.cbegin() + pos, std::istream_iterator<int>(input),
552                      std::istream_iterator<int>());
553         EXPECT_THAT(v, ElementsAreArray(std_v));
554         EXPECT_EQ(it, v.cbegin() + pos);
555       }
556       {
557         // Initializer list
558         std::vector<int> std_v;
559         Fill(&std_v, len);
560         IntVec v;
561         Fill(&v, len);
562 
563         std_v.insert(std_v.begin() + pos, {9999, 8888});
564         IntVec::iterator it = v.insert(v.cbegin() + pos, {9999, 8888});
565         EXPECT_THAT(v, ElementsAreArray(std_v));
566         EXPECT_EQ(it, v.cbegin() + pos);
567       }
568     }
569   }
570 }
571 
TEST(RefCountedVec,InsertConstructorDestructor)572 TEST(RefCountedVec, InsertConstructorDestructor) {
573   // Make sure the proper construction/destruction happen during insert
574   // operations.
575   for (size_t len = 0; len < 20; len++) {
576     SCOPED_TRACE(len);
577     for (size_t pos = 0; pos <= len; pos++) {
578       SCOPED_TRACE(pos);
579       std::vector<int> counts(len, 0);
580       int inserted_count = 0;
581       RefCountedVec v;
582       for (size_t i = 0; i < len; ++i) {
583         SCOPED_TRACE(i);
584         v.push_back(RefCounted(static_cast<int>(i), &counts[i]));
585       }
586 
587       EXPECT_THAT(counts, Each(Eq(1)));
588 
589       RefCounted insert_element(9999, &inserted_count);
590       EXPECT_EQ(1, inserted_count);
591       v.insert(v.begin() + pos, insert_element);
592       EXPECT_EQ(2, inserted_count);
593       // Check that the elements at the end are preserved.
594       EXPECT_THAT(counts, Each(Eq(1)));
595       EXPECT_EQ(2, inserted_count);
596     }
597   }
598 }
599 
TEST(IntVec,Resize)600 TEST(IntVec, Resize) {
601   for (size_t len = 0; len < 20; len++) {
602     IntVec v;
603     Fill(&v, len);
604 
605     // Try resizing up and down by k elements
606     static const int kResizeElem = 1000000;
607     for (size_t k = 0; k < 10; k++) {
608       // Enlarging resize
609       v.resize(len + k, kResizeElem);
610       EXPECT_EQ(len + k, v.size());
611       EXPECT_LE(len + k, v.capacity());
612       for (size_t i = 0; i < len + k; i++) {
613         if (i < len) {
614           EXPECT_EQ(static_cast<int>(i), v[i]);
615         } else {
616           EXPECT_EQ(kResizeElem, v[i]);
617         }
618       }
619 
620       // Shrinking resize
621       v.resize(len, kResizeElem);
622       EXPECT_EQ(len, v.size());
623       EXPECT_LE(len, v.capacity());
624       for (size_t i = 0; i < len; i++) {
625         EXPECT_EQ(static_cast<int>(i), v[i]);
626       }
627     }
628   }
629 }
630 
TEST(IntVec,InitWithLength)631 TEST(IntVec, InitWithLength) {
632   for (size_t len = 0; len < 20; len++) {
633     IntVec v(len, 7);
634     EXPECT_EQ(len, v.size());
635     EXPECT_LE(len, v.capacity());
636     for (size_t i = 0; i < len; i++) {
637       EXPECT_EQ(7, v[i]);
638     }
639   }
640 }
641 
TEST(IntVec,CopyConstructorAndAssignment)642 TEST(IntVec, CopyConstructorAndAssignment) {
643   for (size_t len = 0; len < 20; len++) {
644     IntVec v;
645     Fill(&v, len);
646     EXPECT_EQ(len, v.size());
647     EXPECT_LE(len, v.capacity());
648 
649     IntVec v2(v);
650     EXPECT_TRUE(v == v2) << PrintToString(v) << PrintToString(v2);
651 
652     for (size_t start_len = 0; start_len < 20; start_len++) {
653       IntVec v3;
654       Fill(&v3, start_len, 99);  // Add dummy elements that should go away
655       v3 = v;
656       EXPECT_TRUE(v == v3) << PrintToString(v) << PrintToString(v3);
657     }
658   }
659 }
660 
TEST(IntVec,AliasingCopyAssignment)661 TEST(IntVec, AliasingCopyAssignment) {
662   for (size_t len = 0; len < 20; ++len) {
663     IntVec original;
664     Fill(&original, len);
665     IntVec dup = original;
666     dup = *&dup;
667     EXPECT_EQ(dup, original);
668   }
669 }
670 
TEST(IntVec,MoveConstructorAndAssignment)671 TEST(IntVec, MoveConstructorAndAssignment) {
672   for (size_t len = 0; len < 20; len++) {
673     IntVec v_in;
674     const size_t inlined_capacity = v_in.capacity();
675     Fill(&v_in, len);
676     EXPECT_EQ(len, v_in.size());
677     EXPECT_LE(len, v_in.capacity());
678 
679     {
680       IntVec v_temp(v_in);
681       auto* old_data = v_temp.data();
682       IntVec v_out(std::move(v_temp));
683       EXPECT_TRUE(v_in == v_out) << PrintToString(v_in) << PrintToString(v_out);
684       if (v_in.size() > inlined_capacity) {
685         // Allocation is moved as a whole, data stays in place.
686         EXPECT_TRUE(v_out.data() == old_data);
687       } else {
688         EXPECT_FALSE(v_out.data() == old_data);
689       }
690     }
691     for (size_t start_len = 0; start_len < 20; start_len++) {
692       IntVec v_out;
693       Fill(&v_out, start_len, 99);  // Add dummy elements that should go away
694       IntVec v_temp(v_in);
695       auto* old_data = v_temp.data();
696       v_out = std::move(v_temp);
697       EXPECT_TRUE(v_in == v_out) << PrintToString(v_in) << PrintToString(v_out);
698       if (v_in.size() > inlined_capacity) {
699         // Allocation is moved as a whole, data stays in place.
700         EXPECT_TRUE(v_out.data() == old_data);
701       } else {
702         EXPECT_FALSE(v_out.data() == old_data);
703       }
704     }
705   }
706 }
707 
708 class NotTriviallyDestructible {
709  public:
NotTriviallyDestructible()710   NotTriviallyDestructible() : p_(new int(1)) {}
NotTriviallyDestructible(int i)711   explicit NotTriviallyDestructible(int i) : p_(new int(i)) {}
712 
NotTriviallyDestructible(const NotTriviallyDestructible & other)713   NotTriviallyDestructible(const NotTriviallyDestructible& other)
714       : p_(new int(*other.p_)) {}
715 
operator =(const NotTriviallyDestructible & other)716   NotTriviallyDestructible& operator=(const NotTriviallyDestructible& other) {
717     p_ = absl::make_unique<int>(*other.p_);
718     return *this;
719   }
720 
operator ==(const NotTriviallyDestructible & other) const721   bool operator==(const NotTriviallyDestructible& other) const {
722     return *p_ == *other.p_;
723   }
724 
725  private:
726   std::unique_ptr<int> p_;
727 };
728 
TEST(AliasingTest,Emplace)729 TEST(AliasingTest, Emplace) {
730   for (size_t i = 2; i < 20; ++i) {
731     absl::InlinedVector<NotTriviallyDestructible, 10> vec;
732     for (size_t j = 0; j < i; ++j) {
733       vec.push_back(NotTriviallyDestructible(static_cast<int>(j)));
734     }
735     vec.emplace(vec.begin(), vec[0]);
736     EXPECT_EQ(vec[0], vec[1]);
737     vec.emplace(vec.begin() + i / 2, vec[i / 2]);
738     EXPECT_EQ(vec[i / 2], vec[i / 2 + 1]);
739     vec.emplace(vec.end() - 1, vec.back());
740     EXPECT_EQ(vec[vec.size() - 2], vec.back());
741   }
742 }
743 
TEST(AliasingTest,InsertWithCount)744 TEST(AliasingTest, InsertWithCount) {
745   for (size_t i = 1; i < 20; ++i) {
746     absl::InlinedVector<NotTriviallyDestructible, 10> vec;
747     for (size_t j = 0; j < i; ++j) {
748       vec.push_back(NotTriviallyDestructible(static_cast<int>(j)));
749     }
750     for (size_t n = 0; n < 5; ++n) {
751       // We use back where we can because it's guaranteed to become invalidated
752       vec.insert(vec.begin(), n, vec.back());
753       auto b = vec.begin();
754       EXPECT_TRUE(
755           std::all_of(b, b + n, [&vec](const NotTriviallyDestructible& x) {
756             return x == vec.back();
757           }));
758 
759       auto m_idx = vec.size() / 2;
760       vec.insert(vec.begin() + m_idx, n, vec.back());
761       auto m = vec.begin() + m_idx;
762       EXPECT_TRUE(
763           std::all_of(m, m + n, [&vec](const NotTriviallyDestructible& x) {
764             return x == vec.back();
765           }));
766 
767       // We want distinct values so the equality test is meaningful,
768       // vec[vec.size() - 1] is also almost always invalidated.
769       auto old_e = vec.size() - 1;
770       auto val = vec[old_e];
771       vec.insert(vec.end(), n, vec[old_e]);
772       auto e = vec.begin() + old_e;
773       EXPECT_TRUE(std::all_of(
774           e, e + n,
775           [&val](const NotTriviallyDestructible& x) { return x == val; }));
776     }
777   }
778 }
779 
TEST(OverheadTest,Storage)780 TEST(OverheadTest, Storage) {
781   // Check for size overhead.
782   // In particular, ensure that std::allocator doesn't cost anything to store.
783   // The union should be absorbing some of the allocation bookkeeping overhead
784   // in the larger vectors, leaving only the size_ field as overhead.
785 
786   struct T { void* val; };
787   size_t expected_overhead = sizeof(T);
788 
789   EXPECT_EQ((2 * expected_overhead),
790             sizeof(absl::InlinedVector<T, 1>) - sizeof(T[1]));
791   EXPECT_EQ(expected_overhead,
792             sizeof(absl::InlinedVector<T, 2>) - sizeof(T[2]));
793   EXPECT_EQ(expected_overhead,
794             sizeof(absl::InlinedVector<T, 3>) - sizeof(T[3]));
795   EXPECT_EQ(expected_overhead,
796             sizeof(absl::InlinedVector<T, 4>) - sizeof(T[4]));
797   EXPECT_EQ(expected_overhead,
798             sizeof(absl::InlinedVector<T, 5>) - sizeof(T[5]));
799   EXPECT_EQ(expected_overhead,
800             sizeof(absl::InlinedVector<T, 6>) - sizeof(T[6]));
801   EXPECT_EQ(expected_overhead,
802             sizeof(absl::InlinedVector<T, 7>) - sizeof(T[7]));
803   EXPECT_EQ(expected_overhead,
804             sizeof(absl::InlinedVector<T, 8>) - sizeof(T[8]));
805 }
806 
TEST(IntVec,Clear)807 TEST(IntVec, Clear) {
808   for (size_t len = 0; len < 20; len++) {
809     SCOPED_TRACE(len);
810     IntVec v;
811     Fill(&v, len);
812     v.clear();
813     EXPECT_EQ(0u, v.size());
814     EXPECT_EQ(v.begin(), v.end());
815   }
816 }
817 
TEST(IntVec,Reserve)818 TEST(IntVec, Reserve) {
819   for (size_t len = 0; len < 20; len++) {
820     IntVec v;
821     Fill(&v, len);
822 
823     for (size_t newlen = 0; newlen < 100; newlen++) {
824       const int* start_rep = v.data();
825       v.reserve(newlen);
826       const int* final_rep = v.data();
827       if (newlen <= len) {
828         EXPECT_EQ(start_rep, final_rep);
829       }
830       EXPECT_LE(newlen, v.capacity());
831 
832       // Filling up to newlen should not change rep
833       while (v.size() < newlen) {
834         v.push_back(0);
835       }
836       EXPECT_EQ(final_rep, v.data());
837     }
838   }
839 }
840 
TEST(StringVec,SelfRefPushBack)841 TEST(StringVec, SelfRefPushBack) {
842   std::vector<std::string> std_v;
843   absl::InlinedVector<std::string, 4> v;
844   const std::string s = "A quite long string to ensure heap.";
845   std_v.push_back(s);
846   v.push_back(s);
847   for (int i = 0; i < 20; ++i) {
848     EXPECT_THAT(v, ElementsAreArray(std_v));
849 
850     v.push_back(v.back());
851     std_v.push_back(std_v.back());
852   }
853   EXPECT_THAT(v, ElementsAreArray(std_v));
854 }
855 
TEST(StringVec,SelfRefPushBackWithMove)856 TEST(StringVec, SelfRefPushBackWithMove) {
857   std::vector<std::string> std_v;
858   absl::InlinedVector<std::string, 4> v;
859   const std::string s = "A quite long string to ensure heap.";
860   std_v.push_back(s);
861   v.push_back(s);
862   for (int i = 0; i < 20; ++i) {
863     EXPECT_EQ(v.back(), std_v.back());
864 
865     v.push_back(std::move(v.back()));
866     std_v.push_back(std::move(std_v.back()));
867   }
868   EXPECT_EQ(v.back(), std_v.back());
869 }
870 
TEST(StringVec,SelfMove)871 TEST(StringVec, SelfMove) {
872   const std::string s = "A quite long string to ensure heap.";
873   for (int len = 0; len < 20; len++) {
874     SCOPED_TRACE(len);
875     absl::InlinedVector<std::string, 8> v;
876     for (int i = 0; i < len; ++i) {
877       SCOPED_TRACE(i);
878       v.push_back(s);
879     }
880     // Indirection necessary to avoid compiler warning.
881     v = std::move(*(&v));
882     // Ensure that the inlined vector is still in a valid state by copying it.
883     // We don't expect specific contents since a self-move results in an
884     // unspecified valid state.
885     std::vector<std::string> copy(v.begin(), v.end());
886   }
887 }
888 
TEST(IntVec,Swap)889 TEST(IntVec, Swap) {
890   for (size_t l1 = 0; l1 < 20; l1++) {
891     SCOPED_TRACE(l1);
892     for (size_t l2 = 0; l2 < 20; l2++) {
893       SCOPED_TRACE(l2);
894       IntVec a = Fill(l1, 0);
895       IntVec b = Fill(l2, 100);
896       {
897         using std::swap;
898         swap(a, b);
899       }
900       EXPECT_EQ(l1, b.size());
901       EXPECT_EQ(l2, a.size());
902       for (size_t i = 0; i < l1; i++) {
903         SCOPED_TRACE(i);
904         EXPECT_EQ(static_cast<int>(i), b[i]);
905       }
906       for (size_t i = 0; i < l2; i++) {
907         SCOPED_TRACE(i);
908         EXPECT_EQ(100 + static_cast<int>(i), a[i]);
909       }
910     }
911   }
912 }
913 
TYPED_TEST_P(InstanceTest,Swap)914 TYPED_TEST_P(InstanceTest, Swap) {
915   using Instance = TypeParam;
916   using InstanceVec = absl::InlinedVector<Instance, 8>;
917   for (size_t l1 = 0; l1 < 20; l1++) {
918     SCOPED_TRACE(l1);
919     for (size_t l2 = 0; l2 < 20; l2++) {
920       SCOPED_TRACE(l2);
921       InstanceTracker tracker;
922       InstanceVec a, b;
923       const size_t inlined_capacity = a.capacity();
924       auto min_len = std::min(l1, l2);
925       auto max_len = std::max(l1, l2);
926       for (size_t i = 0; i < l1; i++)
927         a.push_back(Instance(static_cast<int>(i)));
928       for (size_t i = 0; i < l2; i++)
929         b.push_back(Instance(100 + static_cast<int>(i)));
930       EXPECT_EQ(tracker.instances(), static_cast<int>(l1 + l2));
931       tracker.ResetCopiesMovesSwaps();
932       {
933         using std::swap;
934         swap(a, b);
935       }
936       EXPECT_EQ(tracker.instances(), static_cast<int>(l1 + l2));
937       if (a.size() > inlined_capacity && b.size() > inlined_capacity) {
938         EXPECT_EQ(tracker.swaps(), 0);  // Allocations are swapped.
939         EXPECT_EQ(tracker.moves(), 0);
940       } else if (a.size() <= inlined_capacity && b.size() <= inlined_capacity) {
941         EXPECT_EQ(tracker.swaps(), static_cast<int>(min_len));
942         EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
943                   static_cast<int>(max_len - min_len));
944       } else {
945         // One is allocated and the other isn't. The allocation is transferred
946         // without copying elements, and the inlined instances are copied/moved.
947         EXPECT_EQ(tracker.swaps(), 0);
948         EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
949                   static_cast<int>(min_len));
950       }
951 
952       EXPECT_EQ(l1, b.size());
953       EXPECT_EQ(l2, a.size());
954       for (size_t i = 0; i < l1; i++) {
955         EXPECT_EQ(static_cast<int>(i), b[i].value());
956       }
957       for (size_t i = 0; i < l2; i++) {
958         EXPECT_EQ(100 + static_cast<int>(i), a[i].value());
959       }
960     }
961   }
962 }
963 
TEST(IntVec,EqualAndNotEqual)964 TEST(IntVec, EqualAndNotEqual) {
965   IntVec a, b;
966   EXPECT_TRUE(a == b);
967   EXPECT_FALSE(a != b);
968 
969   a.push_back(3);
970   EXPECT_FALSE(a == b);
971   EXPECT_TRUE(a != b);
972 
973   b.push_back(3);
974   EXPECT_TRUE(a == b);
975   EXPECT_FALSE(a != b);
976 
977   b.push_back(7);
978   EXPECT_FALSE(a == b);
979   EXPECT_TRUE(a != b);
980 
981   a.push_back(6);
982   EXPECT_FALSE(a == b);
983   EXPECT_TRUE(a != b);
984 
985   a.clear();
986   b.clear();
987   for (size_t i = 0; i < 100; i++) {
988     a.push_back(static_cast<int>(i));
989     b.push_back(static_cast<int>(i));
990     EXPECT_TRUE(a == b);
991     EXPECT_FALSE(a != b);
992 
993     b[i] = b[i] + 1;
994     EXPECT_FALSE(a == b);
995     EXPECT_TRUE(a != b);
996 
997     b[i] = b[i] - 1;  // Back to before
998     EXPECT_TRUE(a == b);
999     EXPECT_FALSE(a != b);
1000   }
1001 }
1002 
TEST(IntVec,RelationalOps)1003 TEST(IntVec, RelationalOps) {
1004   IntVec a, b;
1005   EXPECT_FALSE(a < b);
1006   EXPECT_FALSE(b < a);
1007   EXPECT_FALSE(a > b);
1008   EXPECT_FALSE(b > a);
1009   EXPECT_TRUE(a <= b);
1010   EXPECT_TRUE(b <= a);
1011   EXPECT_TRUE(a >= b);
1012   EXPECT_TRUE(b >= a);
1013   b.push_back(3);
1014   EXPECT_TRUE(a < b);
1015   EXPECT_FALSE(b < a);
1016   EXPECT_FALSE(a > b);
1017   EXPECT_TRUE(b > a);
1018   EXPECT_TRUE(a <= b);
1019   EXPECT_FALSE(b <= a);
1020   EXPECT_FALSE(a >= b);
1021   EXPECT_TRUE(b >= a);
1022 }
1023 
TYPED_TEST_P(InstanceTest,CountConstructorsDestructors)1024 TYPED_TEST_P(InstanceTest, CountConstructorsDestructors) {
1025   using Instance = TypeParam;
1026   using InstanceVec = absl::InlinedVector<Instance, 8>;
1027   InstanceTracker tracker;
1028   for (size_t len = 0; len < 20; len++) {
1029     SCOPED_TRACE(len);
1030     tracker.ResetCopiesMovesSwaps();
1031 
1032     InstanceVec v;
1033     const size_t inlined_capacity = v.capacity();
1034     for (size_t i = 0; i < len; i++) {
1035       v.push_back(Instance(static_cast<int>(i)));
1036     }
1037     EXPECT_EQ(tracker.instances(), static_cast<int>(len));
1038     EXPECT_GE(tracker.copies() + tracker.moves(),
1039               static_cast<int>(len));  // More due to reallocation.
1040     tracker.ResetCopiesMovesSwaps();
1041 
1042     // Enlarging resize() must construct some objects
1043     tracker.ResetCopiesMovesSwaps();
1044     v.resize(len + 10, Instance(100));
1045     EXPECT_EQ(tracker.instances(), static_cast<int>(len) + 10);
1046     if (len <= inlined_capacity && len + 10 > inlined_capacity) {
1047       EXPECT_EQ(tracker.copies() + tracker.moves(), 10 + static_cast<int>(len));
1048     } else {
1049       // Only specify a minimum number of copies + moves. We don't want to
1050       // depend on the reallocation policy here.
1051       EXPECT_GE(tracker.copies() + tracker.moves(),
1052                 10);  // More due to reallocation.
1053     }
1054 
1055     // Shrinking resize() must destroy some objects
1056     tracker.ResetCopiesMovesSwaps();
1057     v.resize(len, Instance(100));
1058     EXPECT_EQ(tracker.instances(), static_cast<int>(len));
1059     EXPECT_EQ(tracker.copies(), 0);
1060     EXPECT_EQ(tracker.moves(), 0);
1061 
1062     // reserve() must not increase the number of initialized objects
1063     SCOPED_TRACE("reserve");
1064     v.reserve(len + 1000);
1065     EXPECT_EQ(tracker.instances(), static_cast<int>(len));
1066     EXPECT_EQ(tracker.copies() + tracker.moves(), static_cast<int>(len));
1067 
1068     // pop_back() and erase() must destroy one object
1069     if (len > 0) {
1070       tracker.ResetCopiesMovesSwaps();
1071       v.pop_back();
1072       EXPECT_EQ(tracker.instances(), static_cast<int>(len) - 1);
1073       EXPECT_EQ(tracker.copies(), 0);
1074       EXPECT_EQ(tracker.moves(), 0);
1075 
1076       if (!v.empty()) {
1077         tracker.ResetCopiesMovesSwaps();
1078         v.erase(v.begin());
1079         EXPECT_EQ(tracker.instances(), static_cast<int>(len) - 2);
1080         EXPECT_EQ(tracker.copies() + tracker.moves(),
1081                   static_cast<int>(len) - 2);
1082       }
1083     }
1084 
1085     tracker.ResetCopiesMovesSwaps();
1086     int instances_before_empty_erase = tracker.instances();
1087     v.erase(v.begin(), v.begin());
1088     EXPECT_EQ(tracker.instances(), instances_before_empty_erase);
1089     EXPECT_EQ(tracker.copies() + tracker.moves(), 0);
1090   }
1091 }
1092 
TYPED_TEST_P(InstanceTest,CountConstructorsDestructorsOnCopyConstruction)1093 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnCopyConstruction) {
1094   using Instance = TypeParam;
1095   using InstanceVec = absl::InlinedVector<Instance, 8>;
1096   InstanceTracker tracker;
1097   for (int len = 0; len < 20; len++) {
1098     SCOPED_TRACE(len);
1099     tracker.ResetCopiesMovesSwaps();
1100 
1101     InstanceVec v;
1102     for (int i = 0; i < len; i++) {
1103       v.push_back(Instance(i));
1104     }
1105     EXPECT_EQ(tracker.instances(), len);
1106     EXPECT_GE(tracker.copies() + tracker.moves(),
1107               len);  // More due to reallocation.
1108     tracker.ResetCopiesMovesSwaps();
1109     {  // Copy constructor should create 'len' more instances.
1110       InstanceVec v_copy(v);
1111       EXPECT_EQ(tracker.instances(), len + len);
1112       EXPECT_EQ(tracker.copies(), len);
1113       EXPECT_EQ(tracker.moves(), 0);
1114     }
1115     EXPECT_EQ(tracker.instances(), len);
1116   }
1117 }
1118 
TYPED_TEST_P(InstanceTest,CountConstructorsDestructorsOnMoveConstruction)1119 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveConstruction) {
1120   using Instance = TypeParam;
1121   using InstanceVec = absl::InlinedVector<Instance, 8>;
1122   InstanceTracker tracker;
1123   for (int len = 0; len < 20; len++) {
1124     SCOPED_TRACE(len);
1125     tracker.ResetCopiesMovesSwaps();
1126 
1127     InstanceVec v;
1128     const size_t inlined_capacity = v.capacity();
1129     for (int i = 0; i < len; i++) {
1130       v.push_back(Instance(i));
1131     }
1132     EXPECT_EQ(tracker.instances(), len);
1133     EXPECT_GE(tracker.copies() + tracker.moves(),
1134               len);  // More due to reallocation.
1135     tracker.ResetCopiesMovesSwaps();
1136     {
1137       InstanceVec v_copy(std::move(v));
1138       if (static_cast<size_t>(len) > inlined_capacity) {
1139         // Allocation is moved as a whole.
1140         EXPECT_EQ(tracker.instances(), len);
1141         EXPECT_EQ(tracker.live_instances(), len);
1142         // Tests an implementation detail, don't rely on this in your code.
1143         EXPECT_EQ(v.size(), 0u);  // NOLINT misc-use-after-move
1144         EXPECT_EQ(tracker.copies(), 0);
1145         EXPECT_EQ(tracker.moves(), 0);
1146       } else {
1147         EXPECT_EQ(tracker.instances(), len + len);
1148         if (Instance::supports_move()) {
1149           EXPECT_EQ(tracker.live_instances(), len);
1150           EXPECT_EQ(tracker.copies(), 0);
1151           EXPECT_EQ(tracker.moves(), len);
1152         } else {
1153           EXPECT_EQ(tracker.live_instances(), len + len);
1154           EXPECT_EQ(tracker.copies(), len);
1155           EXPECT_EQ(tracker.moves(), 0);
1156         }
1157       }
1158       EXPECT_EQ(tracker.swaps(), 0);
1159     }
1160   }
1161 }
1162 
TYPED_TEST_P(InstanceTest,CountConstructorsDestructorsOnAssignment)1163 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnAssignment) {
1164   using Instance = TypeParam;
1165   using InstanceVec = absl::InlinedVector<Instance, 8>;
1166   InstanceTracker tracker;
1167   for (int len = 0; len < 20; len++) {
1168     SCOPED_TRACE(len);
1169     for (int longorshort = 0; longorshort <= 1; ++longorshort) {
1170       SCOPED_TRACE(longorshort);
1171       tracker.ResetCopiesMovesSwaps();
1172 
1173       InstanceVec longer, shorter;
1174       for (int i = 0; i < len; i++) {
1175         longer.push_back(Instance(i));
1176         shorter.push_back(Instance(i));
1177       }
1178       longer.push_back(Instance(len));
1179       EXPECT_EQ(tracker.instances(), len + len + 1);
1180       EXPECT_GE(tracker.copies() + tracker.moves(),
1181                 len + len + 1);  // More due to reallocation.
1182 
1183       tracker.ResetCopiesMovesSwaps();
1184       if (longorshort) {
1185         shorter = longer;
1186         EXPECT_EQ(tracker.instances(), (len + 1) + (len + 1));
1187         EXPECT_GE(tracker.copies() + tracker.moves(),
1188                   len + 1);  // More due to reallocation.
1189       } else {
1190         longer = shorter;
1191         EXPECT_EQ(tracker.instances(), len + len);
1192         EXPECT_EQ(tracker.copies() + tracker.moves(), len);
1193       }
1194     }
1195   }
1196 }
1197 
TYPED_TEST_P(InstanceTest,CountConstructorsDestructorsOnMoveAssignment)1198 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveAssignment) {
1199   using Instance = TypeParam;
1200   using InstanceVec = absl::InlinedVector<Instance, 8>;
1201   InstanceTracker tracker;
1202   for (int len = 0; len < 20; len++) {
1203     SCOPED_TRACE(len);
1204     for (int longorshort = 0; longorshort <= 1; ++longorshort) {
1205       SCOPED_TRACE(longorshort);
1206       tracker.ResetCopiesMovesSwaps();
1207 
1208       InstanceVec longer, shorter;
1209       const size_t inlined_capacity = longer.capacity();
1210       for (int i = 0; i < len; i++) {
1211         longer.push_back(Instance(i));
1212         shorter.push_back(Instance(i));
1213       }
1214       longer.push_back(Instance(len));
1215       EXPECT_EQ(tracker.instances(), len + len + 1);
1216       EXPECT_GE(tracker.copies() + tracker.moves(),
1217                 len + len + 1);  // More due to reallocation.
1218 
1219       tracker.ResetCopiesMovesSwaps();
1220       int src_len;
1221       if (longorshort) {
1222         src_len = len + 1;
1223         shorter = std::move(longer);
1224       } else {
1225         src_len = len;
1226         longer = std::move(shorter);
1227       }
1228       if (static_cast<size_t>(src_len) > inlined_capacity) {
1229         // Allocation moved as a whole.
1230         EXPECT_EQ(tracker.instances(), src_len);
1231         EXPECT_EQ(tracker.live_instances(), src_len);
1232         EXPECT_EQ(tracker.copies(), 0);
1233         EXPECT_EQ(tracker.moves(), 0);
1234       } else {
1235         // Elements are all copied.
1236         EXPECT_EQ(tracker.instances(), src_len + src_len);
1237         if (Instance::supports_move()) {
1238           EXPECT_EQ(tracker.copies(), 0);
1239           EXPECT_EQ(tracker.moves(), src_len);
1240           EXPECT_EQ(tracker.live_instances(), src_len);
1241         } else {
1242           EXPECT_EQ(tracker.copies(), src_len);
1243           EXPECT_EQ(tracker.moves(), 0);
1244           EXPECT_EQ(tracker.live_instances(), src_len + src_len);
1245         }
1246       }
1247       EXPECT_EQ(tracker.swaps(), 0);
1248     }
1249   }
1250 }
1251 
TEST(CountElemAssign,SimpleTypeWithInlineBacking)1252 TEST(CountElemAssign, SimpleTypeWithInlineBacking) {
1253   const size_t inlined_capacity = absl::InlinedVector<int, 2>().capacity();
1254 
1255   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1256     SCOPED_TRACE(original_size);
1257     // Original contents are [12345, 12345, ...]
1258     std::vector<int> original_contents(original_size, 12345);
1259 
1260     absl::InlinedVector<int, 2> v(original_contents.begin(),
1261                                   original_contents.end());
1262     v.assign(2, 123);
1263     EXPECT_THAT(v, AllOf(SizeIs(2u), ElementsAre(123, 123)));
1264     if (original_size <= inlined_capacity) {
1265       // If the original had inline backing, it should stay inline.
1266       EXPECT_EQ(v.capacity(), inlined_capacity);
1267     }
1268   }
1269 }
1270 
TEST(CountElemAssign,SimpleTypeWithAllocation)1271 TEST(CountElemAssign, SimpleTypeWithAllocation) {
1272   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1273     SCOPED_TRACE(original_size);
1274     // Original contents are [12345, 12345, ...]
1275     std::vector<int> original_contents(original_size, 12345);
1276 
1277     absl::InlinedVector<int, 2> v(original_contents.begin(),
1278                                   original_contents.end());
1279     v.assign(3, 123);
1280     EXPECT_THAT(v, AllOf(SizeIs(3u), ElementsAre(123, 123, 123)));
1281     EXPECT_LE(v.size(), v.capacity());
1282   }
1283 }
1284 
TYPED_TEST_P(InstanceTest,CountElemAssignInlineBacking)1285 TYPED_TEST_P(InstanceTest, CountElemAssignInlineBacking) {
1286   using Instance = TypeParam;
1287   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1288     SCOPED_TRACE(original_size);
1289     // Original contents are [12345, 12345, ...]
1290     std::vector<Instance> original_contents(original_size, Instance(12345));
1291 
1292     absl::InlinedVector<Instance, 2> v(original_contents.begin(),
1293                                        original_contents.end());
1294     v.assign(2, Instance(123));
1295     EXPECT_THAT(v, AllOf(SizeIs(2u), ElementsAre(ValueIs(123), ValueIs(123))));
1296     if (original_size <= 2) {
1297       // If the original had inline backing, it should stay inline.
1298       EXPECT_EQ(2u, v.capacity());
1299     }
1300   }
1301 }
1302 
1303 template <typename Instance>
InstanceCountElemAssignWithAllocationTest()1304 void InstanceCountElemAssignWithAllocationTest() {
1305   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1306     SCOPED_TRACE(original_size);
1307     // Original contents are [12345, 12345, ...]
1308     std::vector<Instance> original_contents(original_size, Instance(12345));
1309 
1310     absl::InlinedVector<Instance, 2> v(original_contents.begin(),
1311                                        original_contents.end());
1312     v.assign(3, Instance(123));
1313     EXPECT_THAT(v, AllOf(SizeIs(3u), ElementsAre(ValueIs(123), ValueIs(123),
1314                                                  ValueIs(123))));
1315     EXPECT_LE(v.size(), v.capacity());
1316   }
1317 }
TEST(CountElemAssign,WithAllocationCopyableInstance)1318 TEST(CountElemAssign, WithAllocationCopyableInstance) {
1319   InstanceCountElemAssignWithAllocationTest<CopyableOnlyInstance>();
1320 }
TEST(CountElemAssign,WithAllocationCopyableMovableInstance)1321 TEST(CountElemAssign, WithAllocationCopyableMovableInstance) {
1322   InstanceCountElemAssignWithAllocationTest<CopyableMovableInstance>();
1323 }
1324 
TEST(RangedConstructor,SimpleType)1325 TEST(RangedConstructor, SimpleType) {
1326   std::vector<int> source_v = {4, 5, 6};
1327   // First try to fit in inline backing
1328   absl::InlinedVector<int, 4> v(source_v.begin(), source_v.end());
1329   EXPECT_EQ(3u, v.size());
1330   EXPECT_EQ(4u,
1331             v.capacity());  // Indication that we're still on inlined storage
1332   EXPECT_EQ(4, v[0]);
1333   EXPECT_EQ(5, v[1]);
1334   EXPECT_EQ(6, v[2]);
1335 
1336   // Now, force a re-allocate
1337   absl::InlinedVector<int, 2> realloc_v(source_v.begin(), source_v.end());
1338   EXPECT_EQ(3u, realloc_v.size());
1339   EXPECT_LT(2u, realloc_v.capacity());
1340   EXPECT_EQ(4, realloc_v[0]);
1341   EXPECT_EQ(5, realloc_v[1]);
1342   EXPECT_EQ(6, realloc_v[2]);
1343 }
1344 
1345 // Test for ranged constructors using Instance as the element type and
1346 // SourceContainer as the source container type.
1347 template <typename Instance, typename SourceContainer, int inlined_capacity>
InstanceRangedConstructorTestForContainer()1348 void InstanceRangedConstructorTestForContainer() {
1349   InstanceTracker tracker;
1350   SourceContainer source_v = {Instance(0), Instance(1)};
1351   tracker.ResetCopiesMovesSwaps();
1352   absl::InlinedVector<Instance, inlined_capacity> v(source_v.begin(),
1353                                                     source_v.end());
1354   EXPECT_EQ(2u, v.size());
1355   EXPECT_LT(1u, v.capacity());
1356   EXPECT_EQ(0, v[0].value());
1357   EXPECT_EQ(1, v[1].value());
1358   EXPECT_EQ(tracker.copies(), 2);
1359   EXPECT_EQ(tracker.moves(), 0);
1360 }
1361 
1362 template <typename Instance, int inlined_capacity>
InstanceRangedConstructorTestWithCapacity()1363 void InstanceRangedConstructorTestWithCapacity() {
1364   // Test with const and non-const, random access and non-random-access sources.
1365   // TODO(bsamwel): Test with an input iterator source.
1366   {
1367     SCOPED_TRACE("std::list");
1368     InstanceRangedConstructorTestForContainer<Instance, std::list<Instance>,
1369                                               inlined_capacity>();
1370     {
1371       SCOPED_TRACE("const std::list");
1372       InstanceRangedConstructorTestForContainer<
1373           Instance, const std::list<Instance>, inlined_capacity>();
1374     }
1375     {
1376       SCOPED_TRACE("std::vector");
1377       InstanceRangedConstructorTestForContainer<Instance, std::vector<Instance>,
1378                                                 inlined_capacity>();
1379     }
1380     {
1381       SCOPED_TRACE("const std::vector");
1382       InstanceRangedConstructorTestForContainer<
1383           Instance, const std::vector<Instance>, inlined_capacity>();
1384     }
1385   }
1386 }
1387 
TYPED_TEST_P(InstanceTest,RangedConstructor)1388 TYPED_TEST_P(InstanceTest, RangedConstructor) {
1389   using Instance = TypeParam;
1390   SCOPED_TRACE("capacity=1");
1391   InstanceRangedConstructorTestWithCapacity<Instance, 1>();
1392   SCOPED_TRACE("capacity=2");
1393   InstanceRangedConstructorTestWithCapacity<Instance, 2>();
1394 }
1395 
TEST(RangedConstructor,ElementsAreConstructed)1396 TEST(RangedConstructor, ElementsAreConstructed) {
1397   std::vector<std::string> source_v = {"cat", "dog"};
1398 
1399   // Force expansion and re-allocation of v.  Ensures that when the vector is
1400   // expanded that new elements are constructed.
1401   absl::InlinedVector<std::string, 1> v(source_v.begin(), source_v.end());
1402   EXPECT_EQ("cat", v[0]);
1403   EXPECT_EQ("dog", v[1]);
1404 }
1405 
TEST(RangedAssign,SimpleType)1406 TEST(RangedAssign, SimpleType) {
1407   const size_t inlined_capacity = absl::InlinedVector<int, 3>().capacity();
1408 
1409   // Test for all combinations of original sizes (empty and non-empty inline,
1410   // and out of line) and target sizes.
1411   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1412     SCOPED_TRACE(original_size);
1413     // Original contents are [12345, 12345, ...]
1414     std::vector<int> original_contents(original_size, 12345);
1415 
1416     for (size_t target_size = 0; target_size <= 5; ++target_size) {
1417       SCOPED_TRACE(target_size);
1418 
1419       // New contents are [3, 4, ...]
1420       std::vector<int> new_contents;
1421       for (size_t i = 0; i < target_size; ++i) {
1422         new_contents.push_back(static_cast<int>(i + 3));
1423       }
1424 
1425       absl::InlinedVector<int, 3> v(original_contents.begin(),
1426                                     original_contents.end());
1427       v.assign(new_contents.begin(), new_contents.end());
1428 
1429       EXPECT_EQ(new_contents.size(), v.size());
1430       EXPECT_LE(new_contents.size(), v.capacity());
1431       if (target_size <= inlined_capacity &&
1432           original_size <= inlined_capacity) {
1433         // Storage should stay inline when target size is small.
1434         EXPECT_EQ(v.capacity(), inlined_capacity);
1435       }
1436       EXPECT_THAT(v, ElementsAreArray(new_contents));
1437     }
1438   }
1439 }
1440 
1441 // Returns true if lhs and rhs have the same value.
1442 template <typename Instance>
InstanceValuesEqual(const Instance & lhs,const Instance & rhs)1443 static bool InstanceValuesEqual(const Instance& lhs, const Instance& rhs) {
1444   return lhs.value() == rhs.value();
1445 }
1446 
1447 // Test for ranged assign() using Instance as the element type and
1448 // SourceContainer as the source container type.
1449 template <typename Instance, typename SourceContainer>
InstanceRangedAssignTestForContainer()1450 void InstanceRangedAssignTestForContainer() {
1451   // Test for all combinations of original sizes (empty and non-empty inline,
1452   // and out of line) and target sizes.
1453   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1454     SCOPED_TRACE(original_size);
1455     // Original contents are [12345, 12345, ...]
1456     std::vector<Instance> original_contents(original_size, Instance(12345));
1457 
1458     for (size_t target_size = 0; target_size <= 5; ++target_size) {
1459       SCOPED_TRACE(target_size);
1460 
1461       // New contents are [3, 4, ...]
1462       // Generate data using a non-const container, because SourceContainer
1463       // itself may be const.
1464       // TODO(bsamwel): Test with an input iterator.
1465       std::vector<Instance> new_contents_in;
1466       for (size_t i = 0; i < target_size; ++i) {
1467         new_contents_in.push_back(Instance(static_cast<int>(i) + 3));
1468       }
1469       SourceContainer new_contents(new_contents_in.begin(),
1470                                    new_contents_in.end());
1471 
1472       absl::InlinedVector<Instance, 3> v(original_contents.begin(),
1473                                          original_contents.end());
1474       v.assign(new_contents.begin(), new_contents.end());
1475 
1476       EXPECT_EQ(new_contents.size(), v.size());
1477       EXPECT_LE(new_contents.size(), v.capacity());
1478       if (target_size <= 3 && original_size <= 3) {
1479         // Storage should stay inline when target size is small.
1480         EXPECT_EQ(3u, v.capacity());
1481       }
1482       EXPECT_TRUE(std::equal(v.begin(), v.end(), new_contents.begin(),
1483                              InstanceValuesEqual<Instance>));
1484     }
1485   }
1486 }
1487 
TYPED_TEST_P(InstanceTest,RangedAssign)1488 TYPED_TEST_P(InstanceTest, RangedAssign) {
1489   using Instance = TypeParam;
1490   // Test with const and non-const, random access and non-random-access sources.
1491   // TODO(bsamwel): Test with an input iterator source.
1492   SCOPED_TRACE("std::list");
1493   InstanceRangedAssignTestForContainer<Instance, std::list<Instance>>();
1494   SCOPED_TRACE("const std::list");
1495   InstanceRangedAssignTestForContainer<Instance, const std::list<Instance>>();
1496   SCOPED_TRACE("std::vector");
1497   InstanceRangedAssignTestForContainer<Instance, std::vector<Instance>>();
1498   SCOPED_TRACE("const std::vector");
1499   InstanceRangedAssignTestForContainer<Instance, const std::vector<Instance>>();
1500 }
1501 
TEST(InitializerListConstructor,SimpleTypeWithInlineBacking)1502 TEST(InitializerListConstructor, SimpleTypeWithInlineBacking) {
1503   EXPECT_THAT((absl::InlinedVector<int, 4>{4, 5, 6}),
1504               AllOf(SizeIs(3u), CapacityIs(4u), ElementsAre(4, 5, 6)));
1505 }
1506 
TEST(InitializerListConstructor,SimpleTypeWithReallocationRequired)1507 TEST(InitializerListConstructor, SimpleTypeWithReallocationRequired) {
1508   EXPECT_THAT((absl::InlinedVector<int, 2>{4, 5, 6}),
1509               AllOf(SizeIs(3u), CapacityIs(Gt(2u)), ElementsAre(4, 5, 6)));
1510 }
1511 
TEST(InitializerListConstructor,DisparateTypesInList)1512 TEST(InitializerListConstructor, DisparateTypesInList) {
1513   EXPECT_THAT((absl::InlinedVector<int, 2>{-7, 8ULL}), ElementsAre(-7, 8));
1514 
1515   EXPECT_THAT((absl::InlinedVector<std::string, 2>{"foo", std::string("bar")}),
1516               ElementsAre("foo", "bar"));
1517 }
1518 
TEST(InitializerListConstructor,ComplexTypeWithInlineBacking)1519 TEST(InitializerListConstructor, ComplexTypeWithInlineBacking) {
1520   const size_t inlined_capacity =
1521       absl::InlinedVector<CopyableMovableInstance, 1>().capacity();
1522   EXPECT_THAT(
1523       (absl::InlinedVector<CopyableMovableInstance, 1>{
1524           CopyableMovableInstance(0)}),
1525       AllOf(SizeIs(1u), CapacityIs(inlined_capacity), ElementsAre(ValueIs(0))));
1526 }
1527 
TEST(InitializerListConstructor,ComplexTypeWithReallocationRequired)1528 TEST(InitializerListConstructor, ComplexTypeWithReallocationRequired) {
1529   EXPECT_THAT((absl::InlinedVector<CopyableMovableInstance, 1>{
1530                   CopyableMovableInstance(0), CopyableMovableInstance(1)}),
1531               AllOf(SizeIs(2u), CapacityIs(Gt(1u)),
1532                     ElementsAre(ValueIs(0), ValueIs(1))));
1533 }
1534 
TEST(InitializerListAssign,SimpleTypeFitsInlineBacking)1535 TEST(InitializerListAssign, SimpleTypeFitsInlineBacking) {
1536   for (size_t original_size = 0; original_size <= 4; ++original_size) {
1537     SCOPED_TRACE(original_size);
1538 
1539     absl::InlinedVector<int, 2> v1(original_size, 12345);
1540     const size_t original_capacity_v1 = v1.capacity();
1541     v1.assign({3});
1542     EXPECT_THAT(v1, AllOf(SizeIs(1u), CapacityIs(original_capacity_v1),
1543                           ElementsAre(3)));
1544 
1545     absl::InlinedVector<int, 2> v2(original_size, 12345);
1546     const size_t original_capacity_v2 = v2.capacity();
1547     v2 = {3};
1548     EXPECT_THAT(v2, AllOf(SizeIs(1u), CapacityIs(original_capacity_v2),
1549                           ElementsAre(3)));
1550   }
1551 }
1552 
TEST(InitializerListAssign,SimpleTypeDoesNotFitInlineBacking)1553 TEST(InitializerListAssign, SimpleTypeDoesNotFitInlineBacking) {
1554   for (size_t original_size = 0; original_size <= 4; ++original_size) {
1555     SCOPED_TRACE(original_size);
1556     absl::InlinedVector<int, 2> v1(original_size, 12345);
1557     v1.assign({3, 4, 5});
1558     EXPECT_THAT(v1, AllOf(SizeIs(3u), ElementsAre(3, 4, 5)));
1559     EXPECT_LE(3u, v1.capacity());
1560 
1561     absl::InlinedVector<int, 2> v2(original_size, 12345);
1562     v2 = {3, 4, 5};
1563     EXPECT_THAT(v2, AllOf(SizeIs(3u), ElementsAre(3, 4, 5)));
1564     EXPECT_LE(3u, v2.capacity());
1565   }
1566 }
1567 
TEST(InitializerListAssign,DisparateTypesInList)1568 TEST(InitializerListAssign, DisparateTypesInList) {
1569   absl::InlinedVector<int, 2> v_int1;
1570   v_int1.assign({-7, 8ULL});
1571   EXPECT_THAT(v_int1, ElementsAre(-7, 8));
1572 
1573   absl::InlinedVector<int, 2> v_int2;
1574   v_int2 = {-7, 8ULL};
1575   EXPECT_THAT(v_int2, ElementsAre(-7, 8));
1576 
1577   absl::InlinedVector<std::string, 2> v_string1;
1578   v_string1.assign({"foo", std::string("bar")});
1579   EXPECT_THAT(v_string1, ElementsAre("foo", "bar"));
1580 
1581   absl::InlinedVector<std::string, 2> v_string2;
1582   v_string2 = {"foo", std::string("bar")};
1583   EXPECT_THAT(v_string2, ElementsAre("foo", "bar"));
1584 }
1585 
TYPED_TEST_P(InstanceTest,InitializerListAssign)1586 TYPED_TEST_P(InstanceTest, InitializerListAssign) {
1587   using Instance = TypeParam;
1588   for (size_t original_size = 0; original_size <= 4; ++original_size) {
1589     SCOPED_TRACE(original_size);
1590     absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));
1591     const size_t original_capacity = v.capacity();
1592     v.assign({Instance(3)});
1593     EXPECT_THAT(v, AllOf(SizeIs(1u), CapacityIs(original_capacity),
1594                          ElementsAre(ValueIs(3))));
1595   }
1596   for (size_t original_size = 0; original_size <= 4; ++original_size) {
1597     SCOPED_TRACE(original_size);
1598     absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));
1599     v.assign({Instance(3), Instance(4), Instance(5)});
1600     EXPECT_THAT(
1601         v, AllOf(SizeIs(3u), ElementsAre(ValueIs(3), ValueIs(4), ValueIs(5))));
1602     EXPECT_LE(3u, v.capacity());
1603   }
1604 }
1605 
1606 REGISTER_TYPED_TEST_SUITE_P(InstanceTest, Swap, CountConstructorsDestructors,
1607                             CountConstructorsDestructorsOnCopyConstruction,
1608                             CountConstructorsDestructorsOnMoveConstruction,
1609                             CountConstructorsDestructorsOnAssignment,
1610                             CountConstructorsDestructorsOnMoveAssignment,
1611                             CountElemAssignInlineBacking, RangedConstructor,
1612                             RangedAssign, InitializerListAssign);
1613 
1614 using InstanceTypes =
1615     ::testing::Types<CopyableOnlyInstance, CopyableMovableInstance>;
1616 INSTANTIATE_TYPED_TEST_SUITE_P(InstanceTestOnTypes, InstanceTest,
1617                                InstanceTypes);
1618 
TEST(DynamicVec,DynamicVecCompiles)1619 TEST(DynamicVec, DynamicVecCompiles) {
1620   DynamicVec v;
1621   (void)v;
1622 }
1623 
TEST(AllocatorSupportTest,Constructors)1624 TEST(AllocatorSupportTest, Constructors) {
1625   using MyAlloc = CountingAllocator<int>;
1626   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
1627   const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
1628   int64_t allocated = 0;
1629   MyAlloc alloc(&allocated);
1630   { AllocVec ABSL_ATTRIBUTE_UNUSED v; }
1631   { AllocVec ABSL_ATTRIBUTE_UNUSED v(alloc); }
1632   { AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc); }
1633   { AllocVec ABSL_ATTRIBUTE_UNUSED v({1, 2, 3}, alloc); }
1634 
1635   AllocVec v2;
1636   { AllocVec ABSL_ATTRIBUTE_UNUSED v(v2, alloc); }
1637   { AllocVec ABSL_ATTRIBUTE_UNUSED v(std::move(v2), alloc); }
1638 }
1639 
TEST(AllocatorSupportTest,CountAllocations)1640 TEST(AllocatorSupportTest, CountAllocations) {
1641   using MyAlloc = CountingAllocator<int>;
1642   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
1643   const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
1644   int64_t allocated = 0;
1645   MyAlloc alloc(&allocated);
1646   {
1647     AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + 4, alloc);
1648     EXPECT_THAT(allocated, Eq(0));
1649   }
1650   EXPECT_THAT(allocated, Eq(0));
1651   {
1652     AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc);
1653     EXPECT_THAT(allocated, Eq(static_cast<int64_t>(v.size() * sizeof(int))));
1654   }
1655   EXPECT_THAT(allocated, Eq(0));
1656   {
1657     AllocVec v(4, 1, alloc);
1658     EXPECT_THAT(allocated, Eq(0));
1659 
1660     int64_t allocated2 = 0;
1661     MyAlloc alloc2(&allocated2);
1662     AllocVec v2(v, alloc2);
1663     EXPECT_THAT(allocated2, Eq(0));
1664 
1665     int64_t allocated3 = 0;
1666     MyAlloc alloc3(&allocated3);
1667     AllocVec v3(std::move(v), alloc3);
1668     EXPECT_THAT(allocated3, Eq(0));
1669   }
1670   EXPECT_THAT(allocated, 0);
1671   {
1672     AllocVec v(8, 2, alloc);
1673     EXPECT_THAT(allocated, Eq(static_cast<int64_t>(v.size() * sizeof(int))));
1674 
1675     int64_t allocated2 = 0;
1676     MyAlloc alloc2(&allocated2);
1677     AllocVec v2(v, alloc2);
1678     EXPECT_THAT(allocated2, Eq(static_cast<int64_t>(v2.size() * sizeof(int))));
1679 
1680     int64_t allocated3 = 0;
1681     MyAlloc alloc3(&allocated3);
1682     AllocVec v3(std::move(v), alloc3);
1683     EXPECT_THAT(allocated3, Eq(static_cast<int64_t>(v3.size() * sizeof(int))));
1684   }
1685   EXPECT_EQ(allocated, 0);
1686   {
1687     // Test shrink_to_fit deallocations.
1688     AllocVec v(8, 2, alloc);
1689     EXPECT_EQ(allocated, static_cast<int64_t>(8 * sizeof(int)));
1690     v.resize(5);
1691     EXPECT_EQ(allocated, static_cast<int64_t>(8 * sizeof(int)));
1692     v.shrink_to_fit();
1693     EXPECT_EQ(allocated, static_cast<int64_t>(5 * sizeof(int)));
1694     v.resize(4);
1695     EXPECT_EQ(allocated, static_cast<int64_t>(5 * sizeof(int)));
1696     v.shrink_to_fit();
1697     EXPECT_EQ(allocated, 0);
1698   }
1699 }
1700 
TEST(AllocatorSupportTest,SwapBothAllocated)1701 TEST(AllocatorSupportTest, SwapBothAllocated) {
1702   using MyAlloc = CountingAllocator<int>;
1703   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
1704   int64_t allocated1 = 0;
1705   int64_t allocated2 = 0;
1706   {
1707     const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7};
1708     const int ia2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1709     MyAlloc a1(&allocated1);
1710     MyAlloc a2(&allocated2);
1711     AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);
1712     AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2);
1713     EXPECT_LT(v1.capacity(), v2.capacity());
1714     EXPECT_THAT(allocated1,
1715                 Eq(static_cast<int64_t>(v1.capacity() * sizeof(int))));
1716     EXPECT_THAT(allocated2,
1717                 Eq(static_cast<int64_t>(v2.capacity() * sizeof(int))));
1718     v1.swap(v2);
1719     EXPECT_THAT(v1, ElementsAreArray(ia2));
1720     EXPECT_THAT(v2, ElementsAreArray(ia1));
1721     EXPECT_THAT(allocated1,
1722                 Eq(static_cast<int64_t>(v2.capacity() * sizeof(int))));
1723     EXPECT_THAT(allocated2,
1724                 Eq(static_cast<int64_t>(v1.capacity() * sizeof(int))));
1725   }
1726   EXPECT_THAT(allocated1, 0);
1727   EXPECT_THAT(allocated2, 0);
1728 }
1729 
TEST(AllocatorSupportTest,SwapOneAllocated)1730 TEST(AllocatorSupportTest, SwapOneAllocated) {
1731   using MyAlloc = CountingAllocator<int>;
1732   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
1733   int64_t allocated1 = 0;
1734   int64_t allocated2 = 0;
1735   {
1736     const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7};
1737     const int ia2[] = {0, 1, 2, 3};
1738     MyAlloc a1(&allocated1);
1739     MyAlloc a2(&allocated2);
1740     AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);
1741     AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2);
1742     EXPECT_THAT(allocated1,
1743                 Eq(static_cast<int64_t>(v1.capacity() * sizeof(int))));
1744     EXPECT_THAT(allocated2, Eq(0));
1745     v1.swap(v2);
1746     EXPECT_THAT(v1, ElementsAreArray(ia2));
1747     EXPECT_THAT(v2, ElementsAreArray(ia1));
1748     EXPECT_THAT(allocated1,
1749                 Eq(static_cast<int64_t>(v2.capacity() * sizeof(int))));
1750     EXPECT_THAT(allocated2, Eq(0));
1751     EXPECT_TRUE(v2.get_allocator() == a1);
1752     EXPECT_TRUE(v1.get_allocator() == a2);
1753   }
1754   EXPECT_THAT(allocated1, 0);
1755   EXPECT_THAT(allocated2, 0);
1756 }
1757 
TEST(AllocatorSupportTest,ScopedAllocatorWorksInlined)1758 TEST(AllocatorSupportTest, ScopedAllocatorWorksInlined) {
1759   using StdVector = std::vector<int, CountingAllocator<int>>;
1760   using Alloc = CountingAllocator<StdVector>;
1761   using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>;
1762   using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>;
1763 
1764   int64_t total_allocated_byte_count = 0;
1765 
1766   AllocVec inlined_case(ScopedAlloc(Alloc(+&total_allocated_byte_count)));
1767 
1768   // Called only once to remain inlined
1769   inlined_case.emplace_back();
1770 
1771   int64_t absl_responsible_for_count = total_allocated_byte_count;
1772 
1773   // MSVC's allocator preemptively allocates in debug mode
1774 #if !defined(_MSC_VER)
1775   EXPECT_EQ(absl_responsible_for_count, 0);
1776 #endif  // !defined(_MSC_VER)
1777 
1778   inlined_case[0].emplace_back();
1779   EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count);
1780 
1781   inlined_case.clear();
1782   inlined_case.shrink_to_fit();
1783   EXPECT_EQ(total_allocated_byte_count, 0);
1784 }
1785 
TEST(AllocatorSupportTest,ScopedAllocatorWorksAllocated)1786 TEST(AllocatorSupportTest, ScopedAllocatorWorksAllocated) {
1787   using StdVector = std::vector<int, CountingAllocator<int>>;
1788   using Alloc = CountingAllocator<StdVector>;
1789   using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>;
1790   using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>;
1791 
1792   int64_t total_allocated_byte_count = 0;
1793 
1794   AllocVec allocated_case(ScopedAlloc(Alloc(+&total_allocated_byte_count)));
1795 
1796   // Called twice to force into being allocated
1797   allocated_case.emplace_back();
1798   allocated_case.emplace_back();
1799 
1800   int64_t absl_responsible_for_count = total_allocated_byte_count;
1801   EXPECT_GT(absl_responsible_for_count, 0);
1802 
1803   allocated_case[1].emplace_back();
1804   EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count);
1805 
1806   allocated_case.clear();
1807   allocated_case.shrink_to_fit();
1808   EXPECT_EQ(total_allocated_byte_count, 0);
1809 }
1810 
TEST(AllocatorSupportTest,SizeAllocConstructor)1811 TEST(AllocatorSupportTest, SizeAllocConstructor) {
1812   constexpr size_t inlined_size = 4;
1813   using Alloc = CountingAllocator<int>;
1814   using AllocVec = absl::InlinedVector<int, inlined_size, Alloc>;
1815 
1816   {
1817     auto len = inlined_size / 2;
1818     int64_t allocated = 0;
1819     auto v = AllocVec(len, Alloc(&allocated));
1820 
1821     // Inline storage used; allocator should not be invoked
1822     EXPECT_THAT(allocated, Eq(0));
1823     EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
1824   }
1825 
1826   {
1827     auto len = inlined_size * 2;
1828     int64_t allocated = 0;
1829     auto v = AllocVec(len, Alloc(&allocated));
1830 
1831     // Out of line storage used; allocation of 8 elements expected
1832     EXPECT_THAT(allocated, Eq(static_cast<int64_t>(len * sizeof(int))));
1833     EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
1834   }
1835 }
1836 
TEST(InlinedVectorTest,MinimumAllocatorCompilesUsingTraits)1837 TEST(InlinedVectorTest, MinimumAllocatorCompilesUsingTraits) {
1838   using T = int;
1839   using A = std::allocator<T>;
1840   using ATraits = absl::allocator_traits<A>;
1841 
1842   struct MinimumAllocator {
1843     using value_type = T;
1844 
1845     value_type* allocate(size_t n) {
1846       A a;
1847       return ATraits::allocate(a, n);
1848     }
1849 
1850     void deallocate(value_type* p, size_t n) {
1851       A a;
1852       ATraits::deallocate(a, p, n);
1853     }
1854   };
1855 
1856   absl::InlinedVector<T, 1, MinimumAllocator> vec;
1857   vec.emplace_back();
1858   vec.resize(0);
1859 }
1860 
TEST(InlinedVectorTest,AbslHashValueWorks)1861 TEST(InlinedVectorTest, AbslHashValueWorks) {
1862   using V = absl::InlinedVector<int, 4>;
1863   std::vector<V> cases;
1864 
1865   // Generate a variety of vectors some of these are small enough for the inline
1866   // space but are stored out of line.
1867   for (size_t i = 0; i < 10; ++i) {
1868     V v;
1869     for (int j = 0; j < static_cast<int>(i); ++j) {
1870       v.push_back(j);
1871     }
1872     cases.push_back(v);
1873     v.resize(i % 4);
1874     cases.push_back(v);
1875   }
1876 
1877   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
1878 }
1879 
1880 class MoveConstructibleOnlyInstance
1881     : public absl::test_internal::BaseCountedInstance {
1882  public:
MoveConstructibleOnlyInstance(int x)1883   explicit MoveConstructibleOnlyInstance(int x) : BaseCountedInstance(x) {}
1884   MoveConstructibleOnlyInstance(MoveConstructibleOnlyInstance&& other) =
1885       default;
1886   MoveConstructibleOnlyInstance& operator=(
1887       MoveConstructibleOnlyInstance&& other) = delete;
1888 };
1889 
1890 MATCHER(HasValue, "") {
1891   return ::testing::get<0>(arg).value() == ::testing::get<1>(arg);
1892 }
1893 
TEST(NonAssignableMoveAssignmentTest,AllocatedToInline)1894 TEST(NonAssignableMoveAssignmentTest, AllocatedToInline) {
1895   using X = MoveConstructibleOnlyInstance;
1896   InstanceTracker tracker;
1897   absl::InlinedVector<X, 2> inlined;
1898   inlined.emplace_back(1);
1899   absl::InlinedVector<X, 2> allocated;
1900   allocated.emplace_back(1);
1901   allocated.emplace_back(2);
1902   allocated.emplace_back(3);
1903   tracker.ResetCopiesMovesSwaps();
1904 
1905   inlined = std::move(allocated);
1906   // passed ownership of the allocated storage
1907   EXPECT_EQ(tracker.moves(), 0);
1908   EXPECT_EQ(tracker.live_instances(), 3);
1909 
1910   EXPECT_THAT(inlined, Pointwise(HasValue(), {1, 2, 3}));
1911 }
1912 
TEST(NonAssignableMoveAssignmentTest,InlineToAllocated)1913 TEST(NonAssignableMoveAssignmentTest, InlineToAllocated) {
1914   using X = MoveConstructibleOnlyInstance;
1915   InstanceTracker tracker;
1916   absl::InlinedVector<X, 2> inlined;
1917   inlined.emplace_back(1);
1918   absl::InlinedVector<X, 2> allocated;
1919   allocated.emplace_back(1);
1920   allocated.emplace_back(2);
1921   allocated.emplace_back(3);
1922   tracker.ResetCopiesMovesSwaps();
1923 
1924   allocated = std::move(inlined);
1925   // Moved elements
1926   EXPECT_EQ(tracker.moves(), 1);
1927   EXPECT_EQ(tracker.live_instances(), 1);
1928 
1929   EXPECT_THAT(allocated, Pointwise(HasValue(), {1}));
1930 }
1931 
TEST(NonAssignableMoveAssignmentTest,InlineToInline)1932 TEST(NonAssignableMoveAssignmentTest, InlineToInline) {
1933   using X = MoveConstructibleOnlyInstance;
1934   InstanceTracker tracker;
1935   absl::InlinedVector<X, 2> inlined_a;
1936   inlined_a.emplace_back(1);
1937   absl::InlinedVector<X, 2> inlined_b;
1938   inlined_b.emplace_back(1);
1939   tracker.ResetCopiesMovesSwaps();
1940 
1941   inlined_a = std::move(inlined_b);
1942   // Moved elements
1943   EXPECT_EQ(tracker.moves(), 1);
1944   EXPECT_EQ(tracker.live_instances(), 1);
1945 
1946   EXPECT_THAT(inlined_a, Pointwise(HasValue(), {1}));
1947 }
1948 
TEST(NonAssignableMoveAssignmentTest,AllocatedToAllocated)1949 TEST(NonAssignableMoveAssignmentTest, AllocatedToAllocated) {
1950   using X = MoveConstructibleOnlyInstance;
1951   InstanceTracker tracker;
1952   absl::InlinedVector<X, 2> allocated_a;
1953   allocated_a.emplace_back(1);
1954   allocated_a.emplace_back(2);
1955   allocated_a.emplace_back(3);
1956   absl::InlinedVector<X, 2> allocated_b;
1957   allocated_b.emplace_back(4);
1958   allocated_b.emplace_back(5);
1959   allocated_b.emplace_back(6);
1960   allocated_b.emplace_back(7);
1961   tracker.ResetCopiesMovesSwaps();
1962 
1963   allocated_a = std::move(allocated_b);
1964   // passed ownership of the allocated storage
1965   EXPECT_EQ(tracker.moves(), 0);
1966   EXPECT_EQ(tracker.live_instances(), 4);
1967 
1968   EXPECT_THAT(allocated_a, Pointwise(HasValue(), {4, 5, 6, 7}));
1969 }
1970 
TEST(NonAssignableMoveAssignmentTest,AssignThis)1971 TEST(NonAssignableMoveAssignmentTest, AssignThis) {
1972   using X = MoveConstructibleOnlyInstance;
1973   InstanceTracker tracker;
1974   absl::InlinedVector<X, 2> v;
1975   v.emplace_back(1);
1976   v.emplace_back(2);
1977   v.emplace_back(3);
1978 
1979   tracker.ResetCopiesMovesSwaps();
1980 
1981   // Obfuscated in order to pass -Wself-move.
1982   v = std::move(*std::addressof(v));
1983   // nothing happens
1984   EXPECT_EQ(tracker.moves(), 0);
1985   EXPECT_EQ(tracker.live_instances(), 3);
1986 
1987   EXPECT_THAT(v, Pointwise(HasValue(), {1, 2, 3}));
1988 }
1989 
1990 class NonSwappableInstance : public absl::test_internal::BaseCountedInstance {
1991  public:
NonSwappableInstance(int x)1992   explicit NonSwappableInstance(int x) : BaseCountedInstance(x) {}
1993   NonSwappableInstance(const NonSwappableInstance& other) = default;
1994   NonSwappableInstance& operator=(const NonSwappableInstance& other) = default;
1995   NonSwappableInstance(NonSwappableInstance&& other) = default;
1996   NonSwappableInstance& operator=(NonSwappableInstance&& other) = default;
1997 };
1998 
1999 void swap(NonSwappableInstance&, NonSwappableInstance&) = delete;
2000 
TEST(NonSwappableSwapTest,InlineAndAllocatedTransferStorageAndMove)2001 TEST(NonSwappableSwapTest, InlineAndAllocatedTransferStorageAndMove) {
2002   using X = NonSwappableInstance;
2003   InstanceTracker tracker;
2004   absl::InlinedVector<X, 2> inlined;
2005   inlined.emplace_back(1);
2006   absl::InlinedVector<X, 2> allocated;
2007   allocated.emplace_back(1);
2008   allocated.emplace_back(2);
2009   allocated.emplace_back(3);
2010   tracker.ResetCopiesMovesSwaps();
2011 
2012   inlined.swap(allocated);
2013   EXPECT_EQ(tracker.moves(), 1);
2014   EXPECT_EQ(tracker.live_instances(), 4);
2015 
2016   EXPECT_THAT(inlined, Pointwise(HasValue(), {1, 2, 3}));
2017 }
2018 
TEST(NonSwappableSwapTest,InlineAndInlineMoveIndividualElements)2019 TEST(NonSwappableSwapTest, InlineAndInlineMoveIndividualElements) {
2020   using X = NonSwappableInstance;
2021   InstanceTracker tracker;
2022   absl::InlinedVector<X, 2> inlined_a;
2023   inlined_a.emplace_back(1);
2024   absl::InlinedVector<X, 2> inlined_b;
2025   inlined_b.emplace_back(2);
2026   tracker.ResetCopiesMovesSwaps();
2027 
2028   inlined_a.swap(inlined_b);
2029   EXPECT_EQ(tracker.moves(), 3);
2030   EXPECT_EQ(tracker.live_instances(), 2);
2031 
2032   EXPECT_THAT(inlined_a, Pointwise(HasValue(), {2}));
2033   EXPECT_THAT(inlined_b, Pointwise(HasValue(), {1}));
2034 }
2035 
TEST(NonSwappableSwapTest,AllocatedAndAllocatedOnlyTransferStorage)2036 TEST(NonSwappableSwapTest, AllocatedAndAllocatedOnlyTransferStorage) {
2037   using X = NonSwappableInstance;
2038   InstanceTracker tracker;
2039   absl::InlinedVector<X, 2> allocated_a;
2040   allocated_a.emplace_back(1);
2041   allocated_a.emplace_back(2);
2042   allocated_a.emplace_back(3);
2043   absl::InlinedVector<X, 2> allocated_b;
2044   allocated_b.emplace_back(4);
2045   allocated_b.emplace_back(5);
2046   allocated_b.emplace_back(6);
2047   allocated_b.emplace_back(7);
2048   tracker.ResetCopiesMovesSwaps();
2049 
2050   allocated_a.swap(allocated_b);
2051   EXPECT_EQ(tracker.moves(), 0);
2052   EXPECT_EQ(tracker.live_instances(), 7);
2053 
2054   EXPECT_THAT(allocated_a, Pointwise(HasValue(), {4, 5, 6, 7}));
2055   EXPECT_THAT(allocated_b, Pointwise(HasValue(), {1, 2, 3}));
2056 }
2057 
TEST(NonSwappableSwapTest,SwapThis)2058 TEST(NonSwappableSwapTest, SwapThis) {
2059   using X = NonSwappableInstance;
2060   InstanceTracker tracker;
2061   absl::InlinedVector<X, 2> v;
2062   v.emplace_back(1);
2063   v.emplace_back(2);
2064   v.emplace_back(3);
2065 
2066   tracker.ResetCopiesMovesSwaps();
2067 
2068   v.swap(v);
2069   EXPECT_EQ(tracker.moves(), 0);
2070   EXPECT_EQ(tracker.live_instances(), 3);
2071 
2072   EXPECT_THAT(v, Pointwise(HasValue(), {1, 2, 3}));
2073 }
2074 
2075 template <size_t N>
2076 using CharVec = absl::InlinedVector<char, N>;
2077 
2078 // Warning: This struct "simulates" the type `InlinedVector::Storage::Allocated`
2079 // to make reasonable expectations for inlined storage capacity optimization. If
2080 // implementation changes `Allocated`, then `MySpan` and tests that use it need
2081 // to be updated accordingly.
2082 template <typename T>
2083 struct MySpan {
2084   T* data;
2085   size_t size;
2086 };
2087 
TEST(StorageTest,InlinedCapacityAutoIncrease)2088 TEST(StorageTest, InlinedCapacityAutoIncrease) {
2089   // The requested capacity is auto increased to `sizeof(MySpan<char>)`.
2090   EXPECT_GT(CharVec<1>().capacity(), 1);
2091   EXPECT_EQ(CharVec<1>().capacity(), sizeof(MySpan<char>));
2092   EXPECT_EQ(CharVec<1>().capacity(), CharVec<2>().capacity());
2093   EXPECT_EQ(sizeof(CharVec<1>), sizeof(CharVec<2>));
2094 
2095   // The requested capacity is auto increased to
2096   // `sizeof(MySpan<int>) / sizeof(int)`.
2097   EXPECT_GT((absl::InlinedVector<int, 1>().capacity()), 1);
2098   EXPECT_EQ((absl::InlinedVector<int, 1>().capacity()),
2099             sizeof(MySpan<int>) / sizeof(int));
2100 }
2101 
2102 }  // anonymous namespace
2103