• 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__anon1853e2900111::NoDefaultCtor310   explicit NoDefaultCtor(int) {}
311 };
312 struct NoCopy {
NoCopy__anon1853e2900111::NoCopy313   NoCopy() {}
314   NoCopy(const NoCopy&) = delete;
315 };
316 struct NoAssign {
NoAssign__anon1853e2900111::NoAssign317   NoAssign() {}
318   NoAssign& operator=(const NoAssign&) = delete;
319 };
320 struct MoveOnly {
MoveOnly__anon1853e2900111::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 
740   struct T { void* val; };
741   size_t expected_overhead = sizeof(T);
742 
743   EXPECT_EQ((2 * expected_overhead),
744             sizeof(absl::InlinedVector<T, 1>) - sizeof(T[1]));
745   EXPECT_EQ(expected_overhead,
746             sizeof(absl::InlinedVector<T, 2>) - sizeof(T[2]));
747   EXPECT_EQ(expected_overhead,
748             sizeof(absl::InlinedVector<T, 3>) - sizeof(T[3]));
749   EXPECT_EQ(expected_overhead,
750             sizeof(absl::InlinedVector<T, 4>) - sizeof(T[4]));
751   EXPECT_EQ(expected_overhead,
752             sizeof(absl::InlinedVector<T, 5>) - sizeof(T[5]));
753   EXPECT_EQ(expected_overhead,
754             sizeof(absl::InlinedVector<T, 6>) - sizeof(T[6]));
755   EXPECT_EQ(expected_overhead,
756             sizeof(absl::InlinedVector<T, 7>) - sizeof(T[7]));
757   EXPECT_EQ(expected_overhead,
758             sizeof(absl::InlinedVector<T, 8>) - sizeof(T[8]));
759 }
760 
TEST(IntVec,Clear)761 TEST(IntVec, Clear) {
762   for (int len = 0; len < 20; len++) {
763     SCOPED_TRACE(len);
764     IntVec v;
765     Fill(&v, len);
766     v.clear();
767     EXPECT_EQ(0, v.size());
768     EXPECT_EQ(v.begin(), v.end());
769   }
770 }
771 
TEST(IntVec,Reserve)772 TEST(IntVec, Reserve) {
773   for (int len = 0; len < 20; len++) {
774     IntVec v;
775     Fill(&v, len);
776 
777     for (int newlen = 0; newlen < 100; newlen++) {
778       const int* start_rep = v.data();
779       v.reserve(newlen);
780       const int* final_rep = v.data();
781       if (newlen <= len) {
782         EXPECT_EQ(start_rep, final_rep);
783       }
784       EXPECT_LE(newlen, v.capacity());
785 
786       // Filling up to newlen should not change rep
787       while (v.size() < newlen) {
788         v.push_back(0);
789       }
790       EXPECT_EQ(final_rep, v.data());
791     }
792   }
793 }
794 
TEST(StringVec,SelfRefPushBack)795 TEST(StringVec, SelfRefPushBack) {
796   std::vector<std::string> std_v;
797   absl::InlinedVector<std::string, 4> v;
798   const std::string s = "A quite long string to ensure heap.";
799   std_v.push_back(s);
800   v.push_back(s);
801   for (int i = 0; i < 20; ++i) {
802     EXPECT_THAT(v, ElementsAreArray(std_v));
803 
804     v.push_back(v.back());
805     std_v.push_back(std_v.back());
806   }
807   EXPECT_THAT(v, ElementsAreArray(std_v));
808 }
809 
TEST(StringVec,SelfRefPushBackWithMove)810 TEST(StringVec, SelfRefPushBackWithMove) {
811   std::vector<std::string> std_v;
812   absl::InlinedVector<std::string, 4> v;
813   const std::string s = "A quite long string to ensure heap.";
814   std_v.push_back(s);
815   v.push_back(s);
816   for (int i = 0; i < 20; ++i) {
817     EXPECT_EQ(v.back(), std_v.back());
818 
819     v.push_back(std::move(v.back()));
820     std_v.push_back(std::move(std_v.back()));
821   }
822   EXPECT_EQ(v.back(), std_v.back());
823 }
824 
TEST(StringVec,SelfMove)825 TEST(StringVec, SelfMove) {
826   const std::string s = "A quite long string to ensure heap.";
827   for (int len = 0; len < 20; len++) {
828     SCOPED_TRACE(len);
829     absl::InlinedVector<std::string, 8> v;
830     for (int i = 0; i < len; ++i) {
831       SCOPED_TRACE(i);
832       v.push_back(s);
833     }
834     // Indirection necessary to avoid compiler warning.
835     v = std::move(*(&v));
836     // Ensure that the inlined vector is still in a valid state by copying it.
837     // We don't expect specific contents since a self-move results in an
838     // unspecified valid state.
839     std::vector<std::string> copy(v.begin(), v.end());
840   }
841 }
842 
TEST(IntVec,Swap)843 TEST(IntVec, Swap) {
844   for (int l1 = 0; l1 < 20; l1++) {
845     SCOPED_TRACE(l1);
846     for (int l2 = 0; l2 < 20; l2++) {
847       SCOPED_TRACE(l2);
848       IntVec a = Fill(l1, 0);
849       IntVec b = Fill(l2, 100);
850       {
851         using std::swap;
852         swap(a, b);
853       }
854       EXPECT_EQ(l1, b.size());
855       EXPECT_EQ(l2, a.size());
856       for (int i = 0; i < l1; i++) {
857         SCOPED_TRACE(i);
858         EXPECT_EQ(i, b[i]);
859       }
860       for (int i = 0; i < l2; i++) {
861         SCOPED_TRACE(i);
862         EXPECT_EQ(100 + i, a[i]);
863       }
864     }
865   }
866 }
867 
TYPED_TEST_P(InstanceTest,Swap)868 TYPED_TEST_P(InstanceTest, Swap) {
869   using Instance = TypeParam;
870   using InstanceVec = absl::InlinedVector<Instance, 8>;
871   for (int l1 = 0; l1 < 20; l1++) {
872     SCOPED_TRACE(l1);
873     for (int l2 = 0; l2 < 20; l2++) {
874       SCOPED_TRACE(l2);
875       InstanceTracker tracker;
876       InstanceVec a, b;
877       const size_t inlined_capacity = a.capacity();
878       auto min_len = std::min(l1, l2);
879       auto max_len = std::max(l1, l2);
880       for (int i = 0; i < l1; i++) a.push_back(Instance(i));
881       for (int i = 0; i < l2; i++) b.push_back(Instance(100 + i));
882       EXPECT_EQ(tracker.instances(), l1 + l2);
883       tracker.ResetCopiesMovesSwaps();
884       {
885         using std::swap;
886         swap(a, b);
887       }
888       EXPECT_EQ(tracker.instances(), l1 + l2);
889       if (a.size() > inlined_capacity && b.size() > inlined_capacity) {
890         EXPECT_EQ(tracker.swaps(), 0);  // Allocations are swapped.
891         EXPECT_EQ(tracker.moves(), 0);
892       } else if (a.size() <= inlined_capacity && b.size() <= inlined_capacity) {
893         EXPECT_EQ(tracker.swaps(), min_len);
894         EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
895                   max_len - min_len);
896       } else {
897         // One is allocated and the other isn't. The allocation is transferred
898         // without copying elements, and the inlined instances are copied/moved.
899         EXPECT_EQ(tracker.swaps(), 0);
900         EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
901                   min_len);
902       }
903 
904       EXPECT_EQ(l1, b.size());
905       EXPECT_EQ(l2, a.size());
906       for (int i = 0; i < l1; i++) {
907         EXPECT_EQ(i, b[i].value());
908       }
909       for (int i = 0; i < l2; i++) {
910         EXPECT_EQ(100 + i, a[i].value());
911       }
912     }
913   }
914 }
915 
TEST(IntVec,EqualAndNotEqual)916 TEST(IntVec, EqualAndNotEqual) {
917   IntVec a, b;
918   EXPECT_TRUE(a == b);
919   EXPECT_FALSE(a != b);
920 
921   a.push_back(3);
922   EXPECT_FALSE(a == b);
923   EXPECT_TRUE(a != b);
924 
925   b.push_back(3);
926   EXPECT_TRUE(a == b);
927   EXPECT_FALSE(a != b);
928 
929   b.push_back(7);
930   EXPECT_FALSE(a == b);
931   EXPECT_TRUE(a != b);
932 
933   a.push_back(6);
934   EXPECT_FALSE(a == b);
935   EXPECT_TRUE(a != b);
936 
937   a.clear();
938   b.clear();
939   for (int i = 0; i < 100; i++) {
940     a.push_back(i);
941     b.push_back(i);
942     EXPECT_TRUE(a == b);
943     EXPECT_FALSE(a != b);
944 
945     b[i] = b[i] + 1;
946     EXPECT_FALSE(a == b);
947     EXPECT_TRUE(a != b);
948 
949     b[i] = b[i] - 1;  // Back to before
950     EXPECT_TRUE(a == b);
951     EXPECT_FALSE(a != b);
952   }
953 }
954 
TEST(IntVec,RelationalOps)955 TEST(IntVec, RelationalOps) {
956   IntVec a, b;
957   EXPECT_FALSE(a < b);
958   EXPECT_FALSE(b < a);
959   EXPECT_FALSE(a > b);
960   EXPECT_FALSE(b > a);
961   EXPECT_TRUE(a <= b);
962   EXPECT_TRUE(b <= a);
963   EXPECT_TRUE(a >= b);
964   EXPECT_TRUE(b >= a);
965   b.push_back(3);
966   EXPECT_TRUE(a < b);
967   EXPECT_FALSE(b < a);
968   EXPECT_FALSE(a > b);
969   EXPECT_TRUE(b > a);
970   EXPECT_TRUE(a <= b);
971   EXPECT_FALSE(b <= a);
972   EXPECT_FALSE(a >= b);
973   EXPECT_TRUE(b >= a);
974 }
975 
TYPED_TEST_P(InstanceTest,CountConstructorsDestructors)976 TYPED_TEST_P(InstanceTest, CountConstructorsDestructors) {
977   using Instance = TypeParam;
978   using InstanceVec = absl::InlinedVector<Instance, 8>;
979   InstanceTracker tracker;
980   for (int len = 0; len < 20; len++) {
981     SCOPED_TRACE(len);
982     tracker.ResetCopiesMovesSwaps();
983 
984     InstanceVec v;
985     const size_t inlined_capacity = v.capacity();
986     for (int i = 0; i < len; i++) {
987       v.push_back(Instance(i));
988     }
989     EXPECT_EQ(tracker.instances(), len);
990     EXPECT_GE(tracker.copies() + tracker.moves(),
991               len);  // More due to reallocation.
992     tracker.ResetCopiesMovesSwaps();
993 
994     // Enlarging resize() must construct some objects
995     tracker.ResetCopiesMovesSwaps();
996     v.resize(len + 10, Instance(100));
997     EXPECT_EQ(tracker.instances(), len + 10);
998     if (len <= inlined_capacity && len + 10 > inlined_capacity) {
999       EXPECT_EQ(tracker.copies() + tracker.moves(), 10 + len);
1000     } else {
1001       // Only specify a minimum number of copies + moves. We don't want to
1002       // depend on the reallocation policy here.
1003       EXPECT_GE(tracker.copies() + tracker.moves(),
1004                 10);  // More due to reallocation.
1005     }
1006 
1007     // Shrinking resize() must destroy some objects
1008     tracker.ResetCopiesMovesSwaps();
1009     v.resize(len, Instance(100));
1010     EXPECT_EQ(tracker.instances(), len);
1011     EXPECT_EQ(tracker.copies(), 0);
1012     EXPECT_EQ(tracker.moves(), 0);
1013 
1014     // reserve() must not increase the number of initialized objects
1015     SCOPED_TRACE("reserve");
1016     v.reserve(len + 1000);
1017     EXPECT_EQ(tracker.instances(), len);
1018     EXPECT_EQ(tracker.copies() + tracker.moves(), len);
1019 
1020     // pop_back() and erase() must destroy one object
1021     if (len > 0) {
1022       tracker.ResetCopiesMovesSwaps();
1023       v.pop_back();
1024       EXPECT_EQ(tracker.instances(), len - 1);
1025       EXPECT_EQ(tracker.copies(), 0);
1026       EXPECT_EQ(tracker.moves(), 0);
1027 
1028       if (!v.empty()) {
1029         tracker.ResetCopiesMovesSwaps();
1030         v.erase(v.begin());
1031         EXPECT_EQ(tracker.instances(), len - 2);
1032         EXPECT_EQ(tracker.copies() + tracker.moves(), len - 2);
1033       }
1034     }
1035 
1036     tracker.ResetCopiesMovesSwaps();
1037     int instances_before_empty_erase = tracker.instances();
1038     v.erase(v.begin(), v.begin());
1039     EXPECT_EQ(tracker.instances(), instances_before_empty_erase);
1040     EXPECT_EQ(tracker.copies() + tracker.moves(), 0);
1041   }
1042 }
1043 
TYPED_TEST_P(InstanceTest,CountConstructorsDestructorsOnCopyConstruction)1044 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnCopyConstruction) {
1045   using Instance = TypeParam;
1046   using InstanceVec = absl::InlinedVector<Instance, 8>;
1047   InstanceTracker tracker;
1048   for (int len = 0; len < 20; len++) {
1049     SCOPED_TRACE(len);
1050     tracker.ResetCopiesMovesSwaps();
1051 
1052     InstanceVec v;
1053     for (int i = 0; i < len; i++) {
1054       v.push_back(Instance(i));
1055     }
1056     EXPECT_EQ(tracker.instances(), len);
1057     EXPECT_GE(tracker.copies() + tracker.moves(),
1058               len);  // More due to reallocation.
1059     tracker.ResetCopiesMovesSwaps();
1060     {  // Copy constructor should create 'len' more instances.
1061       InstanceVec v_copy(v);
1062       EXPECT_EQ(tracker.instances(), len + len);
1063       EXPECT_EQ(tracker.copies(), len);
1064       EXPECT_EQ(tracker.moves(), 0);
1065     }
1066     EXPECT_EQ(tracker.instances(), len);
1067   }
1068 }
1069 
TYPED_TEST_P(InstanceTest,CountConstructorsDestructorsOnMoveConstruction)1070 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveConstruction) {
1071   using Instance = TypeParam;
1072   using InstanceVec = absl::InlinedVector<Instance, 8>;
1073   InstanceTracker tracker;
1074   for (int len = 0; len < 20; len++) {
1075     SCOPED_TRACE(len);
1076     tracker.ResetCopiesMovesSwaps();
1077 
1078     InstanceVec v;
1079     const size_t inlined_capacity = v.capacity();
1080     for (int i = 0; i < len; i++) {
1081       v.push_back(Instance(i));
1082     }
1083     EXPECT_EQ(tracker.instances(), len);
1084     EXPECT_GE(tracker.copies() + tracker.moves(),
1085               len);  // More due to reallocation.
1086     tracker.ResetCopiesMovesSwaps();
1087     {
1088       InstanceVec v_copy(std::move(v));
1089       if (len > inlined_capacity) {
1090         // Allocation is moved as a whole.
1091         EXPECT_EQ(tracker.instances(), len);
1092         EXPECT_EQ(tracker.live_instances(), len);
1093         // Tests an implementation detail, don't rely on this in your code.
1094         EXPECT_EQ(v.size(), 0);  // NOLINT misc-use-after-move
1095         EXPECT_EQ(tracker.copies(), 0);
1096         EXPECT_EQ(tracker.moves(), 0);
1097       } else {
1098         EXPECT_EQ(tracker.instances(), len + len);
1099         if (Instance::supports_move()) {
1100           EXPECT_EQ(tracker.live_instances(), len);
1101           EXPECT_EQ(tracker.copies(), 0);
1102           EXPECT_EQ(tracker.moves(), len);
1103         } else {
1104           EXPECT_EQ(tracker.live_instances(), len + len);
1105           EXPECT_EQ(tracker.copies(), len);
1106           EXPECT_EQ(tracker.moves(), 0);
1107         }
1108       }
1109       EXPECT_EQ(tracker.swaps(), 0);
1110     }
1111   }
1112 }
1113 
TYPED_TEST_P(InstanceTest,CountConstructorsDestructorsOnAssignment)1114 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnAssignment) {
1115   using Instance = TypeParam;
1116   using InstanceVec = absl::InlinedVector<Instance, 8>;
1117   InstanceTracker tracker;
1118   for (int len = 0; len < 20; len++) {
1119     SCOPED_TRACE(len);
1120     for (int longorshort = 0; longorshort <= 1; ++longorshort) {
1121       SCOPED_TRACE(longorshort);
1122       tracker.ResetCopiesMovesSwaps();
1123 
1124       InstanceVec longer, shorter;
1125       for (int i = 0; i < len; i++) {
1126         longer.push_back(Instance(i));
1127         shorter.push_back(Instance(i));
1128       }
1129       longer.push_back(Instance(len));
1130       EXPECT_EQ(tracker.instances(), len + len + 1);
1131       EXPECT_GE(tracker.copies() + tracker.moves(),
1132                 len + len + 1);  // More due to reallocation.
1133 
1134       tracker.ResetCopiesMovesSwaps();
1135       if (longorshort) {
1136         shorter = longer;
1137         EXPECT_EQ(tracker.instances(), (len + 1) + (len + 1));
1138         EXPECT_GE(tracker.copies() + tracker.moves(),
1139                   len + 1);  // More due to reallocation.
1140       } else {
1141         longer = shorter;
1142         EXPECT_EQ(tracker.instances(), len + len);
1143         EXPECT_EQ(tracker.copies() + tracker.moves(), len);
1144       }
1145     }
1146   }
1147 }
1148 
TYPED_TEST_P(InstanceTest,CountConstructorsDestructorsOnMoveAssignment)1149 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveAssignment) {
1150   using Instance = TypeParam;
1151   using InstanceVec = absl::InlinedVector<Instance, 8>;
1152   InstanceTracker tracker;
1153   for (int len = 0; len < 20; len++) {
1154     SCOPED_TRACE(len);
1155     for (int longorshort = 0; longorshort <= 1; ++longorshort) {
1156       SCOPED_TRACE(longorshort);
1157       tracker.ResetCopiesMovesSwaps();
1158 
1159       InstanceVec longer, shorter;
1160       const int inlined_capacity = longer.capacity();
1161       for (int i = 0; i < len; i++) {
1162         longer.push_back(Instance(i));
1163         shorter.push_back(Instance(i));
1164       }
1165       longer.push_back(Instance(len));
1166       EXPECT_EQ(tracker.instances(), len + len + 1);
1167       EXPECT_GE(tracker.copies() + tracker.moves(),
1168                 len + len + 1);  // More due to reallocation.
1169 
1170       tracker.ResetCopiesMovesSwaps();
1171       int src_len;
1172       if (longorshort) {
1173         src_len = len + 1;
1174         shorter = std::move(longer);
1175       } else {
1176         src_len = len;
1177         longer = std::move(shorter);
1178       }
1179       if (src_len > inlined_capacity) {
1180         // Allocation moved as a whole.
1181         EXPECT_EQ(tracker.instances(), src_len);
1182         EXPECT_EQ(tracker.live_instances(), src_len);
1183         EXPECT_EQ(tracker.copies(), 0);
1184         EXPECT_EQ(tracker.moves(), 0);
1185       } else {
1186         // Elements are all copied.
1187         EXPECT_EQ(tracker.instances(), src_len + src_len);
1188         if (Instance::supports_move()) {
1189           EXPECT_EQ(tracker.copies(), 0);
1190           EXPECT_EQ(tracker.moves(), src_len);
1191           EXPECT_EQ(tracker.live_instances(), src_len);
1192         } else {
1193           EXPECT_EQ(tracker.copies(), src_len);
1194           EXPECT_EQ(tracker.moves(), 0);
1195           EXPECT_EQ(tracker.live_instances(), src_len + src_len);
1196         }
1197       }
1198       EXPECT_EQ(tracker.swaps(), 0);
1199     }
1200   }
1201 }
1202 
TEST(CountElemAssign,SimpleTypeWithInlineBacking)1203 TEST(CountElemAssign, SimpleTypeWithInlineBacking) {
1204   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1205     SCOPED_TRACE(original_size);
1206     // Original contents are [12345, 12345, ...]
1207     std::vector<int> original_contents(original_size, 12345);
1208 
1209     absl::InlinedVector<int, 2> v(original_contents.begin(),
1210                                   original_contents.end());
1211     v.assign(2, 123);
1212     EXPECT_THAT(v, AllOf(SizeIs(2), ElementsAre(123, 123)));
1213     if (original_size <= 2) {
1214       // If the original had inline backing, it should stay inline.
1215       EXPECT_EQ(2, v.capacity());
1216     }
1217   }
1218 }
1219 
TEST(CountElemAssign,SimpleTypeWithAllocation)1220 TEST(CountElemAssign, SimpleTypeWithAllocation) {
1221   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1222     SCOPED_TRACE(original_size);
1223     // Original contents are [12345, 12345, ...]
1224     std::vector<int> original_contents(original_size, 12345);
1225 
1226     absl::InlinedVector<int, 2> v(original_contents.begin(),
1227                                   original_contents.end());
1228     v.assign(3, 123);
1229     EXPECT_THAT(v, AllOf(SizeIs(3), ElementsAre(123, 123, 123)));
1230     EXPECT_LE(v.size(), v.capacity());
1231   }
1232 }
1233 
TYPED_TEST_P(InstanceTest,CountElemAssignInlineBacking)1234 TYPED_TEST_P(InstanceTest, CountElemAssignInlineBacking) {
1235   using Instance = TypeParam;
1236   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1237     SCOPED_TRACE(original_size);
1238     // Original contents are [12345, 12345, ...]
1239     std::vector<Instance> original_contents(original_size, Instance(12345));
1240 
1241     absl::InlinedVector<Instance, 2> v(original_contents.begin(),
1242                                        original_contents.end());
1243     v.assign(2, Instance(123));
1244     EXPECT_THAT(v, AllOf(SizeIs(2), ElementsAre(ValueIs(123), ValueIs(123))));
1245     if (original_size <= 2) {
1246       // If the original had inline backing, it should stay inline.
1247       EXPECT_EQ(2, v.capacity());
1248     }
1249   }
1250 }
1251 
1252 template <typename Instance>
InstanceCountElemAssignWithAllocationTest()1253 void InstanceCountElemAssignWithAllocationTest() {
1254   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1255     SCOPED_TRACE(original_size);
1256     // Original contents are [12345, 12345, ...]
1257     std::vector<Instance> original_contents(original_size, Instance(12345));
1258 
1259     absl::InlinedVector<Instance, 2> v(original_contents.begin(),
1260                                        original_contents.end());
1261     v.assign(3, Instance(123));
1262     EXPECT_THAT(v, AllOf(SizeIs(3), ElementsAre(ValueIs(123), ValueIs(123),
1263                                                 ValueIs(123))));
1264     EXPECT_LE(v.size(), v.capacity());
1265   }
1266 }
TEST(CountElemAssign,WithAllocationCopyableInstance)1267 TEST(CountElemAssign, WithAllocationCopyableInstance) {
1268   InstanceCountElemAssignWithAllocationTest<CopyableOnlyInstance>();
1269 }
TEST(CountElemAssign,WithAllocationCopyableMovableInstance)1270 TEST(CountElemAssign, WithAllocationCopyableMovableInstance) {
1271   InstanceCountElemAssignWithAllocationTest<CopyableMovableInstance>();
1272 }
1273 
TEST(RangedConstructor,SimpleType)1274 TEST(RangedConstructor, SimpleType) {
1275   std::vector<int> source_v = {4, 5, 6};
1276   // First try to fit in inline backing
1277   absl::InlinedVector<int, 4> v(source_v.begin(), source_v.end());
1278   EXPECT_EQ(3, v.size());
1279   EXPECT_EQ(4, v.capacity());  // Indication that we're still on inlined storage
1280   EXPECT_EQ(4, v[0]);
1281   EXPECT_EQ(5, v[1]);
1282   EXPECT_EQ(6, v[2]);
1283 
1284   // Now, force a re-allocate
1285   absl::InlinedVector<int, 2> realloc_v(source_v.begin(), source_v.end());
1286   EXPECT_EQ(3, realloc_v.size());
1287   EXPECT_LT(2, realloc_v.capacity());
1288   EXPECT_EQ(4, realloc_v[0]);
1289   EXPECT_EQ(5, realloc_v[1]);
1290   EXPECT_EQ(6, realloc_v[2]);
1291 }
1292 
1293 // Test for ranged constructors using Instance as the element type and
1294 // SourceContainer as the source container type.
1295 template <typename Instance, typename SourceContainer, int inlined_capacity>
InstanceRangedConstructorTestForContainer()1296 void InstanceRangedConstructorTestForContainer() {
1297   InstanceTracker tracker;
1298   SourceContainer source_v = {Instance(0), Instance(1)};
1299   tracker.ResetCopiesMovesSwaps();
1300   absl::InlinedVector<Instance, inlined_capacity> v(source_v.begin(),
1301                                                     source_v.end());
1302   EXPECT_EQ(2, v.size());
1303   EXPECT_LT(1, v.capacity());
1304   EXPECT_EQ(0, v[0].value());
1305   EXPECT_EQ(1, v[1].value());
1306   EXPECT_EQ(tracker.copies(), 2);
1307   EXPECT_EQ(tracker.moves(), 0);
1308 }
1309 
1310 template <typename Instance, int inlined_capacity>
InstanceRangedConstructorTestWithCapacity()1311 void InstanceRangedConstructorTestWithCapacity() {
1312   // Test with const and non-const, random access and non-random-access sources.
1313   // TODO(bsamwel): Test with an input iterator source.
1314   {
1315     SCOPED_TRACE("std::list");
1316     InstanceRangedConstructorTestForContainer<Instance, std::list<Instance>,
1317                                               inlined_capacity>();
1318     {
1319       SCOPED_TRACE("const std::list");
1320       InstanceRangedConstructorTestForContainer<
1321           Instance, const std::list<Instance>, inlined_capacity>();
1322     }
1323     {
1324       SCOPED_TRACE("std::vector");
1325       InstanceRangedConstructorTestForContainer<Instance, std::vector<Instance>,
1326                                                 inlined_capacity>();
1327     }
1328     {
1329       SCOPED_TRACE("const std::vector");
1330       InstanceRangedConstructorTestForContainer<
1331           Instance, const std::vector<Instance>, inlined_capacity>();
1332     }
1333   }
1334 }
1335 
TYPED_TEST_P(InstanceTest,RangedConstructor)1336 TYPED_TEST_P(InstanceTest, RangedConstructor) {
1337   using Instance = TypeParam;
1338   SCOPED_TRACE("capacity=1");
1339   InstanceRangedConstructorTestWithCapacity<Instance, 1>();
1340   SCOPED_TRACE("capacity=2");
1341   InstanceRangedConstructorTestWithCapacity<Instance, 2>();
1342 }
1343 
TEST(RangedConstructor,ElementsAreConstructed)1344 TEST(RangedConstructor, ElementsAreConstructed) {
1345   std::vector<std::string> source_v = {"cat", "dog"};
1346 
1347   // Force expansion and re-allocation of v.  Ensures that when the vector is
1348   // expanded that new elements are constructed.
1349   absl::InlinedVector<std::string, 1> v(source_v.begin(), source_v.end());
1350   EXPECT_EQ("cat", v[0]);
1351   EXPECT_EQ("dog", v[1]);
1352 }
1353 
TEST(RangedAssign,SimpleType)1354 TEST(RangedAssign, SimpleType) {
1355   // Test for all combinations of original sizes (empty and non-empty inline,
1356   // and out of line) and target sizes.
1357   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1358     SCOPED_TRACE(original_size);
1359     // Original contents are [12345, 12345, ...]
1360     std::vector<int> original_contents(original_size, 12345);
1361 
1362     for (size_t target_size = 0; target_size <= 5; ++target_size) {
1363       SCOPED_TRACE(target_size);
1364 
1365       // New contents are [3, 4, ...]
1366       std::vector<int> new_contents;
1367       for (size_t i = 0; i < target_size; ++i) {
1368         new_contents.push_back(i + 3);
1369       }
1370 
1371       absl::InlinedVector<int, 3> v(original_contents.begin(),
1372                                     original_contents.end());
1373       v.assign(new_contents.begin(), new_contents.end());
1374 
1375       EXPECT_EQ(new_contents.size(), v.size());
1376       EXPECT_LE(new_contents.size(), v.capacity());
1377       if (target_size <= 3 && original_size <= 3) {
1378         // Storage should stay inline when target size is small.
1379         EXPECT_EQ(3, v.capacity());
1380       }
1381       EXPECT_THAT(v, ElementsAreArray(new_contents));
1382     }
1383   }
1384 }
1385 
1386 // Returns true if lhs and rhs have the same value.
1387 template <typename Instance>
InstanceValuesEqual(const Instance & lhs,const Instance & rhs)1388 static bool InstanceValuesEqual(const Instance& lhs, const Instance& rhs) {
1389   return lhs.value() == rhs.value();
1390 }
1391 
1392 // Test for ranged assign() using Instance as the element type and
1393 // SourceContainer as the source container type.
1394 template <typename Instance, typename SourceContainer>
InstanceRangedAssignTestForContainer()1395 void InstanceRangedAssignTestForContainer() {
1396   // Test for all combinations of original sizes (empty and non-empty inline,
1397   // and out of line) and target sizes.
1398   for (size_t original_size = 0; original_size <= 5; ++original_size) {
1399     SCOPED_TRACE(original_size);
1400     // Original contents are [12345, 12345, ...]
1401     std::vector<Instance> original_contents(original_size, Instance(12345));
1402 
1403     for (size_t target_size = 0; target_size <= 5; ++target_size) {
1404       SCOPED_TRACE(target_size);
1405 
1406       // New contents are [3, 4, ...]
1407       // Generate data using a non-const container, because SourceContainer
1408       // itself may be const.
1409       // TODO(bsamwel): Test with an input iterator.
1410       std::vector<Instance> new_contents_in;
1411       for (size_t i = 0; i < target_size; ++i) {
1412         new_contents_in.push_back(Instance(i + 3));
1413       }
1414       SourceContainer new_contents(new_contents_in.begin(),
1415                                    new_contents_in.end());
1416 
1417       absl::InlinedVector<Instance, 3> v(original_contents.begin(),
1418                                          original_contents.end());
1419       v.assign(new_contents.begin(), new_contents.end());
1420 
1421       EXPECT_EQ(new_contents.size(), v.size());
1422       EXPECT_LE(new_contents.size(), v.capacity());
1423       if (target_size <= 3 && original_size <= 3) {
1424         // Storage should stay inline when target size is small.
1425         EXPECT_EQ(3, v.capacity());
1426       }
1427       EXPECT_TRUE(std::equal(v.begin(), v.end(), new_contents.begin(),
1428                              InstanceValuesEqual<Instance>));
1429     }
1430   }
1431 }
1432 
TYPED_TEST_P(InstanceTest,RangedAssign)1433 TYPED_TEST_P(InstanceTest, RangedAssign) {
1434   using Instance = TypeParam;
1435   // Test with const and non-const, random access and non-random-access sources.
1436   // TODO(bsamwel): Test with an input iterator source.
1437   SCOPED_TRACE("std::list");
1438   InstanceRangedAssignTestForContainer<Instance, std::list<Instance>>();
1439   SCOPED_TRACE("const std::list");
1440   InstanceRangedAssignTestForContainer<Instance, const std::list<Instance>>();
1441   SCOPED_TRACE("std::vector");
1442   InstanceRangedAssignTestForContainer<Instance, std::vector<Instance>>();
1443   SCOPED_TRACE("const std::vector");
1444   InstanceRangedAssignTestForContainer<Instance, const std::vector<Instance>>();
1445 }
1446 
TEST(InitializerListConstructor,SimpleTypeWithInlineBacking)1447 TEST(InitializerListConstructor, SimpleTypeWithInlineBacking) {
1448   EXPECT_THAT((absl::InlinedVector<int, 4>{4, 5, 6}),
1449               AllOf(SizeIs(3), CapacityIs(4), ElementsAre(4, 5, 6)));
1450 }
1451 
TEST(InitializerListConstructor,SimpleTypeWithReallocationRequired)1452 TEST(InitializerListConstructor, SimpleTypeWithReallocationRequired) {
1453   EXPECT_THAT((absl::InlinedVector<int, 2>{4, 5, 6}),
1454               AllOf(SizeIs(3), CapacityIs(Gt(2)), ElementsAre(4, 5, 6)));
1455 }
1456 
TEST(InitializerListConstructor,DisparateTypesInList)1457 TEST(InitializerListConstructor, DisparateTypesInList) {
1458   EXPECT_THAT((absl::InlinedVector<int, 2>{-7, 8ULL}), ElementsAre(-7, 8));
1459 
1460   EXPECT_THAT((absl::InlinedVector<std::string, 2>{"foo", std::string("bar")}),
1461               ElementsAre("foo", "bar"));
1462 }
1463 
TEST(InitializerListConstructor,ComplexTypeWithInlineBacking)1464 TEST(InitializerListConstructor, ComplexTypeWithInlineBacking) {
1465   EXPECT_THAT((absl::InlinedVector<CopyableMovableInstance, 1>{
1466                   CopyableMovableInstance(0)}),
1467               AllOf(SizeIs(1), CapacityIs(1), ElementsAre(ValueIs(0))));
1468 }
1469 
TEST(InitializerListConstructor,ComplexTypeWithReallocationRequired)1470 TEST(InitializerListConstructor, ComplexTypeWithReallocationRequired) {
1471   EXPECT_THAT(
1472       (absl::InlinedVector<CopyableMovableInstance, 1>{
1473           CopyableMovableInstance(0), CopyableMovableInstance(1)}),
1474       AllOf(SizeIs(2), CapacityIs(Gt(1)), ElementsAre(ValueIs(0), ValueIs(1))));
1475 }
1476 
TEST(InitializerListAssign,SimpleTypeFitsInlineBacking)1477 TEST(InitializerListAssign, SimpleTypeFitsInlineBacking) {
1478   for (size_t original_size = 0; original_size <= 4; ++original_size) {
1479     SCOPED_TRACE(original_size);
1480 
1481     absl::InlinedVector<int, 2> v1(original_size, 12345);
1482     const size_t original_capacity_v1 = v1.capacity();
1483     v1.assign({3});
1484     EXPECT_THAT(
1485         v1, AllOf(SizeIs(1), CapacityIs(original_capacity_v1), ElementsAre(3)));
1486 
1487     absl::InlinedVector<int, 2> v2(original_size, 12345);
1488     const size_t original_capacity_v2 = v2.capacity();
1489     v2 = {3};
1490     EXPECT_THAT(
1491         v2, AllOf(SizeIs(1), CapacityIs(original_capacity_v2), ElementsAre(3)));
1492   }
1493 }
1494 
TEST(InitializerListAssign,SimpleTypeDoesNotFitInlineBacking)1495 TEST(InitializerListAssign, SimpleTypeDoesNotFitInlineBacking) {
1496   for (size_t original_size = 0; original_size <= 4; ++original_size) {
1497     SCOPED_TRACE(original_size);
1498     absl::InlinedVector<int, 2> v1(original_size, 12345);
1499     v1.assign({3, 4, 5});
1500     EXPECT_THAT(v1, AllOf(SizeIs(3), ElementsAre(3, 4, 5)));
1501     EXPECT_LE(3, v1.capacity());
1502 
1503     absl::InlinedVector<int, 2> v2(original_size, 12345);
1504     v2 = {3, 4, 5};
1505     EXPECT_THAT(v2, AllOf(SizeIs(3), ElementsAre(3, 4, 5)));
1506     EXPECT_LE(3, v2.capacity());
1507   }
1508 }
1509 
TEST(InitializerListAssign,DisparateTypesInList)1510 TEST(InitializerListAssign, DisparateTypesInList) {
1511   absl::InlinedVector<int, 2> v_int1;
1512   v_int1.assign({-7, 8ULL});
1513   EXPECT_THAT(v_int1, ElementsAre(-7, 8));
1514 
1515   absl::InlinedVector<int, 2> v_int2;
1516   v_int2 = {-7, 8ULL};
1517   EXPECT_THAT(v_int2, ElementsAre(-7, 8));
1518 
1519   absl::InlinedVector<std::string, 2> v_string1;
1520   v_string1.assign({"foo", std::string("bar")});
1521   EXPECT_THAT(v_string1, ElementsAre("foo", "bar"));
1522 
1523   absl::InlinedVector<std::string, 2> v_string2;
1524   v_string2 = {"foo", std::string("bar")};
1525   EXPECT_THAT(v_string2, ElementsAre("foo", "bar"));
1526 }
1527 
TYPED_TEST_P(InstanceTest,InitializerListAssign)1528 TYPED_TEST_P(InstanceTest, InitializerListAssign) {
1529   using Instance = TypeParam;
1530   for (size_t original_size = 0; original_size <= 4; ++original_size) {
1531     SCOPED_TRACE(original_size);
1532     absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));
1533     const size_t original_capacity = v.capacity();
1534     v.assign({Instance(3)});
1535     EXPECT_THAT(v, AllOf(SizeIs(1), CapacityIs(original_capacity),
1536                          ElementsAre(ValueIs(3))));
1537   }
1538   for (size_t original_size = 0; original_size <= 4; ++original_size) {
1539     SCOPED_TRACE(original_size);
1540     absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));
1541     v.assign({Instance(3), Instance(4), Instance(5)});
1542     EXPECT_THAT(
1543         v, AllOf(SizeIs(3), ElementsAre(ValueIs(3), ValueIs(4), ValueIs(5))));
1544     EXPECT_LE(3, v.capacity());
1545   }
1546 }
1547 
1548 REGISTER_TYPED_TEST_SUITE_P(InstanceTest, Swap, CountConstructorsDestructors,
1549                             CountConstructorsDestructorsOnCopyConstruction,
1550                             CountConstructorsDestructorsOnMoveConstruction,
1551                             CountConstructorsDestructorsOnAssignment,
1552                             CountConstructorsDestructorsOnMoveAssignment,
1553                             CountElemAssignInlineBacking, RangedConstructor,
1554                             RangedAssign, InitializerListAssign);
1555 
1556 using InstanceTypes =
1557     ::testing::Types<CopyableOnlyInstance, CopyableMovableInstance>;
1558 INSTANTIATE_TYPED_TEST_SUITE_P(InstanceTestOnTypes, InstanceTest,
1559                                InstanceTypes);
1560 
TEST(DynamicVec,DynamicVecCompiles)1561 TEST(DynamicVec, DynamicVecCompiles) {
1562   DynamicVec v;
1563   (void)v;
1564 }
1565 
TEST(AllocatorSupportTest,Constructors)1566 TEST(AllocatorSupportTest, Constructors) {
1567   using MyAlloc = CountingAllocator<int>;
1568   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
1569   const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
1570   int64_t allocated = 0;
1571   MyAlloc alloc(&allocated);
1572   { AllocVec ABSL_ATTRIBUTE_UNUSED v; }
1573   { AllocVec ABSL_ATTRIBUTE_UNUSED v(alloc); }
1574   { AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc); }
1575   { AllocVec ABSL_ATTRIBUTE_UNUSED v({1, 2, 3}, alloc); }
1576 
1577   AllocVec v2;
1578   { AllocVec ABSL_ATTRIBUTE_UNUSED v(v2, alloc); }
1579   { AllocVec ABSL_ATTRIBUTE_UNUSED v(std::move(v2), alloc); }
1580 }
1581 
TEST(AllocatorSupportTest,CountAllocations)1582 TEST(AllocatorSupportTest, CountAllocations) {
1583   using MyAlloc = CountingAllocator<int>;
1584   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
1585   const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
1586   int64_t allocated = 0;
1587   MyAlloc alloc(&allocated);
1588   {
1589     AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + 4, alloc);
1590     EXPECT_THAT(allocated, 0);
1591   }
1592   EXPECT_THAT(allocated, 0);
1593   {
1594     AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc);
1595     EXPECT_THAT(allocated, v.size() * sizeof(int));
1596   }
1597   EXPECT_THAT(allocated, 0);
1598   {
1599     AllocVec v(4, 1, alloc);
1600     EXPECT_THAT(allocated, 0);
1601 
1602     int64_t allocated2 = 0;
1603     MyAlloc alloc2(&allocated2);
1604     AllocVec v2(v, alloc2);
1605     EXPECT_THAT(allocated2, 0);
1606 
1607     int64_t allocated3 = 0;
1608     MyAlloc alloc3(&allocated3);
1609     AllocVec v3(std::move(v), alloc3);
1610     EXPECT_THAT(allocated3, 0);
1611   }
1612   EXPECT_THAT(allocated, 0);
1613   {
1614     AllocVec v(8, 2, alloc);
1615     EXPECT_THAT(allocated, v.size() * sizeof(int));
1616 
1617     int64_t allocated2 = 0;
1618     MyAlloc alloc2(&allocated2);
1619     AllocVec v2(v, alloc2);
1620     EXPECT_THAT(allocated2, v2.size() * sizeof(int));
1621 
1622     int64_t allocated3 = 0;
1623     MyAlloc alloc3(&allocated3);
1624     AllocVec v3(std::move(v), alloc3);
1625     EXPECT_THAT(allocated3, v3.size() * sizeof(int));
1626   }
1627   EXPECT_EQ(allocated, 0);
1628   {
1629     // Test shrink_to_fit deallocations.
1630     AllocVec v(8, 2, alloc);
1631     EXPECT_EQ(allocated, 8 * sizeof(int));
1632     v.resize(5);
1633     EXPECT_EQ(allocated, 8 * sizeof(int));
1634     v.shrink_to_fit();
1635     EXPECT_EQ(allocated, 5 * sizeof(int));
1636     v.resize(4);
1637     EXPECT_EQ(allocated, 5 * sizeof(int));
1638     v.shrink_to_fit();
1639     EXPECT_EQ(allocated, 0);
1640   }
1641 }
1642 
TEST(AllocatorSupportTest,SwapBothAllocated)1643 TEST(AllocatorSupportTest, SwapBothAllocated) {
1644   using MyAlloc = CountingAllocator<int>;
1645   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
1646   int64_t allocated1 = 0;
1647   int64_t allocated2 = 0;
1648   {
1649     const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7};
1650     const int ia2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
1651     MyAlloc a1(&allocated1);
1652     MyAlloc a2(&allocated2);
1653     AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);
1654     AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2);
1655     EXPECT_LT(v1.capacity(), v2.capacity());
1656     EXPECT_THAT(allocated1, v1.capacity() * sizeof(int));
1657     EXPECT_THAT(allocated2, v2.capacity() * sizeof(int));
1658     v1.swap(v2);
1659     EXPECT_THAT(v1, ElementsAreArray(ia2));
1660     EXPECT_THAT(v2, ElementsAreArray(ia1));
1661     EXPECT_THAT(allocated1, v2.capacity() * sizeof(int));
1662     EXPECT_THAT(allocated2, v1.capacity() * sizeof(int));
1663   }
1664   EXPECT_THAT(allocated1, 0);
1665   EXPECT_THAT(allocated2, 0);
1666 }
1667 
TEST(AllocatorSupportTest,SwapOneAllocated)1668 TEST(AllocatorSupportTest, SwapOneAllocated) {
1669   using MyAlloc = CountingAllocator<int>;
1670   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
1671   int64_t allocated1 = 0;
1672   int64_t allocated2 = 0;
1673   {
1674     const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7};
1675     const int ia2[] = {0, 1, 2, 3};
1676     MyAlloc a1(&allocated1);
1677     MyAlloc a2(&allocated2);
1678     AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);
1679     AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2);
1680     EXPECT_THAT(allocated1, v1.capacity() * sizeof(int));
1681     EXPECT_THAT(allocated2, 0);
1682     v1.swap(v2);
1683     EXPECT_THAT(v1, ElementsAreArray(ia2));
1684     EXPECT_THAT(v2, ElementsAreArray(ia1));
1685     EXPECT_THAT(allocated1, v2.capacity() * sizeof(int));
1686     EXPECT_THAT(allocated2, 0);
1687     EXPECT_TRUE(v2.get_allocator() == a1);
1688     EXPECT_TRUE(v1.get_allocator() == a2);
1689   }
1690   EXPECT_THAT(allocated1, 0);
1691   EXPECT_THAT(allocated2, 0);
1692 }
1693 
TEST(AllocatorSupportTest,ScopedAllocatorWorksInlined)1694 TEST(AllocatorSupportTest, ScopedAllocatorWorksInlined) {
1695   using StdVector = std::vector<int, CountingAllocator<int>>;
1696   using Alloc = CountingAllocator<StdVector>;
1697   using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>;
1698   using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>;
1699 
1700   int64_t total_allocated_byte_count = 0;
1701 
1702   AllocVec inlined_case(ScopedAlloc(Alloc(+&total_allocated_byte_count)));
1703 
1704   // Called only once to remain inlined
1705   inlined_case.emplace_back();
1706 
1707   int64_t absl_responsible_for_count = total_allocated_byte_count;
1708 
1709   // MSVC's allocator preemptively allocates in debug mode
1710 #if !defined(_MSC_VER)
1711   EXPECT_EQ(absl_responsible_for_count, 0);
1712 #endif  // !defined(_MSC_VER)
1713 
1714   inlined_case[0].emplace_back();
1715   EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count);
1716 
1717   inlined_case.clear();
1718   inlined_case.shrink_to_fit();
1719   EXPECT_EQ(total_allocated_byte_count, 0);
1720 }
1721 
TEST(AllocatorSupportTest,ScopedAllocatorWorksAllocated)1722 TEST(AllocatorSupportTest, ScopedAllocatorWorksAllocated) {
1723   using StdVector = std::vector<int, CountingAllocator<int>>;
1724   using Alloc = CountingAllocator<StdVector>;
1725   using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>;
1726   using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>;
1727 
1728   int64_t total_allocated_byte_count = 0;
1729 
1730   AllocVec allocated_case(ScopedAlloc(Alloc(+&total_allocated_byte_count)));
1731 
1732   // Called twice to force into being allocated
1733   allocated_case.emplace_back();
1734   allocated_case.emplace_back();
1735 
1736   int64_t absl_responsible_for_count = total_allocated_byte_count;
1737   EXPECT_GT(absl_responsible_for_count, 0);
1738 
1739   allocated_case[1].emplace_back();
1740   EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count);
1741 
1742   allocated_case.clear();
1743   allocated_case.shrink_to_fit();
1744   EXPECT_EQ(total_allocated_byte_count, 0);
1745 }
1746 
TEST(AllocatorSupportTest,SizeAllocConstructor)1747 TEST(AllocatorSupportTest, SizeAllocConstructor) {
1748   constexpr int inlined_size = 4;
1749   using Alloc = CountingAllocator<int>;
1750   using AllocVec = absl::InlinedVector<int, inlined_size, Alloc>;
1751 
1752   {
1753     auto len = inlined_size / 2;
1754     int64_t allocated = 0;
1755     auto v = AllocVec(len, Alloc(&allocated));
1756 
1757     // Inline storage used; allocator should not be invoked
1758     EXPECT_THAT(allocated, 0);
1759     EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
1760   }
1761 
1762   {
1763     auto len = inlined_size * 2;
1764     int64_t allocated = 0;
1765     auto v = AllocVec(len, Alloc(&allocated));
1766 
1767     // Out of line storage used; allocation of 8 elements expected
1768     EXPECT_THAT(allocated, len * sizeof(int));
1769     EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
1770   }
1771 }
1772 
TEST(InlinedVectorTest,MinimumAllocatorCompilesUsingTraits)1773 TEST(InlinedVectorTest, MinimumAllocatorCompilesUsingTraits) {
1774   using T = int;
1775   using A = std::allocator<T>;
1776   using ATraits = absl::allocator_traits<A>;
1777 
1778   struct MinimumAllocator {
1779     using value_type = T;
1780 
1781     value_type* allocate(size_t n) {
1782       A a;
1783       return ATraits::allocate(a, n);
1784     }
1785 
1786     void deallocate(value_type* p, size_t n) {
1787       A a;
1788       ATraits::deallocate(a, p, n);
1789     }
1790   };
1791 
1792   absl::InlinedVector<T, 1, MinimumAllocator> vec;
1793   vec.emplace_back();
1794   vec.resize(0);
1795 }
1796 
TEST(InlinedVectorTest,AbslHashValueWorks)1797 TEST(InlinedVectorTest, AbslHashValueWorks) {
1798   using V = absl::InlinedVector<int, 4>;
1799   std::vector<V> cases;
1800 
1801   // Generate a variety of vectors some of these are small enough for the inline
1802   // space but are stored out of line.
1803   for (int i = 0; i < 10; ++i) {
1804     V v;
1805     for (int j = 0; j < i; ++j) {
1806       v.push_back(j);
1807     }
1808     cases.push_back(v);
1809     v.resize(i % 4);
1810     cases.push_back(v);
1811   }
1812 
1813   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
1814 }
1815 
1816 }  // anonymous namespace
1817