inlined_vector_test.cc
Go to the documentation of this file.
00001 // Copyright 2017 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
00014 
00015 #include "absl/container/inlined_vector.h"
00016 
00017 #include <algorithm>
00018 #include <forward_list>
00019 #include <list>
00020 #include <memory>
00021 #include <scoped_allocator>
00022 #include <sstream>
00023 #include <stdexcept>
00024 #include <string>
00025 #include <vector>
00026 
00027 #include "gmock/gmock.h"
00028 #include "gtest/gtest.h"
00029 #include "absl/base/attributes.h"
00030 #include "absl/base/internal/exception_testing.h"
00031 #include "absl/base/internal/raw_logging.h"
00032 #include "absl/base/macros.h"
00033 #include "absl/container/internal/counting_allocator.h"
00034 #include "absl/container/internal/test_instance_tracker.h"
00035 #include "absl/hash/hash_testing.h"
00036 #include "absl/memory/memory.h"
00037 #include "absl/strings/str_cat.h"
00038 
00039 namespace {
00040 
00041 using absl::container_internal::CountingAllocator;
00042 using absl::test_internal::CopyableMovableInstance;
00043 using absl::test_internal::CopyableOnlyInstance;
00044 using absl::test_internal::InstanceTracker;
00045 using testing::AllOf;
00046 using testing::Each;
00047 using testing::ElementsAre;
00048 using testing::ElementsAreArray;
00049 using testing::Eq;
00050 using testing::Gt;
00051 using testing::PrintToString;
00052 
00053 using IntVec = absl::InlinedVector<int, 8>;
00054 
00055 MATCHER_P(SizeIs, n, "") {
00056   return testing::ExplainMatchResult(n, arg.size(), result_listener);
00057 }
00058 
00059 MATCHER_P(CapacityIs, n, "") {
00060   return testing::ExplainMatchResult(n, arg.capacity(), result_listener);
00061 }
00062 
00063 MATCHER_P(ValueIs, e, "") {
00064   return testing::ExplainMatchResult(e, arg.value(), result_listener);
00065 }
00066 
00067 // TODO(bsamwel): Add support for movable-only types.
00068 
00069 // Test fixture for typed tests on BaseCountedInstance derived classes, see
00070 // test_instance_tracker.h.
00071 template <typename T>
00072 class InstanceTest : public ::testing::Test {};
00073 TYPED_TEST_SUITE_P(InstanceTest);
00074 
00075 // A simple reference counted class to make sure that the proper elements are
00076 // destroyed in the erase(begin, end) test.
00077 class RefCounted {
00078  public:
00079   RefCounted(int value, int* count) : value_(value), count_(count) {
00080     Ref();
00081   }
00082 
00083   RefCounted(const RefCounted& v)
00084       : value_(v.value_), count_(v.count_) {
00085     Ref();
00086   }
00087 
00088   ~RefCounted() {
00089     Unref();
00090     count_ = nullptr;
00091   }
00092 
00093   friend void swap(RefCounted& a, RefCounted& b) {
00094     using std::swap;
00095     swap(a.value_, b.value_);
00096     swap(a.count_, b.count_);
00097   }
00098 
00099   RefCounted& operator=(RefCounted v) {
00100     using std::swap;
00101     swap(*this, v);
00102     return *this;
00103   }
00104 
00105   void Ref() const {
00106     ABSL_RAW_CHECK(count_ != nullptr, "");
00107     ++(*count_);
00108   }
00109 
00110   void Unref() const {
00111     --(*count_);
00112     ABSL_RAW_CHECK(*count_ >= 0, "");
00113   }
00114 
00115   int value_;
00116   int* count_;
00117 };
00118 
00119 using RefCountedVec = absl::InlinedVector<RefCounted, 8>;
00120 
00121 // A class with a vtable pointer
00122 class Dynamic {
00123  public:
00124   virtual ~Dynamic() {}
00125 };
00126 
00127 using DynamicVec = absl::InlinedVector<Dynamic, 8>;
00128 
00129 // Append 0..len-1 to *v
00130 template <typename Container>
00131 static void Fill(Container* v, int len, int offset = 0) {
00132   for (int i = 0; i < len; i++) {
00133     v->push_back(i + offset);
00134   }
00135 }
00136 
00137 static IntVec Fill(int len, int offset = 0) {
00138   IntVec v;
00139   Fill(&v, len, offset);
00140   return v;
00141 }
00142 
00143 TEST(IntVec, SimpleOps) {
00144   for (int len = 0; len < 20; len++) {
00145     IntVec v;
00146     const IntVec& cv = v;  // const alias
00147 
00148     Fill(&v, len);
00149     EXPECT_EQ(len, v.size());
00150     EXPECT_LE(len, v.capacity());
00151 
00152     for (int i = 0; i < len; i++) {
00153       EXPECT_EQ(i, v[i]);
00154       EXPECT_EQ(i, v.at(i));
00155     }
00156     EXPECT_EQ(v.begin(), v.data());
00157     EXPECT_EQ(cv.begin(), cv.data());
00158 
00159     int counter = 0;
00160     for (IntVec::iterator iter = v.begin(); iter != v.end(); ++iter) {
00161       EXPECT_EQ(counter, *iter);
00162       counter++;
00163     }
00164     EXPECT_EQ(counter, len);
00165 
00166     counter = 0;
00167     for (IntVec::const_iterator iter = v.begin(); iter != v.end(); ++iter) {
00168       EXPECT_EQ(counter, *iter);
00169       counter++;
00170     }
00171     EXPECT_EQ(counter, len);
00172 
00173     counter = 0;
00174     for (IntVec::const_iterator iter = v.cbegin(); iter != v.cend(); ++iter) {
00175       EXPECT_EQ(counter, *iter);
00176       counter++;
00177     }
00178     EXPECT_EQ(counter, len);
00179 
00180     if (len > 0) {
00181       EXPECT_EQ(0, v.front());
00182       EXPECT_EQ(len - 1, v.back());
00183       v.pop_back();
00184       EXPECT_EQ(len - 1, v.size());
00185       for (int i = 0; i < v.size(); ++i) {
00186         EXPECT_EQ(i, v[i]);
00187         EXPECT_EQ(i, v.at(i));
00188       }
00189     }
00190   }
00191 }
00192 
00193 TEST(IntVec, AtThrows) {
00194   IntVec v = {1, 2, 3};
00195   EXPECT_EQ(v.at(2), 3);
00196   ABSL_BASE_INTERNAL_EXPECT_FAIL(v.at(3), std::out_of_range,
00197                                  "failed bounds check");
00198 }
00199 
00200 TEST(IntVec, ReverseIterator) {
00201   for (int len = 0; len < 20; len++) {
00202     IntVec v;
00203     Fill(&v, len);
00204 
00205     int counter = len;
00206     for (IntVec::reverse_iterator iter = v.rbegin(); iter != v.rend(); ++iter) {
00207       counter--;
00208       EXPECT_EQ(counter, *iter);
00209     }
00210     EXPECT_EQ(counter, 0);
00211 
00212     counter = len;
00213     for (IntVec::const_reverse_iterator iter = v.rbegin(); iter != v.rend();
00214          ++iter) {
00215       counter--;
00216       EXPECT_EQ(counter, *iter);
00217     }
00218     EXPECT_EQ(counter, 0);
00219 
00220     counter = len;
00221     for (IntVec::const_reverse_iterator iter = v.crbegin(); iter != v.crend();
00222          ++iter) {
00223       counter--;
00224       EXPECT_EQ(counter, *iter);
00225     }
00226     EXPECT_EQ(counter, 0);
00227   }
00228 }
00229 
00230 TEST(IntVec, Erase) {
00231   for (int len = 1; len < 20; len++) {
00232     for (int i = 0; i < len; ++i) {
00233       IntVec v;
00234       Fill(&v, len);
00235       v.erase(v.begin() + i);
00236       EXPECT_EQ(len - 1, v.size());
00237       for (int j = 0; j < i; ++j) {
00238         EXPECT_EQ(j, v[j]);
00239       }
00240       for (int j = i; j < len - 1; ++j) {
00241         EXPECT_EQ(j + 1, v[j]);
00242       }
00243     }
00244   }
00245 }
00246 
00247 // At the end of this test loop, the elements between [erase_begin, erase_end)
00248 // should have reference counts == 0, and all others elements should have
00249 // reference counts == 1.
00250 TEST(RefCountedVec, EraseBeginEnd) {
00251   for (int len = 1; len < 20; ++len) {
00252     for (int erase_begin = 0; erase_begin < len; ++erase_begin) {
00253       for (int erase_end = erase_begin; erase_end <= len; ++erase_end) {
00254         std::vector<int> counts(len, 0);
00255         RefCountedVec v;
00256         for (int i = 0; i < len; ++i) {
00257           v.push_back(RefCounted(i, &counts[i]));
00258         }
00259 
00260         int erase_len = erase_end - erase_begin;
00261 
00262         v.erase(v.begin() + erase_begin, v.begin() + erase_end);
00263 
00264         EXPECT_EQ(len - erase_len, v.size());
00265 
00266         // Check the elements before the first element erased.
00267         for (int i = 0; i < erase_begin; ++i) {
00268           EXPECT_EQ(i, v[i].value_);
00269         }
00270 
00271         // Check the elements after the first element erased.
00272         for (int i = erase_begin; i < v.size(); ++i) {
00273           EXPECT_EQ(i + erase_len, v[i].value_);
00274         }
00275 
00276         // Check that the elements at the beginning are preserved.
00277         for (int i = 0; i < erase_begin; ++i) {
00278           EXPECT_EQ(1, counts[i]);
00279         }
00280 
00281         // Check that the erased elements are destroyed
00282         for (int i = erase_begin; i < erase_end; ++i) {
00283           EXPECT_EQ(0, counts[i]);
00284         }
00285 
00286         // Check that the elements at the end are preserved.
00287         for (int i = erase_end; i< len; ++i) {
00288           EXPECT_EQ(1, counts[i]);
00289         }
00290       }
00291     }
00292   }
00293 }
00294 
00295 struct NoDefaultCtor {
00296   explicit NoDefaultCtor(int) {}
00297 };
00298 struct NoCopy {
00299   NoCopy() {}
00300   NoCopy(const NoCopy&) = delete;
00301 };
00302 struct NoAssign {
00303   NoAssign() {}
00304   NoAssign& operator=(const NoAssign&) = delete;
00305 };
00306 struct MoveOnly {
00307   MoveOnly() {}
00308   MoveOnly(MoveOnly&&) = default;
00309   MoveOnly& operator=(MoveOnly&&) = default;
00310 };
00311 TEST(InlinedVectorTest, NoDefaultCtor) {
00312   absl::InlinedVector<NoDefaultCtor, 1> v(10, NoDefaultCtor(2));
00313   (void)v;
00314 }
00315 TEST(InlinedVectorTest, NoCopy) {
00316   absl::InlinedVector<NoCopy, 1> v(10);
00317   (void)v;
00318 }
00319 TEST(InlinedVectorTest, NoAssign) {
00320   absl::InlinedVector<NoAssign, 1> v(10);
00321   (void)v;
00322 }
00323 TEST(InlinedVectorTest, MoveOnly) {
00324   absl::InlinedVector<MoveOnly, 2> v;
00325   v.push_back(MoveOnly{});
00326   v.push_back(MoveOnly{});
00327   v.push_back(MoveOnly{});
00328   v.erase(v.begin());
00329   v.push_back(MoveOnly{});
00330   v.erase(v.begin(), v.begin() + 1);
00331   v.insert(v.begin(), MoveOnly{});
00332   v.emplace(v.begin());
00333   v.emplace(v.begin(), MoveOnly{});
00334 }
00335 TEST(InlinedVectorTest, Noexcept) {
00336   EXPECT_TRUE(std::is_nothrow_move_constructible<IntVec>::value);
00337   EXPECT_TRUE((std::is_nothrow_move_constructible<
00338                absl::InlinedVector<MoveOnly, 2>>::value));
00339 
00340   struct MoveCanThrow {
00341     MoveCanThrow(MoveCanThrow&&) {}
00342   };
00343   EXPECT_EQ(absl::default_allocator_is_nothrow::value,
00344             (std::is_nothrow_move_constructible<
00345                 absl::InlinedVector<MoveCanThrow, 2>>::value));
00346 }
00347 
00348 TEST(InlinedVectorTest, EmplaceBack) {
00349   absl::InlinedVector<std::pair<std::string, int>, 1> v;
00350 
00351   auto& inlined_element = v.emplace_back("answer", 42);
00352   EXPECT_EQ(&inlined_element, &v[0]);
00353   EXPECT_EQ(inlined_element.first, "answer");
00354   EXPECT_EQ(inlined_element.second, 42);
00355 
00356   auto& allocated_element = v.emplace_back("taxicab", 1729);
00357   EXPECT_EQ(&allocated_element, &v[1]);
00358   EXPECT_EQ(allocated_element.first, "taxicab");
00359   EXPECT_EQ(allocated_element.second, 1729);
00360 }
00361 
00362 TEST(InlinedVectorTest, ShrinkToFitGrowingVector) {
00363   absl::InlinedVector<std::pair<std::string, int>, 1> v;
00364 
00365   v.shrink_to_fit();
00366   EXPECT_EQ(v.capacity(), 1);
00367 
00368   v.emplace_back("answer", 42);
00369   v.shrink_to_fit();
00370   EXPECT_EQ(v.capacity(), 1);
00371 
00372   v.emplace_back("taxicab", 1729);
00373   EXPECT_GE(v.capacity(), 2);
00374   v.shrink_to_fit();
00375   EXPECT_EQ(v.capacity(), 2);
00376 
00377   v.reserve(100);
00378   EXPECT_GE(v.capacity(), 100);
00379   v.shrink_to_fit();
00380   EXPECT_EQ(v.capacity(), 2);
00381 }
00382 
00383 TEST(InlinedVectorTest, ShrinkToFitEdgeCases) {
00384   {
00385     absl::InlinedVector<std::pair<std::string, int>, 1> v;
00386     v.emplace_back("answer", 42);
00387     v.emplace_back("taxicab", 1729);
00388     EXPECT_GE(v.capacity(), 2);
00389     v.pop_back();
00390     v.shrink_to_fit();
00391     EXPECT_EQ(v.capacity(), 1);
00392     EXPECT_EQ(v[0].first, "answer");
00393     EXPECT_EQ(v[0].second, 42);
00394   }
00395 
00396   {
00397     absl::InlinedVector<std::string, 2> v(100);
00398     v.resize(0);
00399     v.shrink_to_fit();
00400     EXPECT_EQ(v.capacity(), 2);  // inlined capacity
00401   }
00402 
00403   {
00404     absl::InlinedVector<std::string, 2> v(100);
00405     v.resize(1);
00406     v.shrink_to_fit();
00407     EXPECT_EQ(v.capacity(), 2);  // inlined capacity
00408   }
00409 
00410   {
00411     absl::InlinedVector<std::string, 2> v(100);
00412     v.resize(2);
00413     v.shrink_to_fit();
00414     EXPECT_EQ(v.capacity(), 2);
00415   }
00416 
00417   {
00418     absl::InlinedVector<std::string, 2> v(100);
00419     v.resize(3);
00420     v.shrink_to_fit();
00421     EXPECT_EQ(v.capacity(), 3);
00422   }
00423 }
00424 
00425 TEST(IntVec, Insert) {
00426   for (int len = 0; len < 20; len++) {
00427     for (int pos = 0; pos <= len; pos++) {
00428       {
00429         // Single element
00430         std::vector<int> std_v;
00431         Fill(&std_v, len);
00432         IntVec v;
00433         Fill(&v, len);
00434 
00435         std_v.insert(std_v.begin() + pos, 9999);
00436         IntVec::iterator it = v.insert(v.cbegin() + pos, 9999);
00437         EXPECT_THAT(v, ElementsAreArray(std_v));
00438         EXPECT_EQ(it, v.cbegin() + pos);
00439       }
00440       {
00441         // n elements
00442         std::vector<int> std_v;
00443         Fill(&std_v, len);
00444         IntVec v;
00445         Fill(&v, len);
00446 
00447         IntVec::size_type n = 5;
00448         std_v.insert(std_v.begin() + pos, n, 9999);
00449         IntVec::iterator it = v.insert(v.cbegin() + pos, n, 9999);
00450         EXPECT_THAT(v, ElementsAreArray(std_v));
00451         EXPECT_EQ(it, v.cbegin() + pos);
00452       }
00453       {
00454         // Iterator range (random access iterator)
00455         std::vector<int> std_v;
00456         Fill(&std_v, len);
00457         IntVec v;
00458         Fill(&v, len);
00459 
00460         const std::vector<int> input = {9999, 8888, 7777};
00461         std_v.insert(std_v.begin() + pos, input.cbegin(), input.cend());
00462         IntVec::iterator it =
00463             v.insert(v.cbegin() + pos, input.cbegin(), input.cend());
00464         EXPECT_THAT(v, ElementsAreArray(std_v));
00465         EXPECT_EQ(it, v.cbegin() + pos);
00466       }
00467       {
00468         // Iterator range (forward iterator)
00469         std::vector<int> std_v;
00470         Fill(&std_v, len);
00471         IntVec v;
00472         Fill(&v, len);
00473 
00474         const std::forward_list<int> input = {9999, 8888, 7777};
00475         std_v.insert(std_v.begin() + pos, input.cbegin(), input.cend());
00476         IntVec::iterator it =
00477             v.insert(v.cbegin() + pos, input.cbegin(), input.cend());
00478         EXPECT_THAT(v, ElementsAreArray(std_v));
00479         EXPECT_EQ(it, v.cbegin() + pos);
00480       }
00481       {
00482         // Iterator range (input iterator)
00483         std::vector<int> std_v;
00484         Fill(&std_v, len);
00485         IntVec v;
00486         Fill(&v, len);
00487 
00488         std_v.insert(std_v.begin() + pos, {9999, 8888, 7777});
00489         std::istringstream input("9999 8888 7777");
00490         IntVec::iterator it =
00491             v.insert(v.cbegin() + pos, std::istream_iterator<int>(input),
00492                      std::istream_iterator<int>());
00493         EXPECT_THAT(v, ElementsAreArray(std_v));
00494         EXPECT_EQ(it, v.cbegin() + pos);
00495       }
00496       {
00497         // Initializer list
00498         std::vector<int> std_v;
00499         Fill(&std_v, len);
00500         IntVec v;
00501         Fill(&v, len);
00502 
00503         std_v.insert(std_v.begin() + pos, {9999, 8888});
00504         IntVec::iterator it = v.insert(v.cbegin() + pos, {9999, 8888});
00505         EXPECT_THAT(v, ElementsAreArray(std_v));
00506         EXPECT_EQ(it, v.cbegin() + pos);
00507       }
00508     }
00509   }
00510 }
00511 
00512 TEST(RefCountedVec, InsertConstructorDestructor) {
00513   // Make sure the proper construction/destruction happen during insert
00514   // operations.
00515   for (int len = 0; len < 20; len++) {
00516     SCOPED_TRACE(len);
00517     for (int pos = 0; pos <= len; pos++) {
00518       SCOPED_TRACE(pos);
00519       std::vector<int> counts(len, 0);
00520       int inserted_count = 0;
00521       RefCountedVec v;
00522       for (int i = 0; i < len; ++i) {
00523         SCOPED_TRACE(i);
00524         v.push_back(RefCounted(i, &counts[i]));
00525       }
00526 
00527       EXPECT_THAT(counts, Each(Eq(1)));
00528 
00529       RefCounted insert_element(9999, &inserted_count);
00530       EXPECT_EQ(1, inserted_count);
00531       v.insert(v.begin() + pos, insert_element);
00532       EXPECT_EQ(2, inserted_count);
00533       // Check that the elements at the end are preserved.
00534       EXPECT_THAT(counts, Each(Eq(1)));
00535       EXPECT_EQ(2, inserted_count);
00536     }
00537   }
00538 }
00539 
00540 TEST(IntVec, Resize) {
00541   for (int len = 0; len < 20; len++) {
00542     IntVec v;
00543     Fill(&v, len);
00544 
00545     // Try resizing up and down by k elements
00546     static const int kResizeElem = 1000000;
00547     for (int k = 0; k < 10; k++) {
00548       // Enlarging resize
00549       v.resize(len+k, kResizeElem);
00550       EXPECT_EQ(len+k, v.size());
00551       EXPECT_LE(len+k, v.capacity());
00552       for (int i = 0; i < len+k; i++) {
00553         if (i < len) {
00554           EXPECT_EQ(i, v[i]);
00555         } else {
00556           EXPECT_EQ(kResizeElem, v[i]);
00557         }
00558       }
00559 
00560       // Shrinking resize
00561       v.resize(len, kResizeElem);
00562       EXPECT_EQ(len, v.size());
00563       EXPECT_LE(len, v.capacity());
00564       for (int i = 0; i < len; i++) {
00565         EXPECT_EQ(i, v[i]);
00566       }
00567     }
00568   }
00569 }
00570 
00571 TEST(IntVec, InitWithLength) {
00572   for (int len = 0; len < 20; len++) {
00573     IntVec v(len, 7);
00574     EXPECT_EQ(len, v.size());
00575     EXPECT_LE(len, v.capacity());
00576     for (int i = 0; i < len; i++) {
00577       EXPECT_EQ(7, v[i]);
00578     }
00579   }
00580 }
00581 
00582 TEST(IntVec, CopyConstructorAndAssignment) {
00583   for (int len = 0; len < 20; len++) {
00584     IntVec v;
00585     Fill(&v, len);
00586     EXPECT_EQ(len, v.size());
00587     EXPECT_LE(len, v.capacity());
00588 
00589     IntVec v2(v);
00590     EXPECT_TRUE(v == v2) << PrintToString(v) << PrintToString(v2);
00591 
00592     for (int start_len = 0; start_len < 20; start_len++) {
00593       IntVec v3;
00594       Fill(&v3, start_len, 99);  // Add dummy elements that should go away
00595       v3 = v;
00596       EXPECT_TRUE(v == v3) << PrintToString(v) << PrintToString(v3);
00597     }
00598   }
00599 }
00600 
00601 TEST(IntVec, AliasingCopyAssignment) {
00602   for (int len = 0; len < 20; ++len) {
00603     IntVec original;
00604     Fill(&original, len);
00605     IntVec dup = original;
00606     dup = *&dup;
00607     EXPECT_EQ(dup, original);
00608   }
00609 }
00610 
00611 TEST(IntVec, MoveConstructorAndAssignment) {
00612   for (int len = 0; len < 20; len++) {
00613     IntVec v_in;
00614     const int inlined_capacity = v_in.capacity();
00615     Fill(&v_in, len);
00616     EXPECT_EQ(len, v_in.size());
00617     EXPECT_LE(len, v_in.capacity());
00618 
00619     {
00620       IntVec v_temp(v_in);
00621       auto* old_data = v_temp.data();
00622       IntVec v_out(std::move(v_temp));
00623       EXPECT_TRUE(v_in == v_out) << PrintToString(v_in) << PrintToString(v_out);
00624       if (v_in.size() > inlined_capacity) {
00625         // Allocation is moved as a whole, data stays in place.
00626         EXPECT_TRUE(v_out.data() == old_data);
00627       } else {
00628         EXPECT_FALSE(v_out.data() == old_data);
00629       }
00630     }
00631     for (int start_len = 0; start_len < 20; start_len++) {
00632       IntVec v_out;
00633       Fill(&v_out, start_len, 99);  // Add dummy elements that should go away
00634       IntVec v_temp(v_in);
00635       auto* old_data = v_temp.data();
00636       v_out = std::move(v_temp);
00637       EXPECT_TRUE(v_in == v_out) << PrintToString(v_in) << PrintToString(v_out);
00638       if (v_in.size() > inlined_capacity) {
00639         // Allocation is moved as a whole, data stays in place.
00640         EXPECT_TRUE(v_out.data() == old_data);
00641       } else {
00642         EXPECT_FALSE(v_out.data() == old_data);
00643       }
00644     }
00645   }
00646 }
00647 
00648 class NotTriviallyDestructible {
00649  public:
00650   NotTriviallyDestructible() : p_(new int(1)) {}
00651   explicit NotTriviallyDestructible(int i) : p_(new int(i)) {}
00652 
00653   NotTriviallyDestructible(const NotTriviallyDestructible& other)
00654       : p_(new int(*other.p_)) {}
00655 
00656   NotTriviallyDestructible& operator=(const NotTriviallyDestructible& other) {
00657     p_ = absl::make_unique<int>(*other.p_);
00658     return *this;
00659   }
00660 
00661   bool operator==(const NotTriviallyDestructible& other) const {
00662     return *p_ == *other.p_;
00663   }
00664 
00665  private:
00666   std::unique_ptr<int> p_;
00667 };
00668 
00669 TEST(AliasingTest, Emplace) {
00670   for (int i = 2; i < 20; ++i) {
00671     absl::InlinedVector<NotTriviallyDestructible, 10> vec;
00672     for (int j = 0; j < i; ++j) {
00673       vec.push_back(NotTriviallyDestructible(j));
00674     }
00675     vec.emplace(vec.begin(), vec[0]);
00676     EXPECT_EQ(vec[0], vec[1]);
00677     vec.emplace(vec.begin() + i / 2, vec[i / 2]);
00678     EXPECT_EQ(vec[i / 2], vec[i / 2 + 1]);
00679     vec.emplace(vec.end() - 1, vec.back());
00680     EXPECT_EQ(vec[vec.size() - 2], vec.back());
00681   }
00682 }
00683 
00684 TEST(AliasingTest, InsertWithCount) {
00685   for (int i = 1; i < 20; ++i) {
00686     absl::InlinedVector<NotTriviallyDestructible, 10> vec;
00687     for (int j = 0; j < i; ++j) {
00688       vec.push_back(NotTriviallyDestructible(j));
00689     }
00690     for (int n = 0; n < 5; ++n) {
00691       // We use back where we can because it's guaranteed to become invalidated
00692       vec.insert(vec.begin(), n, vec.back());
00693       auto b = vec.begin();
00694       EXPECT_TRUE(
00695           std::all_of(b, b + n, [&vec](const NotTriviallyDestructible& x) {
00696             return x == vec.back();
00697           }));
00698 
00699       auto m_idx = vec.size() / 2;
00700       vec.insert(vec.begin() + m_idx, n, vec.back());
00701       auto m = vec.begin() + m_idx;
00702       EXPECT_TRUE(
00703           std::all_of(m, m + n, [&vec](const NotTriviallyDestructible& x) {
00704             return x == vec.back();
00705           }));
00706 
00707       // We want distinct values so the equality test is meaningful,
00708       // vec[vec.size() - 1] is also almost always invalidated.
00709       auto old_e = vec.size() - 1;
00710       auto val = vec[old_e];
00711       vec.insert(vec.end(), n, vec[old_e]);
00712       auto e = vec.begin() + old_e;
00713       EXPECT_TRUE(std::all_of(
00714           e, e + n,
00715           [&val](const NotTriviallyDestructible& x) { return x == val; }));
00716     }
00717   }
00718 }
00719 
00720 TEST(OverheadTest, Storage) {
00721   // Check for size overhead.
00722   // In particular, ensure that std::allocator doesn't cost anything to store.
00723   // The union should be absorbing some of the allocation bookkeeping overhead
00724   // in the larger vectors, leaving only the size_ field as overhead.
00725   EXPECT_EQ(2 * sizeof(int*),
00726             sizeof(absl::InlinedVector<int*, 1>) - 1 * sizeof(int*));
00727   EXPECT_EQ(1 * sizeof(int*),
00728             sizeof(absl::InlinedVector<int*, 2>) - 2 * sizeof(int*));
00729   EXPECT_EQ(1 * sizeof(int*),
00730             sizeof(absl::InlinedVector<int*, 3>) - 3 * sizeof(int*));
00731   EXPECT_EQ(1 * sizeof(int*),
00732             sizeof(absl::InlinedVector<int*, 4>) - 4 * sizeof(int*));
00733   EXPECT_EQ(1 * sizeof(int*),
00734             sizeof(absl::InlinedVector<int*, 5>) - 5 * sizeof(int*));
00735   EXPECT_EQ(1 * sizeof(int*),
00736             sizeof(absl::InlinedVector<int*, 6>) - 6 * sizeof(int*));
00737   EXPECT_EQ(1 * sizeof(int*),
00738             sizeof(absl::InlinedVector<int*, 7>) - 7 * sizeof(int*));
00739   EXPECT_EQ(1 * sizeof(int*),
00740             sizeof(absl::InlinedVector<int*, 8>) - 8 * sizeof(int*));
00741 }
00742 
00743 TEST(IntVec, Clear) {
00744   for (int len = 0; len < 20; len++) {
00745     SCOPED_TRACE(len);
00746     IntVec v;
00747     Fill(&v, len);
00748     v.clear();
00749     EXPECT_EQ(0, v.size());
00750     EXPECT_EQ(v.begin(), v.end());
00751   }
00752 }
00753 
00754 TEST(IntVec, Reserve) {
00755   for (int len = 0; len < 20; len++) {
00756     IntVec v;
00757     Fill(&v, len);
00758 
00759     for (int newlen = 0; newlen < 100; newlen++) {
00760       const int* start_rep = v.data();
00761       v.reserve(newlen);
00762       const int* final_rep = v.data();
00763       if (newlen <= len) {
00764         EXPECT_EQ(start_rep, final_rep);
00765       }
00766       EXPECT_LE(newlen, v.capacity());
00767 
00768       // Filling up to newlen should not change rep
00769       while (v.size() < newlen) {
00770         v.push_back(0);
00771       }
00772       EXPECT_EQ(final_rep, v.data());
00773     }
00774   }
00775 }
00776 
00777 TEST(StringVec, SelfRefPushBack) {
00778   std::vector<std::string> std_v;
00779   absl::InlinedVector<std::string, 4> v;
00780   const std::string s = "A quite long std::string to ensure heap.";
00781   std_v.push_back(s);
00782   v.push_back(s);
00783   for (int i = 0; i < 20; ++i) {
00784     EXPECT_THAT(v, ElementsAreArray(std_v));
00785 
00786     v.push_back(v.back());
00787     std_v.push_back(std_v.back());
00788   }
00789   EXPECT_THAT(v, ElementsAreArray(std_v));
00790 }
00791 
00792 TEST(StringVec, SelfRefPushBackWithMove) {
00793   std::vector<std::string> std_v;
00794   absl::InlinedVector<std::string, 4> v;
00795   const std::string s = "A quite long std::string to ensure heap.";
00796   std_v.push_back(s);
00797   v.push_back(s);
00798   for (int i = 0; i < 20; ++i) {
00799     EXPECT_EQ(v.back(), std_v.back());
00800 
00801     v.push_back(std::move(v.back()));
00802     std_v.push_back(std::move(std_v.back()));
00803   }
00804   EXPECT_EQ(v.back(), std_v.back());
00805 }
00806 
00807 TEST(StringVec, SelfMove) {
00808   const std::string s = "A quite long std::string to ensure heap.";
00809   for (int len = 0; len < 20; len++) {
00810     SCOPED_TRACE(len);
00811     absl::InlinedVector<std::string, 8> v;
00812     for (int i = 0; i < len; ++i) {
00813       SCOPED_TRACE(i);
00814       v.push_back(s);
00815     }
00816     // Indirection necessary to avoid compiler warning.
00817     v = std::move(*(&v));
00818     // Ensure that the inlined vector is still in a valid state by copying it.
00819     // We don't expect specific contents since a self-move results in an
00820     // unspecified valid state.
00821     std::vector<std::string> copy(v.begin(), v.end());
00822   }
00823 }
00824 
00825 TEST(IntVec, Swap) {
00826   for (int l1 = 0; l1 < 20; l1++) {
00827     SCOPED_TRACE(l1);
00828     for (int l2 = 0; l2 < 20; l2++) {
00829       SCOPED_TRACE(l2);
00830       IntVec a = Fill(l1, 0);
00831       IntVec b = Fill(l2, 100);
00832       {
00833         using std::swap;
00834         swap(a, b);
00835       }
00836       EXPECT_EQ(l1, b.size());
00837       EXPECT_EQ(l2, a.size());
00838       for (int i = 0; i < l1; i++) {
00839         SCOPED_TRACE(i);
00840         EXPECT_EQ(i, b[i]);
00841       }
00842       for (int i = 0; i < l2; i++) {
00843         SCOPED_TRACE(i);
00844         EXPECT_EQ(100 + i, a[i]);
00845       }
00846     }
00847   }
00848 }
00849 
00850 TYPED_TEST_P(InstanceTest, Swap) {
00851   using Instance = TypeParam;
00852   using InstanceVec = absl::InlinedVector<Instance, 8>;
00853   for (int l1 = 0; l1 < 20; l1++) {
00854     SCOPED_TRACE(l1);
00855     for (int l2 = 0; l2 < 20; l2++) {
00856       SCOPED_TRACE(l2);
00857       InstanceTracker tracker;
00858       InstanceVec a, b;
00859       const size_t inlined_capacity = a.capacity();
00860       auto min_len = std::min(l1, l2);
00861       auto max_len = std::max(l1, l2);
00862       for (int i = 0; i < l1; i++) a.push_back(Instance(i));
00863       for (int i = 0; i < l2; i++) b.push_back(Instance(100+i));
00864       EXPECT_EQ(tracker.instances(), l1 + l2);
00865       tracker.ResetCopiesMovesSwaps();
00866       {
00867         using std::swap;
00868         swap(a, b);
00869       }
00870       EXPECT_EQ(tracker.instances(), l1 + l2);
00871       if (a.size() > inlined_capacity && b.size() > inlined_capacity) {
00872         EXPECT_EQ(tracker.swaps(), 0);  // Allocations are swapped.
00873         EXPECT_EQ(tracker.moves(), 0);
00874       } else if (a.size() <= inlined_capacity && b.size() <= inlined_capacity) {
00875         EXPECT_EQ(tracker.swaps(), min_len);
00876         EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
00877                   max_len - min_len);
00878       } else {
00879         // One is allocated and the other isn't. The allocation is transferred
00880         // without copying elements, and the inlined instances are copied/moved.
00881         EXPECT_EQ(tracker.swaps(), 0);
00882         EXPECT_EQ((tracker.moves() ? tracker.moves() : tracker.copies()),
00883                   min_len);
00884       }
00885 
00886       EXPECT_EQ(l1, b.size());
00887       EXPECT_EQ(l2, a.size());
00888       for (int i = 0; i < l1; i++) {
00889         EXPECT_EQ(i, b[i].value());
00890       }
00891       for (int i = 0; i < l2; i++) {
00892         EXPECT_EQ(100 + i, a[i].value());
00893       }
00894     }
00895   }
00896 }
00897 
00898 TEST(IntVec, EqualAndNotEqual) {
00899   IntVec a, b;
00900   EXPECT_TRUE(a == b);
00901   EXPECT_FALSE(a != b);
00902 
00903   a.push_back(3);
00904   EXPECT_FALSE(a == b);
00905   EXPECT_TRUE(a != b);
00906 
00907   b.push_back(3);
00908   EXPECT_TRUE(a == b);
00909   EXPECT_FALSE(a != b);
00910 
00911   b.push_back(7);
00912   EXPECT_FALSE(a == b);
00913   EXPECT_TRUE(a != b);
00914 
00915   a.push_back(6);
00916   EXPECT_FALSE(a == b);
00917   EXPECT_TRUE(a != b);
00918 
00919   a.clear();
00920   b.clear();
00921   for (int i = 0; i < 100; i++) {
00922     a.push_back(i);
00923     b.push_back(i);
00924     EXPECT_TRUE(a == b);
00925     EXPECT_FALSE(a != b);
00926 
00927     b[i] = b[i] + 1;
00928     EXPECT_FALSE(a == b);
00929     EXPECT_TRUE(a != b);
00930 
00931     b[i] = b[i] - 1;    // Back to before
00932     EXPECT_TRUE(a == b);
00933     EXPECT_FALSE(a != b);
00934   }
00935 }
00936 
00937 TEST(IntVec, RelationalOps) {
00938   IntVec a, b;
00939   EXPECT_FALSE(a < b);
00940   EXPECT_FALSE(b < a);
00941   EXPECT_FALSE(a > b);
00942   EXPECT_FALSE(b > a);
00943   EXPECT_TRUE(a <= b);
00944   EXPECT_TRUE(b <= a);
00945   EXPECT_TRUE(a >= b);
00946   EXPECT_TRUE(b >= a);
00947   b.push_back(3);
00948   EXPECT_TRUE(a < b);
00949   EXPECT_FALSE(b < a);
00950   EXPECT_FALSE(a > b);
00951   EXPECT_TRUE(b > a);
00952   EXPECT_TRUE(a <= b);
00953   EXPECT_FALSE(b <= a);
00954   EXPECT_FALSE(a >= b);
00955   EXPECT_TRUE(b >= a);
00956 }
00957 
00958 TYPED_TEST_P(InstanceTest, CountConstructorsDestructors) {
00959   using Instance = TypeParam;
00960   using InstanceVec = absl::InlinedVector<Instance, 8>;
00961   InstanceTracker tracker;
00962   for (int len = 0; len < 20; len++) {
00963     SCOPED_TRACE(len);
00964     tracker.ResetCopiesMovesSwaps();
00965 
00966     InstanceVec v;
00967     const size_t inlined_capacity = v.capacity();
00968     for (int i = 0; i < len; i++) {
00969       v.push_back(Instance(i));
00970     }
00971     EXPECT_EQ(tracker.instances(), len);
00972     EXPECT_GE(tracker.copies() + tracker.moves(),
00973               len);  // More due to reallocation.
00974     tracker.ResetCopiesMovesSwaps();
00975 
00976     // Enlarging resize() must construct some objects
00977     tracker.ResetCopiesMovesSwaps();
00978     v.resize(len + 10, Instance(100));
00979     EXPECT_EQ(tracker.instances(), len + 10);
00980     if (len <= inlined_capacity && len + 10 > inlined_capacity) {
00981       EXPECT_EQ(tracker.copies() + tracker.moves(), 10 + len);
00982     } else {
00983       // Only specify a minimum number of copies + moves. We don't want to
00984       // depend on the reallocation policy here.
00985       EXPECT_GE(tracker.copies() + tracker.moves(),
00986                 10);  // More due to reallocation.
00987     }
00988 
00989     // Shrinking resize() must destroy some objects
00990     tracker.ResetCopiesMovesSwaps();
00991     v.resize(len, Instance(100));
00992     EXPECT_EQ(tracker.instances(), len);
00993     EXPECT_EQ(tracker.copies(), 0);
00994     EXPECT_EQ(tracker.moves(), 0);
00995 
00996     // reserve() must not increase the number of initialized objects
00997     SCOPED_TRACE("reserve");
00998     v.reserve(len+1000);
00999     EXPECT_EQ(tracker.instances(), len);
01000     EXPECT_EQ(tracker.copies() + tracker.moves(), len);
01001 
01002     // pop_back() and erase() must destroy one object
01003     if (len > 0) {
01004       tracker.ResetCopiesMovesSwaps();
01005       v.pop_back();
01006       EXPECT_EQ(tracker.instances(), len - 1);
01007       EXPECT_EQ(tracker.copies(), 0);
01008       EXPECT_EQ(tracker.moves(), 0);
01009 
01010       if (!v.empty()) {
01011         tracker.ResetCopiesMovesSwaps();
01012         v.erase(v.begin());
01013         EXPECT_EQ(tracker.instances(), len - 2);
01014         EXPECT_EQ(tracker.copies() + tracker.moves(), len - 2);
01015       }
01016     }
01017 
01018     tracker.ResetCopiesMovesSwaps();
01019     int instances_before_empty_erase = tracker.instances();
01020     v.erase(v.begin(), v.begin());
01021     EXPECT_EQ(tracker.instances(), instances_before_empty_erase);
01022     EXPECT_EQ(tracker.copies() + tracker.moves(), 0);
01023   }
01024 }
01025 
01026 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnCopyConstruction) {
01027   using Instance = TypeParam;
01028   using InstanceVec = absl::InlinedVector<Instance, 8>;
01029   InstanceTracker tracker;
01030   for (int len = 0; len < 20; len++) {
01031     SCOPED_TRACE(len);
01032     tracker.ResetCopiesMovesSwaps();
01033 
01034     InstanceVec v;
01035     for (int i = 0; i < len; i++) {
01036       v.push_back(Instance(i));
01037     }
01038     EXPECT_EQ(tracker.instances(), len);
01039     EXPECT_GE(tracker.copies() + tracker.moves(),
01040               len);  // More due to reallocation.
01041     tracker.ResetCopiesMovesSwaps();
01042     {  // Copy constructor should create 'len' more instances.
01043       InstanceVec v_copy(v);
01044       EXPECT_EQ(tracker.instances(), len + len);
01045       EXPECT_EQ(tracker.copies(), len);
01046       EXPECT_EQ(tracker.moves(), 0);
01047     }
01048     EXPECT_EQ(tracker.instances(), len);
01049   }
01050 }
01051 
01052 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveConstruction) {
01053   using Instance = TypeParam;
01054   using InstanceVec = absl::InlinedVector<Instance, 8>;
01055   InstanceTracker tracker;
01056   for (int len = 0; len < 20; len++) {
01057     SCOPED_TRACE(len);
01058     tracker.ResetCopiesMovesSwaps();
01059 
01060     InstanceVec v;
01061     const size_t inlined_capacity = v.capacity();
01062     for (int i = 0; i < len; i++) {
01063       v.push_back(Instance(i));
01064     }
01065     EXPECT_EQ(tracker.instances(), len);
01066     EXPECT_GE(tracker.copies() + tracker.moves(),
01067               len);  // More due to reallocation.
01068     tracker.ResetCopiesMovesSwaps();
01069     {
01070       InstanceVec v_copy(std::move(v));
01071       if (len > inlined_capacity) {
01072         // Allocation is moved as a whole.
01073         EXPECT_EQ(tracker.instances(), len);
01074         EXPECT_EQ(tracker.live_instances(), len);
01075         // Tests an implementation detail, don't rely on this in your code.
01076         EXPECT_EQ(v.size(), 0);  // NOLINT misc-use-after-move
01077         EXPECT_EQ(tracker.copies(), 0);
01078         EXPECT_EQ(tracker.moves(), 0);
01079       } else {
01080         EXPECT_EQ(tracker.instances(), len + len);
01081         if (Instance::supports_move()) {
01082           EXPECT_EQ(tracker.live_instances(), len);
01083           EXPECT_EQ(tracker.copies(), 0);
01084           EXPECT_EQ(tracker.moves(), len);
01085         } else {
01086           EXPECT_EQ(tracker.live_instances(), len + len);
01087           EXPECT_EQ(tracker.copies(), len);
01088           EXPECT_EQ(tracker.moves(), 0);
01089         }
01090       }
01091       EXPECT_EQ(tracker.swaps(), 0);
01092     }
01093   }
01094 }
01095 
01096 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnAssignment) {
01097   using Instance = TypeParam;
01098   using InstanceVec = absl::InlinedVector<Instance, 8>;
01099   InstanceTracker tracker;
01100   for (int len = 0; len < 20; len++) {
01101     SCOPED_TRACE(len);
01102     for (int longorshort = 0; longorshort <= 1; ++longorshort) {
01103       SCOPED_TRACE(longorshort);
01104       tracker.ResetCopiesMovesSwaps();
01105 
01106       InstanceVec longer, shorter;
01107       for (int i = 0; i < len; i++) {
01108         longer.push_back(Instance(i));
01109         shorter.push_back(Instance(i));
01110       }
01111       longer.push_back(Instance(len));
01112       EXPECT_EQ(tracker.instances(), len + len + 1);
01113       EXPECT_GE(tracker.copies() + tracker.moves(),
01114                 len + len + 1);  // More due to reallocation.
01115 
01116       tracker.ResetCopiesMovesSwaps();
01117       if (longorshort) {
01118         shorter = longer;
01119         EXPECT_EQ(tracker.instances(), (len + 1) + (len + 1));
01120         EXPECT_GE(tracker.copies() + tracker.moves(),
01121                   len + 1);  // More due to reallocation.
01122       } else {
01123         longer = shorter;
01124         EXPECT_EQ(tracker.instances(), len + len);
01125         EXPECT_EQ(tracker.copies() + tracker.moves(), len);
01126       }
01127     }
01128   }
01129 }
01130 
01131 TYPED_TEST_P(InstanceTest, CountConstructorsDestructorsOnMoveAssignment) {
01132   using Instance = TypeParam;
01133   using InstanceVec = absl::InlinedVector<Instance, 8>;
01134   InstanceTracker tracker;
01135   for (int len = 0; len < 20; len++) {
01136     SCOPED_TRACE(len);
01137     for (int longorshort = 0; longorshort <= 1; ++longorshort) {
01138       SCOPED_TRACE(longorshort);
01139       tracker.ResetCopiesMovesSwaps();
01140 
01141       InstanceVec longer, shorter;
01142       const int inlined_capacity = longer.capacity();
01143       for (int i = 0; i < len; i++) {
01144         longer.push_back(Instance(i));
01145         shorter.push_back(Instance(i));
01146       }
01147       longer.push_back(Instance(len));
01148       EXPECT_EQ(tracker.instances(), len + len + 1);
01149       EXPECT_GE(tracker.copies() + tracker.moves(),
01150                 len + len + 1);  // More due to reallocation.
01151 
01152       tracker.ResetCopiesMovesSwaps();
01153       int src_len;
01154       if (longorshort) {
01155         src_len = len + 1;
01156         shorter = std::move(longer);
01157       } else {
01158         src_len = len;
01159         longer = std::move(shorter);
01160       }
01161       if (src_len > inlined_capacity) {
01162         // Allocation moved as a whole.
01163         EXPECT_EQ(tracker.instances(), src_len);
01164         EXPECT_EQ(tracker.live_instances(), src_len);
01165         EXPECT_EQ(tracker.copies(), 0);
01166         EXPECT_EQ(tracker.moves(), 0);
01167       } else {
01168         // Elements are all copied.
01169         EXPECT_EQ(tracker.instances(), src_len + src_len);
01170         if (Instance::supports_move()) {
01171           EXPECT_EQ(tracker.copies(), 0);
01172           EXPECT_EQ(tracker.moves(), src_len);
01173           EXPECT_EQ(tracker.live_instances(), src_len);
01174         } else {
01175           EXPECT_EQ(tracker.copies(), src_len);
01176           EXPECT_EQ(tracker.moves(), 0);
01177           EXPECT_EQ(tracker.live_instances(), src_len + src_len);
01178         }
01179       }
01180       EXPECT_EQ(tracker.swaps(), 0);
01181     }
01182   }
01183 }
01184 
01185 TEST(CountElemAssign, SimpleTypeWithInlineBacking) {
01186   for (size_t original_size = 0; original_size <= 5; ++original_size) {
01187     SCOPED_TRACE(original_size);
01188     // Original contents are [12345, 12345, ...]
01189     std::vector<int> original_contents(original_size, 12345);
01190 
01191     absl::InlinedVector<int, 2> v(original_contents.begin(),
01192                                   original_contents.end());
01193     v.assign(2, 123);
01194     EXPECT_THAT(v, AllOf(SizeIs(2), ElementsAre(123, 123)));
01195     if (original_size <= 2) {
01196       // If the original had inline backing, it should stay inline.
01197       EXPECT_EQ(2, v.capacity());
01198     }
01199   }
01200 }
01201 
01202 TEST(CountElemAssign, SimpleTypeWithAllocation) {
01203   for (size_t original_size = 0; original_size <= 5; ++original_size) {
01204     SCOPED_TRACE(original_size);
01205     // Original contents are [12345, 12345, ...]
01206     std::vector<int> original_contents(original_size, 12345);
01207 
01208     absl::InlinedVector<int, 2> v(original_contents.begin(),
01209                                   original_contents.end());
01210     v.assign(3, 123);
01211     EXPECT_THAT(v, AllOf(SizeIs(3), ElementsAre(123, 123, 123)));
01212     EXPECT_LE(v.size(), v.capacity());
01213   }
01214 }
01215 
01216 TYPED_TEST_P(InstanceTest, CountElemAssignInlineBacking) {
01217   using Instance = TypeParam;
01218   for (size_t original_size = 0; original_size <= 5; ++original_size) {
01219     SCOPED_TRACE(original_size);
01220     // Original contents are [12345, 12345, ...]
01221     std::vector<Instance> original_contents(original_size, Instance(12345));
01222 
01223     absl::InlinedVector<Instance, 2> v(original_contents.begin(),
01224                                        original_contents.end());
01225     v.assign(2, Instance(123));
01226     EXPECT_THAT(v, AllOf(SizeIs(2), ElementsAre(ValueIs(123), ValueIs(123))));
01227     if (original_size <= 2) {
01228       // If the original had inline backing, it should stay inline.
01229       EXPECT_EQ(2, v.capacity());
01230     }
01231   }
01232 }
01233 
01234 template <typename Instance>
01235 void InstanceCountElemAssignWithAllocationTest() {
01236   for (size_t original_size = 0; original_size <= 5; ++original_size) {
01237     SCOPED_TRACE(original_size);
01238     // Original contents are [12345, 12345, ...]
01239     std::vector<Instance> original_contents(original_size, Instance(12345));
01240 
01241     absl::InlinedVector<Instance, 2> v(original_contents.begin(),
01242                                        original_contents.end());
01243     v.assign(3, Instance(123));
01244     EXPECT_THAT(v,
01245                 AllOf(SizeIs(3),
01246                       ElementsAre(ValueIs(123), ValueIs(123), ValueIs(123))));
01247     EXPECT_LE(v.size(), v.capacity());
01248   }
01249 }
01250 TEST(CountElemAssign, WithAllocationCopyableInstance) {
01251   InstanceCountElemAssignWithAllocationTest<CopyableOnlyInstance>();
01252 }
01253 TEST(CountElemAssign, WithAllocationCopyableMovableInstance) {
01254   InstanceCountElemAssignWithAllocationTest<CopyableMovableInstance>();
01255 }
01256 
01257 TEST(RangedConstructor, SimpleType) {
01258   std::vector<int> source_v = {4, 5, 6};
01259   // First try to fit in inline backing
01260   absl::InlinedVector<int, 4> v(source_v.begin(), source_v.end());
01261   EXPECT_EQ(3, v.size());
01262   EXPECT_EQ(4, v.capacity());  // Indication that we're still on inlined storage
01263   EXPECT_EQ(4, v[0]);
01264   EXPECT_EQ(5, v[1]);
01265   EXPECT_EQ(6, v[2]);
01266 
01267   // Now, force a re-allocate
01268   absl::InlinedVector<int, 2> realloc_v(source_v.begin(), source_v.end());
01269   EXPECT_EQ(3, realloc_v.size());
01270   EXPECT_LT(2, realloc_v.capacity());
01271   EXPECT_EQ(4, realloc_v[0]);
01272   EXPECT_EQ(5, realloc_v[1]);
01273   EXPECT_EQ(6, realloc_v[2]);
01274 }
01275 
01276 // Test for ranged constructors using Instance as the element type and
01277 // SourceContainer as the source container type.
01278 template <typename Instance, typename SourceContainer, int inlined_capacity>
01279 void InstanceRangedConstructorTestForContainer() {
01280   InstanceTracker tracker;
01281   SourceContainer source_v = {Instance(0), Instance(1)};
01282   tracker.ResetCopiesMovesSwaps();
01283   absl::InlinedVector<Instance, inlined_capacity> v(source_v.begin(),
01284                                                     source_v.end());
01285   EXPECT_EQ(2, v.size());
01286   EXPECT_LT(1, v.capacity());
01287   EXPECT_EQ(0, v[0].value());
01288   EXPECT_EQ(1, v[1].value());
01289   EXPECT_EQ(tracker.copies(), 2);
01290   EXPECT_EQ(tracker.moves(), 0);
01291 }
01292 
01293 template <typename Instance, int inlined_capacity>
01294 void InstanceRangedConstructorTestWithCapacity() {
01295   // Test with const and non-const, random access and non-random-access sources.
01296   // TODO(bsamwel): Test with an input iterator source.
01297   {
01298     SCOPED_TRACE("std::list");
01299     InstanceRangedConstructorTestForContainer<Instance, std::list<Instance>,
01300                                               inlined_capacity>();
01301     {
01302       SCOPED_TRACE("const std::list");
01303       InstanceRangedConstructorTestForContainer<
01304           Instance, const std::list<Instance>, inlined_capacity>();
01305     }
01306     {
01307       SCOPED_TRACE("std::vector");
01308       InstanceRangedConstructorTestForContainer<Instance, std::vector<Instance>,
01309                                                 inlined_capacity>();
01310     }
01311     {
01312       SCOPED_TRACE("const std::vector");
01313       InstanceRangedConstructorTestForContainer<
01314           Instance, const std::vector<Instance>, inlined_capacity>();
01315     }
01316   }
01317 }
01318 
01319 TYPED_TEST_P(InstanceTest, RangedConstructor) {
01320   using Instance = TypeParam;
01321   SCOPED_TRACE("capacity=1");
01322   InstanceRangedConstructorTestWithCapacity<Instance, 1>();
01323   SCOPED_TRACE("capacity=2");
01324   InstanceRangedConstructorTestWithCapacity<Instance, 2>();
01325 }
01326 
01327 TEST(RangedConstructor, ElementsAreConstructed) {
01328   std::vector<std::string> source_v = {"cat", "dog"};
01329 
01330   // Force expansion and re-allocation of v.  Ensures that when the vector is
01331   // expanded that new elements are constructed.
01332   absl::InlinedVector<std::string, 1> v(source_v.begin(), source_v.end());
01333   EXPECT_EQ("cat", v[0]);
01334   EXPECT_EQ("dog", v[1]);
01335 }
01336 
01337 TEST(RangedAssign, SimpleType) {
01338   // Test for all combinations of original sizes (empty and non-empty inline,
01339   // and out of line) and target sizes.
01340   for (size_t original_size = 0; original_size <= 5; ++original_size) {
01341     SCOPED_TRACE(original_size);
01342     // Original contents are [12345, 12345, ...]
01343     std::vector<int> original_contents(original_size, 12345);
01344 
01345     for (size_t target_size = 0; target_size <= 5; ++target_size) {
01346       SCOPED_TRACE(target_size);
01347 
01348       // New contents are [3, 4, ...]
01349       std::vector<int> new_contents;
01350       for (size_t i = 0; i < target_size; ++i) {
01351         new_contents.push_back(i + 3);
01352       }
01353 
01354       absl::InlinedVector<int, 3> v(original_contents.begin(),
01355                                     original_contents.end());
01356       v.assign(new_contents.begin(), new_contents.end());
01357 
01358       EXPECT_EQ(new_contents.size(), v.size());
01359       EXPECT_LE(new_contents.size(), v.capacity());
01360       if (target_size <= 3 && original_size <= 3) {
01361         // Storage should stay inline when target size is small.
01362         EXPECT_EQ(3, v.capacity());
01363       }
01364       EXPECT_THAT(v, ElementsAreArray(new_contents));
01365     }
01366   }
01367 }
01368 
01369 // Returns true if lhs and rhs have the same value.
01370 template <typename Instance>
01371 static bool InstanceValuesEqual(const Instance& lhs, const Instance& rhs) {
01372   return lhs.value() == rhs.value();
01373 }
01374 
01375 // Test for ranged assign() using Instance as the element type and
01376 // SourceContainer as the source container type.
01377 template <typename Instance, typename SourceContainer>
01378 void InstanceRangedAssignTestForContainer() {
01379   // Test for all combinations of original sizes (empty and non-empty inline,
01380   // and out of line) and target sizes.
01381   for (size_t original_size = 0; original_size <= 5; ++original_size) {
01382     SCOPED_TRACE(original_size);
01383     // Original contents are [12345, 12345, ...]
01384     std::vector<Instance> original_contents(original_size, Instance(12345));
01385 
01386     for (size_t target_size = 0; target_size <= 5; ++target_size) {
01387       SCOPED_TRACE(target_size);
01388 
01389       // New contents are [3, 4, ...]
01390       // Generate data using a non-const container, because SourceContainer
01391       // itself may be const.
01392       // TODO(bsamwel): Test with an input iterator.
01393       std::vector<Instance> new_contents_in;
01394       for (size_t i = 0; i < target_size; ++i) {
01395         new_contents_in.push_back(Instance(i + 3));
01396       }
01397       SourceContainer new_contents(new_contents_in.begin(),
01398                                    new_contents_in.end());
01399 
01400       absl::InlinedVector<Instance, 3> v(original_contents.begin(),
01401                                          original_contents.end());
01402       v.assign(new_contents.begin(), new_contents.end());
01403 
01404       EXPECT_EQ(new_contents.size(), v.size());
01405       EXPECT_LE(new_contents.size(), v.capacity());
01406       if (target_size <= 3 && original_size <= 3) {
01407         // Storage should stay inline when target size is small.
01408         EXPECT_EQ(3, v.capacity());
01409       }
01410       EXPECT_TRUE(std::equal(v.begin(), v.end(), new_contents.begin(),
01411                              InstanceValuesEqual<Instance>));
01412     }
01413   }
01414 }
01415 
01416 TYPED_TEST_P(InstanceTest, RangedAssign) {
01417   using Instance = TypeParam;
01418   // Test with const and non-const, random access and non-random-access sources.
01419   // TODO(bsamwel): Test with an input iterator source.
01420   SCOPED_TRACE("std::list");
01421   InstanceRangedAssignTestForContainer<Instance, std::list<Instance>>();
01422   SCOPED_TRACE("const std::list");
01423   InstanceRangedAssignTestForContainer<Instance, const std::list<Instance>>();
01424   SCOPED_TRACE("std::vector");
01425   InstanceRangedAssignTestForContainer<Instance, std::vector<Instance>>();
01426   SCOPED_TRACE("const std::vector");
01427   InstanceRangedAssignTestForContainer<Instance, const std::vector<Instance>>();
01428 }
01429 
01430 TEST(InitializerListConstructor, SimpleTypeWithInlineBacking) {
01431   EXPECT_THAT((absl::InlinedVector<int, 4>{4, 5, 6}),
01432               AllOf(SizeIs(3), CapacityIs(4), ElementsAre(4, 5, 6)));
01433 }
01434 
01435 TEST(InitializerListConstructor, SimpleTypeWithReallocationRequired) {
01436   EXPECT_THAT((absl::InlinedVector<int, 2>{4, 5, 6}),
01437               AllOf(SizeIs(3), CapacityIs(Gt(2)), ElementsAre(4, 5, 6)));
01438 }
01439 
01440 TEST(InitializerListConstructor, DisparateTypesInList) {
01441   EXPECT_THAT((absl::InlinedVector<int, 2>{-7, 8ULL}), ElementsAre(-7, 8));
01442 
01443   EXPECT_THAT((absl::InlinedVector<std::string, 2>{"foo", std::string("bar")}),
01444               ElementsAre("foo", "bar"));
01445 }
01446 
01447 TEST(InitializerListConstructor, ComplexTypeWithInlineBacking) {
01448   EXPECT_THAT((absl::InlinedVector<CopyableMovableInstance, 1>{
01449                   CopyableMovableInstance(0)}),
01450               AllOf(SizeIs(1), CapacityIs(1), ElementsAre(ValueIs(0))));
01451 }
01452 
01453 TEST(InitializerListConstructor, ComplexTypeWithReallocationRequired) {
01454   EXPECT_THAT(
01455       (absl::InlinedVector<CopyableMovableInstance, 1>{
01456           CopyableMovableInstance(0), CopyableMovableInstance(1)}),
01457       AllOf(SizeIs(2), CapacityIs(Gt(1)), ElementsAre(ValueIs(0), ValueIs(1))));
01458 }
01459 
01460 TEST(InitializerListAssign, SimpleTypeFitsInlineBacking) {
01461   for (size_t original_size = 0; original_size <= 4; ++original_size) {
01462     SCOPED_TRACE(original_size);
01463 
01464     absl::InlinedVector<int, 2> v1(original_size, 12345);
01465     const size_t original_capacity_v1 = v1.capacity();
01466     v1.assign({3});
01467     EXPECT_THAT(
01468         v1, AllOf(SizeIs(1), CapacityIs(original_capacity_v1), ElementsAre(3)));
01469 
01470     absl::InlinedVector<int, 2> v2(original_size, 12345);
01471     const size_t original_capacity_v2 = v2.capacity();
01472     v2 = {3};
01473     EXPECT_THAT(
01474         v2, AllOf(SizeIs(1), CapacityIs(original_capacity_v2), ElementsAre(3)));
01475   }
01476 }
01477 
01478 TEST(InitializerListAssign, SimpleTypeDoesNotFitInlineBacking) {
01479   for (size_t original_size = 0; original_size <= 4; ++original_size) {
01480     SCOPED_TRACE(original_size);
01481     absl::InlinedVector<int, 2> v1(original_size, 12345);
01482     v1.assign({3, 4, 5});
01483     EXPECT_THAT(v1, AllOf(SizeIs(3), ElementsAre(3, 4, 5)));
01484     EXPECT_LE(3, v1.capacity());
01485 
01486     absl::InlinedVector<int, 2> v2(original_size, 12345);
01487     v2 = {3, 4, 5};
01488     EXPECT_THAT(v2, AllOf(SizeIs(3), ElementsAre(3, 4, 5)));
01489     EXPECT_LE(3, v2.capacity());
01490   }
01491 }
01492 
01493 TEST(InitializerListAssign, DisparateTypesInList) {
01494   absl::InlinedVector<int, 2> v_int1;
01495   v_int1.assign({-7, 8ULL});
01496   EXPECT_THAT(v_int1, ElementsAre(-7, 8));
01497 
01498   absl::InlinedVector<int, 2> v_int2;
01499   v_int2 = {-7, 8ULL};
01500   EXPECT_THAT(v_int2, ElementsAre(-7, 8));
01501 
01502   absl::InlinedVector<std::string, 2> v_string1;
01503   v_string1.assign({"foo", std::string("bar")});
01504   EXPECT_THAT(v_string1, ElementsAre("foo", "bar"));
01505 
01506   absl::InlinedVector<std::string, 2> v_string2;
01507   v_string2 = {"foo", std::string("bar")};
01508   EXPECT_THAT(v_string2, ElementsAre("foo", "bar"));
01509 }
01510 
01511 TYPED_TEST_P(InstanceTest, InitializerListAssign) {
01512   using Instance = TypeParam;
01513   for (size_t original_size = 0; original_size <= 4; ++original_size) {
01514     SCOPED_TRACE(original_size);
01515     absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));
01516     const size_t original_capacity = v.capacity();
01517     v.assign({Instance(3)});
01518     EXPECT_THAT(v, AllOf(SizeIs(1), CapacityIs(original_capacity),
01519                          ElementsAre(ValueIs(3))));
01520   }
01521   for (size_t original_size = 0; original_size <= 4; ++original_size) {
01522     SCOPED_TRACE(original_size);
01523     absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));
01524     v.assign({Instance(3), Instance(4), Instance(5)});
01525     EXPECT_THAT(v, AllOf(SizeIs(3),
01526                          ElementsAre(ValueIs(3), ValueIs(4), ValueIs(5))));
01527     EXPECT_LE(3, v.capacity());
01528   }
01529 }
01530 
01531 REGISTER_TYPED_TEST_CASE_P(InstanceTest, Swap, CountConstructorsDestructors,
01532                            CountConstructorsDestructorsOnCopyConstruction,
01533                            CountConstructorsDestructorsOnMoveConstruction,
01534                            CountConstructorsDestructorsOnAssignment,
01535                            CountConstructorsDestructorsOnMoveAssignment,
01536                            CountElemAssignInlineBacking, RangedConstructor,
01537                            RangedAssign, InitializerListAssign);
01538 
01539 using InstanceTypes =
01540     ::testing::Types<CopyableOnlyInstance, CopyableMovableInstance>;
01541 INSTANTIATE_TYPED_TEST_CASE_P(InstanceTestOnTypes, InstanceTest, InstanceTypes);
01542 
01543 TEST(DynamicVec, DynamicVecCompiles) {
01544   DynamicVec v;
01545   (void)v;
01546 }
01547 
01548 TEST(AllocatorSupportTest, Constructors) {
01549   using MyAlloc = CountingAllocator<int>;
01550   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
01551   const int ia[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
01552   int64_t allocated = 0;
01553   MyAlloc alloc(&allocated);
01554   { AllocVec ABSL_ATTRIBUTE_UNUSED v; }
01555   { AllocVec ABSL_ATTRIBUTE_UNUSED v(alloc); }
01556   { AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc); }
01557   { AllocVec ABSL_ATTRIBUTE_UNUSED v({1, 2, 3}, alloc); }
01558 
01559   AllocVec v2;
01560   { AllocVec ABSL_ATTRIBUTE_UNUSED v(v2, alloc); }
01561   { AllocVec ABSL_ATTRIBUTE_UNUSED v(std::move(v2), alloc); }
01562 }
01563 
01564 TEST(AllocatorSupportTest, CountAllocations) {
01565   using MyAlloc = CountingAllocator<int>;
01566   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
01567   const int ia[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
01568   int64_t allocated = 0;
01569   MyAlloc alloc(&allocated);
01570   {
01571     AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + 4, alloc);
01572     EXPECT_THAT(allocated, 0);
01573   }
01574   EXPECT_THAT(allocated, 0);
01575   {
01576     AllocVec ABSL_ATTRIBUTE_UNUSED v(ia, ia + ABSL_ARRAYSIZE(ia), alloc);
01577     EXPECT_THAT(allocated, v.size() * sizeof(int));
01578   }
01579   EXPECT_THAT(allocated, 0);
01580   {
01581     AllocVec v(4, 1, alloc);
01582     EXPECT_THAT(allocated, 0);
01583 
01584     int64_t allocated2 = 0;
01585     MyAlloc alloc2(&allocated2);
01586     AllocVec v2(v, alloc2);
01587     EXPECT_THAT(allocated2, 0);
01588 
01589     int64_t allocated3 = 0;
01590     MyAlloc alloc3(&allocated3);
01591     AllocVec v3(std::move(v), alloc3);
01592     EXPECT_THAT(allocated3, 0);
01593   }
01594   EXPECT_THAT(allocated, 0);
01595   {
01596     AllocVec v(8, 2, alloc);
01597     EXPECT_THAT(allocated, v.size() * sizeof(int));
01598 
01599     int64_t allocated2 = 0;
01600     MyAlloc alloc2(&allocated2);
01601     AllocVec v2(v, alloc2);
01602     EXPECT_THAT(allocated2, v2.size() * sizeof(int));
01603 
01604     int64_t allocated3 = 0;
01605     MyAlloc alloc3(&allocated3);
01606     AllocVec v3(std::move(v), alloc3);
01607     EXPECT_THAT(allocated3, v3.size() * sizeof(int));
01608   }
01609   EXPECT_EQ(allocated, 0);
01610   {
01611     // Test shrink_to_fit deallocations.
01612     AllocVec v(8, 2, alloc);
01613     EXPECT_EQ(allocated, 8 * sizeof(int));
01614     v.resize(5);
01615     EXPECT_EQ(allocated, 8 * sizeof(int));
01616     v.shrink_to_fit();
01617     EXPECT_EQ(allocated, 5 * sizeof(int));
01618     v.resize(4);
01619     EXPECT_EQ(allocated, 5 * sizeof(int));
01620     v.shrink_to_fit();
01621     EXPECT_EQ(allocated, 0);
01622   }
01623 }
01624 
01625 TEST(AllocatorSupportTest, SwapBothAllocated) {
01626   using MyAlloc = CountingAllocator<int>;
01627   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
01628   int64_t allocated1 = 0;
01629   int64_t allocated2 = 0;
01630   {
01631     const int ia1[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
01632     const int ia2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
01633     MyAlloc a1(&allocated1);
01634     MyAlloc a2(&allocated2);
01635     AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);
01636     AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2);
01637     EXPECT_LT(v1.capacity(), v2.capacity());
01638     EXPECT_THAT(allocated1, v1.capacity() * sizeof(int));
01639     EXPECT_THAT(allocated2, v2.capacity() * sizeof(int));
01640     v1.swap(v2);
01641     EXPECT_THAT(v1, ElementsAreArray(ia2));
01642     EXPECT_THAT(v2, ElementsAreArray(ia1));
01643     EXPECT_THAT(allocated1, v2.capacity() * sizeof(int));
01644     EXPECT_THAT(allocated2, v1.capacity() * sizeof(int));
01645   }
01646   EXPECT_THAT(allocated1, 0);
01647   EXPECT_THAT(allocated2, 0);
01648 }
01649 
01650 TEST(AllocatorSupportTest, SwapOneAllocated) {
01651   using MyAlloc = CountingAllocator<int>;
01652   using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
01653   int64_t allocated1 = 0;
01654   int64_t allocated2 = 0;
01655   {
01656     const int ia1[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
01657     const int ia2[] = { 0, 1, 2, 3 };
01658     MyAlloc a1(&allocated1);
01659     MyAlloc a2(&allocated2);
01660     AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);
01661     AllocVec v2(ia2, ia2 + ABSL_ARRAYSIZE(ia2), a2);
01662     EXPECT_THAT(allocated1, v1.capacity() * sizeof(int));
01663     EXPECT_THAT(allocated2, 0);
01664     v1.swap(v2);
01665     EXPECT_THAT(v1, ElementsAreArray(ia2));
01666     EXPECT_THAT(v2, ElementsAreArray(ia1));
01667     EXPECT_THAT(allocated1, v2.capacity() * sizeof(int));
01668     EXPECT_THAT(allocated2, 0);
01669     EXPECT_TRUE(v2.get_allocator() == a1);
01670     EXPECT_TRUE(v1.get_allocator() == a2);
01671   }
01672   EXPECT_THAT(allocated1, 0);
01673   EXPECT_THAT(allocated2, 0);
01674 }
01675 
01676 TEST(AllocatorSupportTest, ScopedAllocatorWorks) {
01677   using StdVector = std::vector<int, CountingAllocator<int>>;
01678   using MyAlloc =
01679       std::scoped_allocator_adaptor<CountingAllocator<StdVector>>;
01680   using AllocVec = absl::InlinedVector<StdVector, 4, MyAlloc>;
01681 
01682   // MSVC 2017's std::vector allocates different amounts of memory in debug
01683   // versus opt mode.
01684   int64_t test_allocated = 0;
01685   StdVector v(CountingAllocator<int>{&test_allocated});
01686   // The amount of memory allocated by a default constructed vector<int>
01687   auto default_std_vec_allocated = test_allocated;
01688   v.push_back(1);
01689   // The amound of memory allocated by a copy-constructed vector<int> with one
01690   // element.
01691   int64_t one_element_std_vec_copy_allocated = test_allocated;
01692 
01693   int64_t allocated = 0;
01694   AllocVec vec(MyAlloc{CountingAllocator<StdVector>{&allocated}});
01695   EXPECT_EQ(allocated, 0);
01696 
01697   // This default constructs a vector<int>, but the allocator should pass itself
01698   // into the vector<int>, so check allocation compared to that.
01699   // The absl::InlinedVector does not allocate any memory.
01700   // The vector<int> may allocate any memory.
01701   auto expected = default_std_vec_allocated;
01702   vec.resize(1);
01703   EXPECT_EQ(allocated, expected);
01704 
01705   // We make vector<int> allocate memory.
01706   // It must go through the allocator even though we didn't construct the
01707   // vector directly.  This assumes that vec[0] doesn't need to grow its
01708   // allocation.
01709   expected += sizeof(int);
01710   vec[0].push_back(1);
01711   EXPECT_EQ(allocated, expected);
01712 
01713   // Another allocating vector.
01714   expected += one_element_std_vec_copy_allocated;
01715   vec.push_back(vec[0]);
01716   EXPECT_EQ(allocated, expected);
01717 
01718   // Overflow the inlined memory.
01719   // The absl::InlinedVector will now allocate.
01720   expected += sizeof(StdVector) * 8 + default_std_vec_allocated * 3;
01721   vec.resize(5);
01722   EXPECT_EQ(allocated, expected);
01723 
01724   // Adding one more in external mode should also work.
01725   expected += one_element_std_vec_copy_allocated;
01726   vec.push_back(vec[0]);
01727   EXPECT_EQ(allocated, expected);
01728 
01729   // And extending these should still work.  This assumes that vec[0] does not
01730   // need to grow its allocation.
01731   expected += sizeof(int);
01732   vec[0].push_back(1);
01733   EXPECT_EQ(allocated, expected);
01734 
01735   vec.clear();
01736   EXPECT_EQ(allocated, 0);
01737 }
01738 
01739 TEST(AllocatorSupportTest, SizeAllocConstructor) {
01740   constexpr int inlined_size = 4;
01741   using Alloc = CountingAllocator<int>;
01742   using AllocVec = absl::InlinedVector<int, inlined_size, Alloc>;
01743 
01744   {
01745     auto len = inlined_size / 2;
01746     int64_t allocated = 0;
01747     auto v = AllocVec(len, Alloc(&allocated));
01748 
01749     // Inline storage used; allocator should not be invoked
01750     EXPECT_THAT(allocated, 0);
01751     EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
01752   }
01753 
01754   {
01755     auto len = inlined_size * 2;
01756     int64_t allocated = 0;
01757     auto v = AllocVec(len, Alloc(&allocated));
01758 
01759     // Out of line storage used; allocation of 8 elements expected
01760     EXPECT_THAT(allocated, len * sizeof(int));
01761     EXPECT_THAT(v, AllOf(SizeIs(len), Each(0)));
01762   }
01763 }
01764 
01765 TEST(InlinedVectorTest, AbslHashValueWorks) {
01766   using V = absl::InlinedVector<int, 4>;
01767   std::vector<V> cases;
01768 
01769   // Generate a variety of vectors some of these are small enough for the inline
01770   // space but are stored out of line.
01771   for (int i = 0; i < 10; ++i) {
01772     V v;
01773     for (int j = 0; j < i; ++j) {
01774       v.push_back(j);
01775     }
01776     cases.push_back(v);
01777     v.resize(i % 4);
01778     cases.push_back(v);
01779   }
01780 
01781   EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
01782 }
01783 
01784 }  // anonymous namespace


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:15