|  | @@ -17,20 +17,32 @@
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #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());
 | 
	
		
			
				|  |  | -  for (int i = 0; i < kNumElements; ++i) {
 | 
	
		
			
				|  |  | -    v.push_back(i);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  FillVector(&v, kNumElements);
 | 
	
		
			
				|  |  |    EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
 | 
	
		
			
				|  |  |    EXPECT_FALSE(v.empty());
 | 
	
		
			
				|  |  |    for (int i = 0; i < kNumElements; ++i) {
 | 
	
	
		
			
				|  | @@ -42,9 +54,7 @@ TEST(InlinedVectorTest, CreateAndIterate) {
 | 
	
		
			
				|  |  |  TEST(InlinedVectorTest, ValuesAreInlined) {
 | 
	
		
			
				|  |  |    const int kNumElements = 5;
 | 
	
		
			
				|  |  |    InlinedVector<int, 10> v;
 | 
	
		
			
				|  |  | -  for (int i = 0; i < kNumElements; ++i) {
 | 
	
		
			
				|  |  | -    v.push_back(i);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  FillVector(&v, kNumElements);
 | 
	
		
			
				|  |  |    EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
 | 
	
		
			
				|  |  |    for (int i = 0; i < kNumElements; ++i) {
 | 
	
		
			
				|  |  |      EXPECT_EQ(i, v[i]);
 | 
	
	
		
			
				|  | @@ -71,19 +81,13 @@ TEST(InlinedVectorTest, ClearAndRepopulate) {
 | 
	
		
			
				|  |  |    const int kNumElements = 10;
 | 
	
		
			
				|  |  |    InlinedVector<int, 5> v;
 | 
	
		
			
				|  |  |    EXPECT_EQ(0UL, v.size());
 | 
	
		
			
				|  |  | -  for (int i = 0; i < kNumElements; ++i) {
 | 
	
		
			
				|  |  | -    v.push_back(i);
 | 
	
		
			
				|  |  | -    EXPECT_EQ(i + 1UL, v.size());
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  FillVector(&v, kNumElements);
 | 
	
		
			
				|  |  |    for (int i = 0; i < kNumElements; ++i) {
 | 
	
		
			
				|  |  |      EXPECT_EQ(i, v[i]);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    v.clear();
 | 
	
		
			
				|  |  |    EXPECT_EQ(0UL, v.size());
 | 
	
		
			
				|  |  | -  for (int i = 0; i < kNumElements; ++i) {
 | 
	
		
			
				|  |  | -    v.push_back(kNumElements + i);
 | 
	
		
			
				|  |  | -    EXPECT_EQ(i + 1UL, v.size());
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | +  FillVector(&v, kNumElements, kNumElements);
 | 
	
		
			
				|  |  |    for (int i = 0; i < kNumElements; ++i) {
 | 
	
		
			
				|  |  |      EXPECT_EQ(kNumElements + i, v[i]);
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -93,10 +97,7 @@ TEST(InlinedVectorTest, ConstIndexOperator) {
 | 
	
		
			
				|  |  |    constexpr int kNumElements = 10;
 | 
	
		
			
				|  |  |    InlinedVector<int, 5> v;
 | 
	
		
			
				|  |  |    EXPECT_EQ(0UL, v.size());
 | 
	
		
			
				|  |  | -  for (int i = 0; i < kNumElements; ++i) {
 | 
	
		
			
				|  |  | -    v.push_back(i);
 | 
	
		
			
				|  |  | -    EXPECT_EQ(i + 1UL, 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.
 | 
	
	
		
			
				|  | @@ -108,6 +109,161 @@ TEST(InlinedVectorTest, ConstIndexOperator) {
 | 
	
		
			
				|  |  |    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, CopyConstructerInlined) {
 | 
	
		
			
				|  |  | +  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, CopyConstructerAllocated) {
 | 
	
		
			
				|  |  | +  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);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  }  // namespace testing
 | 
	
		
			
				|  |  |  }  // namespace grpc_core
 | 
	
		
			
				|  |  |  
 |