| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 | 
							- /*
 
-  *
 
-  * Copyright 2017 gRPC authors.
 
-  *
 
-  * Licensed under the Apache License, Version 2.0 (the "License");
 
-  * you may not use this file except in compliance with the License.
 
-  * You may obtain a copy of the License at
 
-  *
 
-  *     http://www.apache.org/licenses/LICENSE-2.0
 
-  *
 
-  * Unless required by applicable law or agreed to in writing, software
 
-  * distributed under the License is distributed on an "AS IS" BASIS,
 
-  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-  * See the License for the specific language governing permissions and
 
-  * limitations under the License.
 
-  *
 
-  */
 
- #include "src/core/lib/gprpp/inlined_vector.h"
 
- #include <grpc/support/log.h>
 
- #include <gtest/gtest.h>
 
- #include "src/core/lib/gprpp/memory.h"
 
- #include "test/core/util/test_config.h"
 
- namespace grpc_core {
 
- namespace testing {
 
- namespace {
 
- template <typename Vector>
 
- static void FillVector(Vector* v, int len, int start = 0) {
 
-   for (int i = 0; i < len; i++) {
 
-     v->push_back(i + start);
 
-     EXPECT_EQ(i + 1UL, v->size());
 
-   }
 
-   EXPECT_EQ(static_cast<size_t>(len), v->size());
 
-   EXPECT_LE(static_cast<size_t>(len), v->capacity());
 
- }
 
- }  // namespace
 
- TEST(InlinedVectorTest, CreateAndIterate) {
 
-   const int kNumElements = 9;
 
-   InlinedVector<int, 2> v;
 
-   EXPECT_TRUE(v.empty());
 
-   FillVector(&v, kNumElements);
 
-   EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
 
-   EXPECT_FALSE(v.empty());
 
-   for (int i = 0; i < kNumElements; ++i) {
 
-     EXPECT_EQ(i, v[i]);
 
-     EXPECT_EQ(i, &v[i] - &v[0]);  // Ensure contiguous allocation.
 
-   }
 
- }
 
- TEST(InlinedVectorTest, ValuesAreInlined) {
 
-   const int kNumElements = 5;
 
-   InlinedVector<int, 10> v;
 
-   FillVector(&v, kNumElements);
 
-   EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
 
-   for (int i = 0; i < kNumElements; ++i) {
 
-     EXPECT_EQ(i, v[i]);
 
-   }
 
- }
 
- TEST(InlinedVectorTest, PushBackWithMove) {
 
-   InlinedVector<UniquePtr<int>, 1> v;
 
-   UniquePtr<int> i = MakeUnique<int>(3);
 
-   v.push_back(std::move(i));
 
-   EXPECT_EQ(nullptr, i.get());
 
-   EXPECT_EQ(1UL, v.size());
 
-   EXPECT_EQ(3, *v[0]);
 
- }
 
- TEST(InlinedVectorTest, EmplaceBack) {
 
-   InlinedVector<UniquePtr<int>, 1> v;
 
-   v.emplace_back(New<int>(3));
 
-   EXPECT_EQ(1UL, v.size());
 
-   EXPECT_EQ(3, *v[0]);
 
- }
 
- TEST(InlinedVectorTest, ClearAndRepopulate) {
 
-   const int kNumElements = 10;
 
-   InlinedVector<int, 5> v;
 
-   EXPECT_EQ(0UL, v.size());
 
-   FillVector(&v, kNumElements);
 
-   for (int i = 0; i < kNumElements; ++i) {
 
-     EXPECT_EQ(i, v[i]);
 
-   }
 
-   v.clear();
 
-   EXPECT_EQ(0UL, v.size());
 
-   FillVector(&v, kNumElements, kNumElements);
 
-   for (int i = 0; i < kNumElements; ++i) {
 
-     EXPECT_EQ(kNumElements + i, v[i]);
 
-   }
 
- }
 
- TEST(InlinedVectorTest, ConstIndexOperator) {
 
-   constexpr int kNumElements = 10;
 
-   InlinedVector<int, 5> v;
 
-   EXPECT_EQ(0UL, v.size());
 
-   FillVector(&v, kNumElements);
 
-   // The following lambda function is exceptionally allowed to use an anonymous
 
-   // capture due to the erroneous behavior of the MSVC compiler, that refuses to
 
-   // capture the kNumElements constexpr, something allowed by the standard.
 
-   auto const_func = [&](const InlinedVector<int, 5>& v) {
 
-     for (int i = 0; i < kNumElements; ++i) {
 
-       EXPECT_EQ(i, v[i]);
 
-     }
 
-   };
 
-   const_func(v);
 
- }
 
- // the following constants and typedefs are used for copy/move
 
- // construction/assignment
 
- const size_t kInlinedLength = 8;
 
- typedef InlinedVector<int, kInlinedLength> IntVec8;
 
- const size_t kInlinedFillSize = kInlinedLength - 1;
 
- const size_t kAllocatedFillSize = kInlinedLength + 1;
 
- TEST(InlinedVectorTest, CopyConstructorInlined) {
 
-   IntVec8 original;
 
-   FillVector(&original, kInlinedFillSize);
 
-   IntVec8 copy_constructed(original);
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], copy_constructed[i]);
 
-   }
 
- }
 
- TEST(InlinedVectorTest, CopyConstructorAllocated) {
 
-   IntVec8 original;
 
-   FillVector(&original, kAllocatedFillSize);
 
-   IntVec8 copy_constructed(original);
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], copy_constructed[i]);
 
-   }
 
- }
 
- TEST(InlinedVectorTest, CopyAssignementInlinedInlined) {
 
-   IntVec8 original;
 
-   FillVector(&original, kInlinedFillSize);
 
-   IntVec8 copy_assigned;
 
-   FillVector(©_assigned, kInlinedFillSize, 99);
 
-   copy_assigned = original;
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], copy_assigned[i]);
 
-   }
 
- }
 
- TEST(InlinedVectorTest, CopyAssignementInlinedAllocated) {
 
-   IntVec8 original;
 
-   FillVector(&original, kInlinedFillSize);
 
-   IntVec8 copy_assigned;
 
-   FillVector(©_assigned, kAllocatedFillSize, 99);
 
-   copy_assigned = original;
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], copy_assigned[i]);
 
-   }
 
- }
 
- TEST(InlinedVectorTest, CopyAssignementAllocatedInlined) {
 
-   IntVec8 original;
 
-   FillVector(&original, kAllocatedFillSize);
 
-   IntVec8 copy_assigned;
 
-   FillVector(©_assigned, kInlinedFillSize, 99);
 
-   copy_assigned = original;
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], copy_assigned[i]);
 
-   }
 
- }
 
- TEST(InlinedVectorTest, CopyAssignementAllocatedAllocated) {
 
-   IntVec8 original;
 
-   FillVector(&original, kAllocatedFillSize);
 
-   IntVec8 copy_assigned;
 
-   FillVector(©_assigned, kAllocatedFillSize, 99);
 
-   copy_assigned = original;
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], copy_assigned[i]);
 
-   }
 
- }
 
- TEST(InlinedVectorTest, MoveConstructorInlined) {
 
-   IntVec8 original;
 
-   FillVector(&original, kInlinedFillSize);
 
-   IntVec8 tmp(original);
 
-   auto* old_data = tmp.data();
 
-   IntVec8 move_constructed(std::move(tmp));
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], move_constructed[i]);
 
-   }
 
-   // original data was inlined so it should have been copied, not moved.
 
-   EXPECT_NE(move_constructed.data(), old_data);
 
- }
 
- TEST(InlinedVectorTest, MoveConstructorAllocated) {
 
-   IntVec8 original;
 
-   FillVector(&original, kAllocatedFillSize);
 
-   IntVec8 tmp(original);
 
-   auto* old_data = tmp.data();
 
-   IntVec8 move_constructed(std::move(tmp));
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], move_constructed[i]);
 
-   }
 
-   // original data was allocated, so it should been moved, not copied
 
-   EXPECT_EQ(move_constructed.data(), old_data);
 
- }
 
- TEST(InlinedVectorTest, MoveAssignmentInlinedInlined) {
 
-   IntVec8 original;
 
-   FillVector(&original, kInlinedFillSize);
 
-   IntVec8 move_assigned;
 
-   FillVector(&move_assigned, kInlinedFillSize, 99);  // Add dummy elements
 
-   IntVec8 tmp(original);
 
-   auto* old_data = tmp.data();
 
-   move_assigned = std::move(tmp);
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], move_assigned[i]);
 
-   }
 
-   // original data was inlined so it should have been copied, not moved.
 
-   EXPECT_NE(move_assigned.data(), old_data);
 
- }
 
- TEST(InlinedVectorTest, MoveAssignmentInlinedAllocated) {
 
-   IntVec8 original;
 
-   FillVector(&original, kInlinedFillSize);
 
-   IntVec8 move_assigned;
 
-   FillVector(&move_assigned, kAllocatedFillSize, 99);  // Add dummy elements
 
-   IntVec8 tmp(original);
 
-   auto* old_data = tmp.data();
 
-   move_assigned = std::move(tmp);
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], move_assigned[i]);
 
-   }
 
-   // original data was inlined so it should have been copied, not moved.
 
-   EXPECT_NE(move_assigned.data(), old_data);
 
- }
 
- TEST(InlinedVectorTest, MoveAssignmentAllocatedInlined) {
 
-   IntVec8 original;
 
-   FillVector(&original, kAllocatedFillSize);
 
-   IntVec8 move_assigned;
 
-   FillVector(&move_assigned, kInlinedFillSize, 99);  // Add dummy elements
 
-   IntVec8 tmp(original);
 
-   auto* old_data = tmp.data();
 
-   move_assigned = std::move(tmp);
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], move_assigned[i]);
 
-   }
 
-   // original data was allocated so it should have been moved, not copied.
 
-   EXPECT_EQ(move_assigned.data(), old_data);
 
- }
 
- TEST(InlinedVectorTest, MoveAssignmentAllocatedAllocated) {
 
-   IntVec8 original;
 
-   FillVector(&original, kAllocatedFillSize);
 
-   IntVec8 move_assigned;
 
-   FillVector(&move_assigned, kAllocatedFillSize, 99);  // Add dummy elements
 
-   IntVec8 tmp(original);
 
-   auto* old_data = tmp.data();
 
-   move_assigned = std::move(tmp);
 
-   for (size_t i = 0; i < original.size(); ++i) {
 
-     EXPECT_EQ(original[i], move_assigned[i]);
 
-   }
 
-   // original data was allocated so it should have been moved, not copied.
 
-   EXPECT_EQ(move_assigned.data(), old_data);
 
- }
 
- // A copyable and movable value class, used to test that elements' copy
 
- // and move methods are called correctly.
 
- class Value {
 
-  public:
 
-   explicit Value(int v) : value_(MakeUnique<int>(v)) {}
 
-   // copyable
 
-   Value(const Value& v) {
 
-     value_ = MakeUnique<int>(*v.value_);
 
-     copied_ = true;
 
-   }
 
-   Value& operator=(const Value& v) {
 
-     value_ = MakeUnique<int>(*v.value_);
 
-     copied_ = true;
 
-     return *this;
 
-   }
 
-   // movable
 
-   Value(Value&& v) {
 
-     value_ = std::move(v.value_);
 
-     moved_ = true;
 
-   }
 
-   Value& operator=(Value&& v) {
 
-     value_ = std::move(v.value_);
 
-     moved_ = true;
 
-     return *this;
 
-   }
 
-   const UniquePtr<int>& value() const { return value_; }
 
-   bool copied() const { return copied_; }
 
-   bool moved() const { return moved_; }
 
-  private:
 
-   UniquePtr<int> value_;
 
-   bool copied_ = false;
 
-   bool moved_ = false;
 
- };
 
- TEST(InlinedVectorTest, CopyConstructorCopiesElementsInlined) {
 
-   InlinedVector<Value, 1> v1;
 
-   v1.emplace_back(3);
 
-   InlinedVector<Value, 1> v2(v1);
 
-   EXPECT_EQ(v2.size(), 1UL);
 
-   EXPECT_EQ(*v2[0].value(), 3);
 
-   // Addresses should differ.
 
-   EXPECT_NE(v1[0].value().get(), v2[0].value().get());
 
-   EXPECT_TRUE(v2[0].copied());
 
- }
 
- TEST(InlinedVectorTest, CopyConstructorCopiesElementsAllocated) {
 
-   InlinedVector<Value, 1> v1;
 
-   v1.reserve(2);
 
-   v1.emplace_back(3);
 
-   v1.emplace_back(5);
 
-   InlinedVector<Value, 1> v2(v1);
 
-   EXPECT_EQ(v2.size(), 2UL);
 
-   EXPECT_EQ(*v2[0].value(), 3);
 
-   EXPECT_EQ(*v2[1].value(), 5);
 
-   // Addresses should differ.
 
-   EXPECT_NE(v1[0].value().get(), v2[0].value().get());
 
-   EXPECT_NE(v1[1].value().get(), v2[1].value().get());
 
-   EXPECT_TRUE(v2[0].copied());
 
-   EXPECT_TRUE(v2[1].copied());
 
- }
 
- TEST(InlinedVectorTest, CopyAssignmentCopiesElementsInlined) {
 
-   InlinedVector<Value, 1> v1;
 
-   v1.emplace_back(3);
 
-   InlinedVector<Value, 1> v2;
 
-   EXPECT_EQ(v2.size(), 0UL);
 
-   v2 = v1;
 
-   EXPECT_EQ(v2.size(), 1UL);
 
-   EXPECT_EQ(*v2[0].value(), 3);
 
-   // Addresses should differ.
 
-   EXPECT_NE(v1[0].value().get(), v2[0].value().get());
 
-   EXPECT_TRUE(v2[0].copied());
 
- }
 
- TEST(InlinedVectorTest, CopyAssignmentCopiesElementsAllocated) {
 
-   InlinedVector<Value, 1> v1;
 
-   v1.reserve(2);
 
-   v1.emplace_back(3);
 
-   v1.emplace_back(5);
 
-   InlinedVector<Value, 1> v2;
 
-   EXPECT_EQ(v2.size(), 0UL);
 
-   v2 = v1;
 
-   EXPECT_EQ(v2.size(), 2UL);
 
-   EXPECT_EQ(*v2[0].value(), 3);
 
-   EXPECT_EQ(*v2[1].value(), 5);
 
-   // Addresses should differ.
 
-   EXPECT_NE(v1[0].value().get(), v2[0].value().get());
 
-   EXPECT_NE(v1[1].value().get(), v2[1].value().get());
 
-   EXPECT_TRUE(v2[0].copied());
 
-   EXPECT_TRUE(v2[1].copied());
 
- }
 
- TEST(InlinedVectorTest, MoveConstructorMovesElementsInlined) {
 
-   InlinedVector<Value, 1> v1;
 
-   v1.emplace_back(3);
 
-   int* addr = v1[0].value().get();
 
-   InlinedVector<Value, 1> v2(std::move(v1));
 
-   EXPECT_EQ(v2.size(), 1UL);
 
-   EXPECT_EQ(*v2[0].value(), 3);
 
-   EXPECT_EQ(addr, v2[0].value().get());
 
-   EXPECT_TRUE(v2[0].moved());
 
- }
 
- TEST(InlinedVectorTest, MoveConstructorMovesElementsAllocated) {
 
-   InlinedVector<Value, 1> v1;
 
-   v1.reserve(2);
 
-   v1.emplace_back(3);
 
-   v1.emplace_back(5);
 
-   int* addr1 = v1[0].value().get();
 
-   int* addr2 = v1[1].value().get();
 
-   Value* data1 = v1.data();
 
-   InlinedVector<Value, 1> v2(std::move(v1));
 
-   EXPECT_EQ(v2.size(), 2UL);
 
-   EXPECT_EQ(*v2[0].value(), 3);
 
-   EXPECT_EQ(*v2[1].value(), 5);
 
-   EXPECT_EQ(addr1, v2[0].value().get());
 
-   EXPECT_EQ(addr2, v2[1].value().get());
 
-   // In this case, elements won't be moved, because we have just stolen
 
-   // the underlying storage.
 
-   EXPECT_EQ(data1, v2.data());
 
- }
 
- TEST(InlinedVectorTest, MoveAssignmentMovesElementsInlined) {
 
-   InlinedVector<Value, 1> v1;
 
-   v1.emplace_back(3);
 
-   int* addr = v1[0].value().get();
 
-   InlinedVector<Value, 1> v2;
 
-   EXPECT_EQ(v2.size(), 0UL);
 
-   v2 = std::move(v1);
 
-   EXPECT_EQ(v2.size(), 1UL);
 
-   EXPECT_EQ(*v2[0].value(), 3);
 
-   EXPECT_EQ(addr, v2[0].value().get());
 
-   EXPECT_TRUE(v2[0].moved());
 
- }
 
- TEST(InlinedVectorTest, MoveAssignmentMovesElementsAllocated) {
 
-   InlinedVector<Value, 1> v1;
 
-   v1.reserve(2);
 
-   v1.emplace_back(3);
 
-   v1.emplace_back(5);
 
-   int* addr1 = v1[0].value().get();
 
-   int* addr2 = v1[1].value().get();
 
-   Value* data1 = v1.data();
 
-   InlinedVector<Value, 1> v2;
 
-   EXPECT_EQ(v2.size(), 0UL);
 
-   v2 = std::move(v1);
 
-   EXPECT_EQ(v2.size(), 2UL);
 
-   EXPECT_EQ(*v2[0].value(), 3);
 
-   EXPECT_EQ(*v2[1].value(), 5);
 
-   EXPECT_EQ(addr1, v2[0].value().get());
 
-   EXPECT_EQ(addr2, v2[1].value().get());
 
-   // In this case, elements won't be moved, because we have just stolen
 
-   // the underlying storage.
 
-   EXPECT_EQ(data1, v2.data());
 
- }
 
- TEST(InlinedVectorTest, PopBackInlined) {
 
-   InlinedVector<UniquePtr<int>, 2> v;
 
-   // Add two elements, pop one out
 
-   v.push_back(MakeUnique<int>(3));
 
-   EXPECT_EQ(1UL, v.size());
 
-   EXPECT_EQ(3, *v[0]);
 
-   v.push_back(MakeUnique<int>(5));
 
-   EXPECT_EQ(2UL, v.size());
 
-   EXPECT_EQ(5, *v[1]);
 
-   v.pop_back();
 
-   EXPECT_EQ(1UL, v.size());
 
- }
 
- TEST(InlinedVectorTest, PopBackAllocated) {
 
-   const int kInlinedSize = 2;
 
-   InlinedVector<UniquePtr<int>, kInlinedSize> v;
 
-   // Add elements to ensure allocated backing.
 
-   for (size_t i = 0; i < kInlinedSize + 1; ++i) {
 
-     v.push_back(MakeUnique<int>(3));
 
-     EXPECT_EQ(i + 1, v.size());
 
-   }
 
-   size_t sz = v.size();
 
-   v.pop_back();
 
-   EXPECT_EQ(sz - 1, v.size());
 
- }
 
- }  // namespace testing
 
- }  // namespace grpc_core
 
- int main(int argc, char** argv) {
 
-   grpc::testing::TestEnvironment env(argc, argv);
 
-   ::testing::InitGoogleTest(&argc, argv);
 
-   return RUN_ALL_TESTS();
 
- }
 
 
  |