• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2017 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #include "src/core/lib/gprpp/inlined_vector.h"
20 #include <grpc/support/log.h>
21 #include <gtest/gtest.h>
22 #include "src/core/lib/gprpp/memory.h"
23 #include "test/core/util/test_config.h"
24 
25 namespace grpc_core {
26 namespace testing {
27 namespace {
28 
29 template <typename Vector>
FillVector(Vector * v,int len,int start=0)30 static void FillVector(Vector* v, int len, int start = 0) {
31   for (int i = 0; i < len; i++) {
32     v->push_back(i + start);
33     EXPECT_EQ(i + 1UL, v->size());
34   }
35   EXPECT_EQ(static_cast<size_t>(len), v->size());
36   EXPECT_LE(static_cast<size_t>(len), v->capacity());
37 }
38 
39 }  // namespace
40 
TEST(InlinedVectorTest,CreateAndIterate)41 TEST(InlinedVectorTest, CreateAndIterate) {
42   const int kNumElements = 9;
43   InlinedVector<int, 2> v;
44   EXPECT_TRUE(v.empty());
45   FillVector(&v, kNumElements);
46   EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
47   EXPECT_FALSE(v.empty());
48   for (int i = 0; i < kNumElements; ++i) {
49     EXPECT_EQ(i, v[i]);
50     EXPECT_EQ(i, &v[i] - &v[0]);  // Ensure contiguous allocation.
51   }
52 }
53 
TEST(InlinedVectorTest,ValuesAreInlined)54 TEST(InlinedVectorTest, ValuesAreInlined) {
55   const int kNumElements = 5;
56   InlinedVector<int, 10> v;
57   FillVector(&v, kNumElements);
58   EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
59   for (int i = 0; i < kNumElements; ++i) {
60     EXPECT_EQ(i, v[i]);
61   }
62 }
63 
TEST(InlinedVectorTest,PushBackWithMove)64 TEST(InlinedVectorTest, PushBackWithMove) {
65   InlinedVector<UniquePtr<int>, 1> v;
66   UniquePtr<int> i = MakeUnique<int>(3);
67   v.push_back(std::move(i));
68   EXPECT_EQ(nullptr, i.get());
69   EXPECT_EQ(1UL, v.size());
70   EXPECT_EQ(3, *v[0]);
71 }
72 
TEST(InlinedVectorTest,EmplaceBack)73 TEST(InlinedVectorTest, EmplaceBack) {
74   InlinedVector<UniquePtr<int>, 1> v;
75   v.emplace_back(New<int>(3));
76   EXPECT_EQ(1UL, v.size());
77   EXPECT_EQ(3, *v[0]);
78 }
79 
TEST(InlinedVectorTest,ClearAndRepopulate)80 TEST(InlinedVectorTest, ClearAndRepopulate) {
81   const int kNumElements = 10;
82   InlinedVector<int, 5> v;
83   EXPECT_EQ(0UL, v.size());
84   FillVector(&v, kNumElements);
85   for (int i = 0; i < kNumElements; ++i) {
86     EXPECT_EQ(i, v[i]);
87   }
88   v.clear();
89   EXPECT_EQ(0UL, v.size());
90   FillVector(&v, kNumElements, kNumElements);
91   for (int i = 0; i < kNumElements; ++i) {
92     EXPECT_EQ(kNumElements + i, v[i]);
93   }
94 }
95 
TEST(InlinedVectorTest,ConstIndexOperator)96 TEST(InlinedVectorTest, ConstIndexOperator) {
97   constexpr int kNumElements = 10;
98   InlinedVector<int, 5> v;
99   EXPECT_EQ(0UL, v.size());
100   FillVector(&v, kNumElements);
101   // The following lambda function is exceptionally allowed to use an anonymous
102   // capture due to the erroneous behavior of the MSVC compiler, that refuses to
103   // capture the kNumElements constexpr, something allowed by the standard.
104   auto const_func = [&](const InlinedVector<int, 5>& v) {
105     for (int i = 0; i < kNumElements; ++i) {
106       EXPECT_EQ(i, v[i]);
107     }
108   };
109   const_func(v);
110 }
111 
112 // the following constants and typedefs are used for copy/move
113 // construction/assignment
114 const size_t kInlinedLength = 8;
115 typedef InlinedVector<int, kInlinedLength> IntVec8;
116 const size_t kInlinedFillSize = kInlinedLength - 1;
117 const size_t kAllocatedFillSize = kInlinedLength + 1;
118 
TEST(InlinedVectorTest,CopyConstructerInlined)119 TEST(InlinedVectorTest, CopyConstructerInlined) {
120   IntVec8 original;
121   FillVector(&original, kInlinedFillSize);
122   IntVec8 copy_constructed(original);
123   for (size_t i = 0; i < original.size(); ++i) {
124     EXPECT_EQ(original[i], copy_constructed[i]);
125   }
126 }
127 
TEST(InlinedVectorTest,CopyConstructerAllocated)128 TEST(InlinedVectorTest, CopyConstructerAllocated) {
129   IntVec8 original;
130   FillVector(&original, kAllocatedFillSize);
131   IntVec8 copy_constructed(original);
132   for (size_t i = 0; i < original.size(); ++i) {
133     EXPECT_EQ(original[i], copy_constructed[i]);
134   }
135 }
136 
TEST(InlinedVectorTest,CopyAssignementInlinedInlined)137 TEST(InlinedVectorTest, CopyAssignementInlinedInlined) {
138   IntVec8 original;
139   FillVector(&original, kInlinedFillSize);
140   IntVec8 copy_assigned;
141   FillVector(&copy_assigned, kInlinedFillSize, 99);
142   copy_assigned = original;
143   for (size_t i = 0; i < original.size(); ++i) {
144     EXPECT_EQ(original[i], copy_assigned[i]);
145   }
146 }
147 
TEST(InlinedVectorTest,CopyAssignementInlinedAllocated)148 TEST(InlinedVectorTest, CopyAssignementInlinedAllocated) {
149   IntVec8 original;
150   FillVector(&original, kInlinedFillSize);
151   IntVec8 copy_assigned;
152   FillVector(&copy_assigned, kAllocatedFillSize, 99);
153   copy_assigned = original;
154   for (size_t i = 0; i < original.size(); ++i) {
155     EXPECT_EQ(original[i], copy_assigned[i]);
156   }
157 }
158 
TEST(InlinedVectorTest,CopyAssignementAllocatedInlined)159 TEST(InlinedVectorTest, CopyAssignementAllocatedInlined) {
160   IntVec8 original;
161   FillVector(&original, kAllocatedFillSize);
162   IntVec8 copy_assigned;
163   FillVector(&copy_assigned, kInlinedFillSize, 99);
164   copy_assigned = original;
165   for (size_t i = 0; i < original.size(); ++i) {
166     EXPECT_EQ(original[i], copy_assigned[i]);
167   }
168 }
169 
TEST(InlinedVectorTest,CopyAssignementAllocatedAllocated)170 TEST(InlinedVectorTest, CopyAssignementAllocatedAllocated) {
171   IntVec8 original;
172   FillVector(&original, kAllocatedFillSize);
173   IntVec8 copy_assigned;
174   FillVector(&copy_assigned, kAllocatedFillSize, 99);
175   copy_assigned = original;
176   for (size_t i = 0; i < original.size(); ++i) {
177     EXPECT_EQ(original[i], copy_assigned[i]);
178   }
179 }
180 
TEST(InlinedVectorTest,MoveConstructorInlined)181 TEST(InlinedVectorTest, MoveConstructorInlined) {
182   IntVec8 original;
183   FillVector(&original, kInlinedFillSize);
184   IntVec8 tmp(original);
185   auto* old_data = tmp.data();
186   IntVec8 move_constructed(std::move(tmp));
187   for (size_t i = 0; i < original.size(); ++i) {
188     EXPECT_EQ(original[i], move_constructed[i]);
189   }
190   // original data was inlined so it should have been copied, not moved.
191   EXPECT_NE(move_constructed.data(), old_data);
192 }
193 
TEST(InlinedVectorTest,MoveConstructorAllocated)194 TEST(InlinedVectorTest, MoveConstructorAllocated) {
195   IntVec8 original;
196   FillVector(&original, kAllocatedFillSize);
197   IntVec8 tmp(original);
198   auto* old_data = tmp.data();
199   IntVec8 move_constructed(std::move(tmp));
200   for (size_t i = 0; i < original.size(); ++i) {
201     EXPECT_EQ(original[i], move_constructed[i]);
202   }
203   // original data was allocated, so it should been moved, not copied
204   EXPECT_EQ(move_constructed.data(), old_data);
205 }
206 
TEST(InlinedVectorTest,MoveAssignmentInlinedInlined)207 TEST(InlinedVectorTest, MoveAssignmentInlinedInlined) {
208   IntVec8 original;
209   FillVector(&original, kInlinedFillSize);
210   IntVec8 move_assigned;
211   FillVector(&move_assigned, kInlinedFillSize, 99);  // Add dummy elements
212   IntVec8 tmp(original);
213   auto* old_data = tmp.data();
214   move_assigned = std::move(tmp);
215   for (size_t i = 0; i < original.size(); ++i) {
216     EXPECT_EQ(original[i], move_assigned[i]);
217   }
218   // original data was inlined so it should have been copied, not moved.
219   EXPECT_NE(move_assigned.data(), old_data);
220 }
221 
TEST(InlinedVectorTest,MoveAssignmentInlinedAllocated)222 TEST(InlinedVectorTest, MoveAssignmentInlinedAllocated) {
223   IntVec8 original;
224   FillVector(&original, kInlinedFillSize);
225   IntVec8 move_assigned;
226   FillVector(&move_assigned, kAllocatedFillSize, 99);  // Add dummy elements
227   IntVec8 tmp(original);
228   auto* old_data = tmp.data();
229   move_assigned = std::move(tmp);
230   for (size_t i = 0; i < original.size(); ++i) {
231     EXPECT_EQ(original[i], move_assigned[i]);
232   }
233   // original data was inlined so it should have been copied, not moved.
234   EXPECT_NE(move_assigned.data(), old_data);
235 }
236 
TEST(InlinedVectorTest,MoveAssignmentAllocatedInlined)237 TEST(InlinedVectorTest, MoveAssignmentAllocatedInlined) {
238   IntVec8 original;
239   FillVector(&original, kAllocatedFillSize);
240   IntVec8 move_assigned;
241   FillVector(&move_assigned, kInlinedFillSize, 99);  // Add dummy elements
242   IntVec8 tmp(original);
243   auto* old_data = tmp.data();
244   move_assigned = std::move(tmp);
245   for (size_t i = 0; i < original.size(); ++i) {
246     EXPECT_EQ(original[i], move_assigned[i]);
247   }
248   // original data was allocated so it should have been moved, not copied.
249   EXPECT_EQ(move_assigned.data(), old_data);
250 }
251 
TEST(InlinedVectorTest,MoveAssignmentAllocatedAllocated)252 TEST(InlinedVectorTest, MoveAssignmentAllocatedAllocated) {
253   IntVec8 original;
254   FillVector(&original, kAllocatedFillSize);
255   IntVec8 move_assigned;
256   FillVector(&move_assigned, kAllocatedFillSize, 99);  // Add dummy elements
257   IntVec8 tmp(original);
258   auto* old_data = tmp.data();
259   move_assigned = std::move(tmp);
260   for (size_t i = 0; i < original.size(); ++i) {
261     EXPECT_EQ(original[i], move_assigned[i]);
262   }
263   // original data was allocated so it should have been moved, not copied.
264   EXPECT_EQ(move_assigned.data(), old_data);
265 }
266 
267 }  // namespace testing
268 }  // namespace grpc_core
269 
main(int argc,char ** argv)270 int main(int argc, char** argv) {
271   grpc_test_init(argc, argv);
272   ::testing::InitGoogleTest(&argc, argv);
273   return RUN_ALL_TESTS();
274 }
275