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