1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "absl/container/internal/layout.h"
16
17 // We need ::max_align_t because some libstdc++ versions don't provide
18 // std::max_align_t
19 #include <stddef.h>
20
21 #include <cstdint>
22 #include <cstring>
23 #include <initializer_list>
24 #include <memory>
25 #include <ostream>
26 #include <string>
27 #include <tuple>
28 #include <type_traits>
29
30 #include "gmock/gmock.h"
31 #include "gtest/gtest.h"
32 #include "absl/base/config.h"
33 #include "absl/log/check.h"
34 #include "absl/types/span.h"
35 #include "absl/utility/utility.h"
36
37 namespace absl {
38 ABSL_NAMESPACE_BEGIN
39 namespace container_internal {
40 namespace {
41
42 using ::absl::Span;
43 using ::testing::ElementsAre;
44
Distance(const void * from,const void * to)45 size_t Distance(const void* from, const void* to) {
46 CHECK_LE(from, to) << "Distance must be non-negative";
47 return static_cast<const char*>(to) - static_cast<const char*>(from);
48 }
49
50 template <class Expected, class Actual>
Type(Actual val)51 Expected Type(Actual val) {
52 static_assert(std::is_same<Expected, Actual>(), "");
53 return val;
54 }
55
56 // Helper classes to test different size and alignments.
57 struct alignas(8) Int128 {
58 uint64_t a, b;
operator ==(Int128 lhs,Int128 rhs)59 friend bool operator==(Int128 lhs, Int128 rhs) {
60 return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b);
61 }
62
Nameabsl::container_internal::__anon7a58ff470111::Int12863 static std::string Name() {
64 return internal_layout::adl_barrier::TypeName<Int128>();
65 }
66 };
67
68 // int64_t is *not* 8-byte aligned on all platforms!
69 struct alignas(8) Int64 {
70 int64_t a;
operator ==(Int64 lhs,Int64 rhs)71 friend bool operator==(Int64 lhs, Int64 rhs) {
72 return lhs.a == rhs.a;
73 }
74 };
75
76 // Properties of types that this test relies on.
77 static_assert(sizeof(int8_t) == 1, "");
78 static_assert(alignof(int8_t) == 1, "");
79 static_assert(sizeof(int16_t) == 2, "");
80 static_assert(alignof(int16_t) == 2, "");
81 static_assert(sizeof(int32_t) == 4, "");
82 static_assert(alignof(int32_t) == 4, "");
83 static_assert(sizeof(Int64) == 8, "");
84 static_assert(alignof(Int64) == 8, "");
85 static_assert(sizeof(Int128) == 16, "");
86 static_assert(alignof(Int128) == 8, "");
87
88 template <class Expected, class Actual>
SameType()89 void SameType() {
90 static_assert(std::is_same<Expected, Actual>(), "");
91 }
92
TEST(Layout,ElementType)93 TEST(Layout, ElementType) {
94 {
95 using L = Layout<int32_t>;
96 SameType<int32_t, L::ElementType<0>>();
97 SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
98 SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
99 }
100 {
101 using L = Layout<int32_t, int32_t>;
102 SameType<int32_t, L::ElementType<0>>();
103 SameType<int32_t, L::ElementType<1>>();
104 SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
105 SameType<int32_t, decltype(L::Partial())::ElementType<1>>();
106 SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
107 SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
108 }
109 {
110 using L = Layout<int8_t, int32_t, Int128>;
111 SameType<int8_t, L::ElementType<0>>();
112 SameType<int32_t, L::ElementType<1>>();
113 SameType<Int128, L::ElementType<2>>();
114 SameType<int8_t, decltype(L::Partial())::ElementType<0>>();
115 SameType<int8_t, decltype(L::Partial(0))::ElementType<0>>();
116 SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
117 SameType<int8_t, decltype(L::Partial(0, 0))::ElementType<0>>();
118 SameType<int32_t, decltype(L::Partial(0, 0))::ElementType<1>>();
119 SameType<Int128, decltype(L::Partial(0, 0))::ElementType<2>>();
120 SameType<int8_t, decltype(L::Partial(0, 0, 0))::ElementType<0>>();
121 SameType<int32_t, decltype(L::Partial(0, 0, 0))::ElementType<1>>();
122 SameType<Int128, decltype(L::Partial(0, 0, 0))::ElementType<2>>();
123 }
124 }
125
TEST(Layout,ElementTypes)126 TEST(Layout, ElementTypes) {
127 {
128 using L = Layout<int32_t>;
129 SameType<std::tuple<int32_t>, L::ElementTypes>();
130 SameType<std::tuple<int32_t>, decltype(L::Partial())::ElementTypes>();
131 SameType<std::tuple<int32_t>, decltype(L::Partial(0))::ElementTypes>();
132 }
133 {
134 using L = Layout<int32_t, int32_t>;
135 SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();
136 SameType<std::tuple<int32_t, int32_t>,
137 decltype(L::Partial())::ElementTypes>();
138 SameType<std::tuple<int32_t, int32_t>,
139 decltype(L::Partial(0))::ElementTypes>();
140 }
141 {
142 using L = Layout<int8_t, int32_t, Int128>;
143 SameType<std::tuple<int8_t, int32_t, Int128>, L::ElementTypes>();
144 SameType<std::tuple<int8_t, int32_t, Int128>,
145 decltype(L::Partial())::ElementTypes>();
146 SameType<std::tuple<int8_t, int32_t, Int128>,
147 decltype(L::Partial(0))::ElementTypes>();
148 SameType<std::tuple<int8_t, int32_t, Int128>,
149 decltype(L::Partial(0, 0))::ElementTypes>();
150 SameType<std::tuple<int8_t, int32_t, Int128>,
151 decltype(L::Partial(0, 0, 0))::ElementTypes>();
152 }
153 }
154
TEST(Layout,OffsetByIndex)155 TEST(Layout, OffsetByIndex) {
156 {
157 using L = Layout<int32_t>;
158 EXPECT_EQ(0, L::Partial().Offset<0>());
159 EXPECT_EQ(0, L::Partial(3).Offset<0>());
160 EXPECT_EQ(0, L(3).Offset<0>());
161 }
162 {
163 using L = Layout<int32_t, int32_t>;
164 EXPECT_EQ(0, L::Partial().Offset<0>());
165 EXPECT_EQ(0, L::Partial(3).Offset<0>());
166 EXPECT_EQ(12, L::Partial(3).Offset<1>());
167 EXPECT_EQ(0, L::Partial(3, 5).Offset<0>());
168 EXPECT_EQ(12, L::Partial(3, 5).Offset<1>());
169 EXPECT_EQ(0, L(3, 5).Offset<0>());
170 EXPECT_EQ(12, L(3, 5).Offset<1>());
171 }
172 {
173 using L = Layout<int8_t, int32_t, Int128>;
174 EXPECT_EQ(0, L::Partial().Offset<0>());
175 EXPECT_EQ(0, L::Partial(0).Offset<0>());
176 EXPECT_EQ(0, L::Partial(0).Offset<1>());
177 EXPECT_EQ(0, L::Partial(1).Offset<0>());
178 EXPECT_EQ(4, L::Partial(1).Offset<1>());
179 EXPECT_EQ(0, L::Partial(5).Offset<0>());
180 EXPECT_EQ(8, L::Partial(5).Offset<1>());
181 EXPECT_EQ(0, L::Partial(0, 0).Offset<0>());
182 EXPECT_EQ(0, L::Partial(0, 0).Offset<1>());
183 EXPECT_EQ(0, L::Partial(0, 0).Offset<2>());
184 EXPECT_EQ(0, L::Partial(1, 0).Offset<0>());
185 EXPECT_EQ(4, L::Partial(1, 0).Offset<1>());
186 EXPECT_EQ(8, L::Partial(1, 0).Offset<2>());
187 EXPECT_EQ(0, L::Partial(5, 3).Offset<0>());
188 EXPECT_EQ(8, L::Partial(5, 3).Offset<1>());
189 EXPECT_EQ(24, L::Partial(5, 3).Offset<2>());
190 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<0>());
191 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<1>());
192 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<2>());
193 EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<0>());
194 EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<1>());
195 EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<2>());
196 EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<0>());
197 EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<2>());
198 EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<1>());
199 EXPECT_EQ(0, L(5, 3, 1).Offset<0>());
200 EXPECT_EQ(24, L(5, 3, 1).Offset<2>());
201 EXPECT_EQ(8, L(5, 3, 1).Offset<1>());
202 }
203 }
204
TEST(Layout,OffsetByType)205 TEST(Layout, OffsetByType) {
206 {
207 using L = Layout<int32_t>;
208 EXPECT_EQ(0, L::Partial().Offset<int32_t>());
209 EXPECT_EQ(0, L::Partial(3).Offset<int32_t>());
210 EXPECT_EQ(0, L(3).Offset<int32_t>());
211 }
212 {
213 using L = Layout<int8_t, int32_t, Int128>;
214 EXPECT_EQ(0, L::Partial().Offset<int8_t>());
215 EXPECT_EQ(0, L::Partial(0).Offset<int8_t>());
216 EXPECT_EQ(0, L::Partial(0).Offset<int32_t>());
217 EXPECT_EQ(0, L::Partial(1).Offset<int8_t>());
218 EXPECT_EQ(4, L::Partial(1).Offset<int32_t>());
219 EXPECT_EQ(0, L::Partial(5).Offset<int8_t>());
220 EXPECT_EQ(8, L::Partial(5).Offset<int32_t>());
221 EXPECT_EQ(0, L::Partial(0, 0).Offset<int8_t>());
222 EXPECT_EQ(0, L::Partial(0, 0).Offset<int32_t>());
223 EXPECT_EQ(0, L::Partial(0, 0).Offset<Int128>());
224 EXPECT_EQ(0, L::Partial(1, 0).Offset<int8_t>());
225 EXPECT_EQ(4, L::Partial(1, 0).Offset<int32_t>());
226 EXPECT_EQ(8, L::Partial(1, 0).Offset<Int128>());
227 EXPECT_EQ(0, L::Partial(5, 3).Offset<int8_t>());
228 EXPECT_EQ(8, L::Partial(5, 3).Offset<int32_t>());
229 EXPECT_EQ(24, L::Partial(5, 3).Offset<Int128>());
230 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int8_t>());
231 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int32_t>());
232 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<Int128>());
233 EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<int8_t>());
234 EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<int32_t>());
235 EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<Int128>());
236 EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<int8_t>());
237 EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<Int128>());
238 EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<int32_t>());
239 EXPECT_EQ(0, L(5, 3, 1).Offset<int8_t>());
240 EXPECT_EQ(24, L(5, 3, 1).Offset<Int128>());
241 EXPECT_EQ(8, L(5, 3, 1).Offset<int32_t>());
242 }
243 }
244
TEST(Layout,Offsets)245 TEST(Layout, Offsets) {
246 {
247 using L = Layout<int32_t>;
248 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
249 EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0));
250 EXPECT_THAT(L(3).Offsets(), ElementsAre(0));
251 }
252 {
253 using L = Layout<int32_t, int32_t>;
254 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
255 EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0, 12));
256 EXPECT_THAT(L::Partial(3, 5).Offsets(), ElementsAre(0, 12));
257 EXPECT_THAT(L(3, 5).Offsets(), ElementsAre(0, 12));
258 }
259 {
260 using L = Layout<int8_t, int32_t, Int128>;
261 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
262 EXPECT_THAT(L::Partial(1).Offsets(), ElementsAre(0, 4));
263 EXPECT_THAT(L::Partial(5).Offsets(), ElementsAre(0, 8));
264 EXPECT_THAT(L::Partial(0, 0).Offsets(), ElementsAre(0, 0, 0));
265 EXPECT_THAT(L::Partial(1, 0).Offsets(), ElementsAre(0, 4, 8));
266 EXPECT_THAT(L::Partial(5, 3).Offsets(), ElementsAre(0, 8, 24));
267 EXPECT_THAT(L::Partial(0, 0, 0).Offsets(), ElementsAre(0, 0, 0));
268 EXPECT_THAT(L::Partial(1, 0, 0).Offsets(), ElementsAre(0, 4, 8));
269 EXPECT_THAT(L::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
270 EXPECT_THAT(L(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
271 }
272 }
273
TEST(Layout,AllocSize)274 TEST(Layout, AllocSize) {
275 {
276 using L = Layout<int32_t>;
277 EXPECT_EQ(0, L::Partial(0).AllocSize());
278 EXPECT_EQ(12, L::Partial(3).AllocSize());
279 EXPECT_EQ(12, L(3).AllocSize());
280 }
281 {
282 using L = Layout<int32_t, int32_t>;
283 EXPECT_EQ(32, L::Partial(3, 5).AllocSize());
284 EXPECT_EQ(32, L(3, 5).AllocSize());
285 }
286 {
287 using L = Layout<int8_t, int32_t, Int128>;
288 EXPECT_EQ(0, L::Partial(0, 0, 0).AllocSize());
289 EXPECT_EQ(8, L::Partial(1, 0, 0).AllocSize());
290 EXPECT_EQ(8, L::Partial(0, 1, 0).AllocSize());
291 EXPECT_EQ(16, L::Partial(0, 0, 1).AllocSize());
292 EXPECT_EQ(24, L::Partial(1, 1, 1).AllocSize());
293 EXPECT_EQ(136, L::Partial(3, 5, 7).AllocSize());
294 EXPECT_EQ(136, L(3, 5, 7).AllocSize());
295 }
296 }
297
TEST(Layout,SizeByIndex)298 TEST(Layout, SizeByIndex) {
299 {
300 using L = Layout<int32_t>;
301 EXPECT_EQ(0, L::Partial(0).Size<0>());
302 EXPECT_EQ(3, L::Partial(3).Size<0>());
303 EXPECT_EQ(3, L(3).Size<0>());
304 }
305 {
306 using L = Layout<int32_t, int32_t>;
307 EXPECT_EQ(0, L::Partial(0).Size<0>());
308 EXPECT_EQ(3, L::Partial(3).Size<0>());
309 EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
310 EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
311 EXPECT_EQ(3, L(3, 5).Size<0>());
312 EXPECT_EQ(5, L(3, 5).Size<1>());
313 }
314 {
315 using L = Layout<int8_t, int32_t, Int128>;
316 EXPECT_EQ(3, L::Partial(3).Size<0>());
317 EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
318 EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
319 EXPECT_EQ(3, L::Partial(3, 5, 7).Size<0>());
320 EXPECT_EQ(5, L::Partial(3, 5, 7).Size<1>());
321 EXPECT_EQ(7, L::Partial(3, 5, 7).Size<2>());
322 EXPECT_EQ(3, L(3, 5, 7).Size<0>());
323 EXPECT_EQ(5, L(3, 5, 7).Size<1>());
324 EXPECT_EQ(7, L(3, 5, 7).Size<2>());
325 }
326 }
327
TEST(Layout,SizeByType)328 TEST(Layout, SizeByType) {
329 {
330 using L = Layout<int32_t>;
331 EXPECT_EQ(0, L::Partial(0).Size<int32_t>());
332 EXPECT_EQ(3, L::Partial(3).Size<int32_t>());
333 EXPECT_EQ(3, L(3).Size<int32_t>());
334 }
335 {
336 using L = Layout<int8_t, int32_t, Int128>;
337 EXPECT_EQ(3, L::Partial(3).Size<int8_t>());
338 EXPECT_EQ(3, L::Partial(3, 5).Size<int8_t>());
339 EXPECT_EQ(5, L::Partial(3, 5).Size<int32_t>());
340 EXPECT_EQ(3, L::Partial(3, 5, 7).Size<int8_t>());
341 EXPECT_EQ(5, L::Partial(3, 5, 7).Size<int32_t>());
342 EXPECT_EQ(7, L::Partial(3, 5, 7).Size<Int128>());
343 EXPECT_EQ(3, L(3, 5, 7).Size<int8_t>());
344 EXPECT_EQ(5, L(3, 5, 7).Size<int32_t>());
345 EXPECT_EQ(7, L(3, 5, 7).Size<Int128>());
346 }
347 }
348
TEST(Layout,Sizes)349 TEST(Layout, Sizes) {
350 {
351 using L = Layout<int32_t>;
352 EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
353 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
354 EXPECT_THAT(L(3).Sizes(), ElementsAre(3));
355 }
356 {
357 using L = Layout<int32_t, int32_t>;
358 EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
359 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
360 EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
361 EXPECT_THAT(L(3, 5).Sizes(), ElementsAre(3, 5));
362 }
363 {
364 using L = Layout<int8_t, int32_t, Int128>;
365 EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
366 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
367 EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
368 EXPECT_THAT(L::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
369 EXPECT_THAT(L(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
370 }
371 }
372
TEST(Layout,PointerByIndex)373 TEST(Layout, PointerByIndex) {
374 alignas(max_align_t) const unsigned char p[100] = {0};
375 {
376 using L = Layout<int32_t>;
377 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
378 EXPECT_EQ(0,
379 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
380 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));
381 }
382 {
383 using L = Layout<int32_t, int32_t>;
384 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
385 EXPECT_EQ(0,
386 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
387 EXPECT_EQ(12,
388 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
389 EXPECT_EQ(
390 0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
391 EXPECT_EQ(
392 12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
393 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));
394 EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));
395 }
396 {
397 using L = Layout<int8_t, int32_t, Int128>;
398 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));
399 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));
400 EXPECT_EQ(0,
401 Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
402 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));
403 EXPECT_EQ(4,
404 Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
405 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));
406 EXPECT_EQ(8,
407 Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
408 EXPECT_EQ(0,
409 Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
410 EXPECT_EQ(
411 0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
412 EXPECT_EQ(0,
413 Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));
414 EXPECT_EQ(0,
415 Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
416 EXPECT_EQ(
417 4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
418 EXPECT_EQ(8,
419 Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));
420 EXPECT_EQ(0,
421 Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
422 EXPECT_EQ(
423 8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
424 EXPECT_EQ(24,
425 Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));
426 EXPECT_EQ(
427 0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
428 EXPECT_EQ(
429 0,
430 Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
431 EXPECT_EQ(
432 0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
433 EXPECT_EQ(
434 0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
435 EXPECT_EQ(
436 4,
437 Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
438 EXPECT_EQ(
439 8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
440 EXPECT_EQ(
441 0, Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
442 EXPECT_EQ(
443 24,
444 Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
445 EXPECT_EQ(
446 8,
447 Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
448 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));
449 EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));
450 EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));
451 }
452 }
453
TEST(Layout,PointerByType)454 TEST(Layout, PointerByType) {
455 alignas(max_align_t) const unsigned char p[100] = {0};
456 {
457 using L = Layout<int32_t>;
458 EXPECT_EQ(
459 0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
460 EXPECT_EQ(
461 0,
462 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
463 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));
464 }
465 {
466 using L = Layout<int8_t, int32_t, Int128>;
467 EXPECT_EQ(
468 0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
469 EXPECT_EQ(
470 0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
471 EXPECT_EQ(
472 0,
473 Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
474 EXPECT_EQ(
475 0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
476 EXPECT_EQ(
477 4,
478 Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
479 EXPECT_EQ(
480 0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
481 EXPECT_EQ(
482 8,
483 Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
484 EXPECT_EQ(
485 0,
486 Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
487 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
488 L::Partial(0, 0).Pointer<int32_t>(p))));
489 EXPECT_EQ(
490 0,
491 Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
492 EXPECT_EQ(
493 0,
494 Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
495 EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
496 L::Partial(1, 0).Pointer<int32_t>(p))));
497 EXPECT_EQ(
498 8,
499 Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
500 EXPECT_EQ(
501 0,
502 Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
503 EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
504 L::Partial(5, 3).Pointer<int32_t>(p))));
505 EXPECT_EQ(
506 24,
507 Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
508 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
509 L::Partial(0, 0, 0).Pointer<int8_t>(p))));
510 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
511 L::Partial(0, 0, 0).Pointer<int32_t>(p))));
512 EXPECT_EQ(0, Distance(p, Type<const Int128*>(
513 L::Partial(0, 0, 0).Pointer<Int128>(p))));
514 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
515 L::Partial(1, 0, 0).Pointer<int8_t>(p))));
516 EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
517 L::Partial(1, 0, 0).Pointer<int32_t>(p))));
518 EXPECT_EQ(8, Distance(p, Type<const Int128*>(
519 L::Partial(1, 0, 0).Pointer<Int128>(p))));
520 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
521 L::Partial(5, 3, 1).Pointer<int8_t>(p))));
522 EXPECT_EQ(24, Distance(p, Type<const Int128*>(
523 L::Partial(5, 3, 1).Pointer<Int128>(p))));
524 EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
525 L::Partial(5, 3, 1).Pointer<int32_t>(p))));
526 EXPECT_EQ(24,
527 Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
528 EXPECT_EQ(
529 8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
530 }
531 }
532
TEST(Layout,MutablePointerByIndex)533 TEST(Layout, MutablePointerByIndex) {
534 alignas(max_align_t) unsigned char p[100] = {0};
535 {
536 using L = Layout<int32_t>;
537 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
538 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
539 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<0>(p))));
540 }
541 {
542 using L = Layout<int32_t, int32_t>;
543 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
544 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
545 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<1>(p))));
546 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
547 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
548 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3, 5).Pointer<0>(p))));
549 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L(3, 5).Pointer<1>(p))));
550 }
551 {
552 using L = Layout<int8_t, int32_t, Int128>;
553 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<0>(p))));
554 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<0>(p))));
555 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<1>(p))));
556 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<0>(p))));
557 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<1>(p))));
558 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<0>(p))));
559 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<1>(p))));
560 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
561 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
562 EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<2>(p))));
563 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
564 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
565 EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<2>(p))));
566 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
567 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
568 EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));
569 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
570 EXPECT_EQ(0,
571 Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
572 EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
573 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
574 EXPECT_EQ(4,
575 Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
576 EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
577 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
578 EXPECT_EQ(24,
579 Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
580 EXPECT_EQ(8,
581 Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
582 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));
583 EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));
584 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));
585 }
586 }
587
TEST(Layout,MutablePointerByType)588 TEST(Layout, MutablePointerByType) {
589 alignas(max_align_t) unsigned char p[100] = {0};
590 {
591 using L = Layout<int32_t>;
592 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));
593 EXPECT_EQ(0,
594 Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
595 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));
596 }
597 {
598 using L = Layout<int8_t, int32_t, Int128>;
599 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));
600 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
601 EXPECT_EQ(0,
602 Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
603 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
604 EXPECT_EQ(4,
605 Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
606 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
607 EXPECT_EQ(8,
608 Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
609 EXPECT_EQ(0,
610 Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
611 EXPECT_EQ(
612 0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
613 EXPECT_EQ(0,
614 Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
615 EXPECT_EQ(0,
616 Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
617 EXPECT_EQ(
618 4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
619 EXPECT_EQ(8,
620 Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
621 EXPECT_EQ(0,
622 Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
623 EXPECT_EQ(
624 8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
625 EXPECT_EQ(24,
626 Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
627 EXPECT_EQ(
628 0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
629 EXPECT_EQ(
630 0,
631 Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
632 EXPECT_EQ(
633 0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));
634 EXPECT_EQ(
635 0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
636 EXPECT_EQ(
637 4,
638 Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
639 EXPECT_EQ(
640 8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));
641 EXPECT_EQ(
642 0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
643 EXPECT_EQ(
644 24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));
645 EXPECT_EQ(
646 8,
647 Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
648 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));
649 EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
650 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
651 }
652 }
653
TEST(Layout,Pointers)654 TEST(Layout, Pointers) {
655 alignas(max_align_t) const unsigned char p[100] = {0};
656 using L = Layout<int8_t, int8_t, Int128>;
657 {
658 const auto x = L::Partial();
659 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
660 Type<std::tuple<const int8_t*>>(x.Pointers(p)));
661 }
662 {
663 const auto x = L::Partial(1);
664 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
665 (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));
666 }
667 {
668 const auto x = L::Partial(1, 2);
669 EXPECT_EQ(
670 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
671 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
672 x.Pointers(p))));
673 }
674 {
675 const auto x = L::Partial(1, 2, 3);
676 EXPECT_EQ(
677 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
678 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
679 x.Pointers(p))));
680 }
681 {
682 const L x(1, 2, 3);
683 EXPECT_EQ(
684 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
685 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
686 x.Pointers(p))));
687 }
688 }
689
TEST(Layout,MutablePointers)690 TEST(Layout, MutablePointers) {
691 alignas(max_align_t) unsigned char p[100] = {0};
692 using L = Layout<int8_t, int8_t, Int128>;
693 {
694 const auto x = L::Partial();
695 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
696 Type<std::tuple<int8_t*>>(x.Pointers(p)));
697 }
698 {
699 const auto x = L::Partial(1);
700 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
701 (Type<std::tuple<int8_t*, int8_t*>>(x.Pointers(p))));
702 }
703 {
704 const auto x = L::Partial(1, 2);
705 EXPECT_EQ(
706 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
707 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
708 }
709 {
710 const auto x = L::Partial(1, 2, 3);
711 EXPECT_EQ(
712 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
713 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
714 }
715 {
716 const L x(1, 2, 3);
717 EXPECT_EQ(
718 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
719 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
720 }
721 }
722
TEST(Layout,SliceByIndexSize)723 TEST(Layout, SliceByIndexSize) {
724 alignas(max_align_t) const unsigned char p[100] = {0};
725 {
726 using L = Layout<int32_t>;
727 EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
728 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
729 EXPECT_EQ(3, L(3).Slice<0>(p).size());
730 }
731 {
732 using L = Layout<int32_t, int32_t>;
733 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
734 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
735 EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
736 }
737 {
738 using L = Layout<int8_t, int32_t, Int128>;
739 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
740 EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
741 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
742 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
743 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
744 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
745 EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
746 EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
747 EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
748 }
749 }
750
TEST(Layout,SliceByTypeSize)751 TEST(Layout, SliceByTypeSize) {
752 alignas(max_align_t) const unsigned char p[100] = {0};
753 {
754 using L = Layout<int32_t>;
755 EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
756 EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
757 EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
758 }
759 {
760 using L = Layout<int8_t, int32_t, Int128>;
761 EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
762 EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
763 EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
764 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
765 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
766 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
767 EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
768 EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
769 EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
770 }
771 }
772
TEST(Layout,MutableSliceByIndexSize)773 TEST(Layout, MutableSliceByIndexSize) {
774 alignas(max_align_t) unsigned char p[100] = {0};
775 {
776 using L = Layout<int32_t>;
777 EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
778 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
779 EXPECT_EQ(3, L(3).Slice<0>(p).size());
780 }
781 {
782 using L = Layout<int32_t, int32_t>;
783 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
784 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
785 EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
786 }
787 {
788 using L = Layout<int8_t, int32_t, Int128>;
789 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
790 EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
791 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
792 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
793 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
794 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
795 EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
796 EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
797 EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
798 }
799 }
800
TEST(Layout,MutableSliceByTypeSize)801 TEST(Layout, MutableSliceByTypeSize) {
802 alignas(max_align_t) unsigned char p[100] = {0};
803 {
804 using L = Layout<int32_t>;
805 EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
806 EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
807 EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
808 }
809 {
810 using L = Layout<int8_t, int32_t, Int128>;
811 EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
812 EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
813 EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
814 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
815 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
816 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
817 EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
818 EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
819 EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
820 }
821 }
822
TEST(Layout,SliceByIndexData)823 TEST(Layout, SliceByIndexData) {
824 alignas(max_align_t) const unsigned char p[100] = {0};
825 {
826 using L = Layout<int32_t>;
827 EXPECT_EQ(
828 0, Distance(
829 p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
830 EXPECT_EQ(
831 0, Distance(
832 p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
833 EXPECT_EQ(0,
834 Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
835 }
836 {
837 using L = Layout<int32_t, int32_t>;
838 EXPECT_EQ(
839 0, Distance(
840 p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
841 EXPECT_EQ(
842 0,
843 Distance(
844 p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
845 EXPECT_EQ(
846 12,
847 Distance(
848 p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
849 EXPECT_EQ(
850 0, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
851 EXPECT_EQ(
852 12, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
853 }
854 {
855 using L = Layout<int8_t, int32_t, Int128>;
856 EXPECT_EQ(
857 0, Distance(
858 p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
859 EXPECT_EQ(
860 0, Distance(
861 p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
862 EXPECT_EQ(
863 0, Distance(
864 p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
865 EXPECT_EQ(
866 0,
867 Distance(
868 p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
869 EXPECT_EQ(
870 0,
871 Distance(
872 p, Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
873 EXPECT_EQ(
874 0,
875 Distance(
876 p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
877 EXPECT_EQ(
878 4,
879 Distance(
880 p, Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
881 EXPECT_EQ(
882 0,
883 Distance(
884 p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
885 EXPECT_EQ(
886 8,
887 Distance(
888 p, Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
889 EXPECT_EQ(
890 0,
891 Distance(
892 p,
893 Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
894 EXPECT_EQ(
895 0,
896 Distance(
897 p,
898 Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
899 EXPECT_EQ(
900 0,
901 Distance(
902 p,
903 Type<Span<const Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
904 EXPECT_EQ(
905 0,
906 Distance(
907 p,
908 Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
909 EXPECT_EQ(
910 4,
911 Distance(
912 p,
913 Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
914 EXPECT_EQ(
915 8,
916 Distance(
917 p,
918 Type<Span<const Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
919 EXPECT_EQ(
920 0,
921 Distance(
922 p,
923 Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
924 EXPECT_EQ(
925 24,
926 Distance(
927 p,
928 Type<Span<const Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
929 EXPECT_EQ(
930 8,
931 Distance(
932 p,
933 Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
934 EXPECT_EQ(
935 0,
936 Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
937 EXPECT_EQ(
938 24,
939 Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
940 EXPECT_EQ(
941 8,
942 Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
943 }
944 }
945
TEST(Layout,SliceByTypeData)946 TEST(Layout, SliceByTypeData) {
947 alignas(max_align_t) const unsigned char p[100] = {0};
948 {
949 using L = Layout<int32_t>;
950 EXPECT_EQ(
951 0,
952 Distance(
953 p,
954 Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
955 EXPECT_EQ(
956 0,
957 Distance(
958 p,
959 Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
960 EXPECT_EQ(
961 0,
962 Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
963 }
964 {
965 using L = Layout<int8_t, int32_t, Int128>;
966 EXPECT_EQ(
967 0,
968 Distance(
969 p,
970 Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
971 EXPECT_EQ(
972 0,
973 Distance(
974 p,
975 Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
976 EXPECT_EQ(
977 0,
978 Distance(
979 p,
980 Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
981 EXPECT_EQ(
982 0,
983 Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p))
984 .data()));
985 EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
986 L::Partial(0, 0).Slice<int32_t>(p))
987 .data()));
988 EXPECT_EQ(
989 0,
990 Distance(p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p))
991 .data()));
992 EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
993 L::Partial(1, 0).Slice<int32_t>(p))
994 .data()));
995 EXPECT_EQ(
996 0,
997 Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p))
998 .data()));
999 EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
1000 L::Partial(5, 3).Slice<int32_t>(p))
1001 .data()));
1002 EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
1003 L::Partial(0, 0, 0).Slice<int8_t>(p))
1004 .data()));
1005 EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
1006 L::Partial(0, 0, 0).Slice<int32_t>(p))
1007 .data()));
1008 EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
1009 L::Partial(0, 0, 0).Slice<Int128>(p))
1010 .data()));
1011 EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
1012 L::Partial(1, 0, 0).Slice<int8_t>(p))
1013 .data()));
1014 EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
1015 L::Partial(1, 0, 0).Slice<int32_t>(p))
1016 .data()));
1017 EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(
1018 L::Partial(1, 0, 0).Slice<Int128>(p))
1019 .data()));
1020 EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
1021 L::Partial(5, 3, 1).Slice<int8_t>(p))
1022 .data()));
1023 EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(
1024 L::Partial(5, 3, 1).Slice<Int128>(p))
1025 .data()));
1026 EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
1027 L::Partial(5, 3, 1).Slice<int32_t>(p))
1028 .data()));
1029 EXPECT_EQ(
1030 0,
1031 Distance(p,
1032 Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
1033 EXPECT_EQ(
1034 24,
1035 Distance(p,
1036 Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
1037 EXPECT_EQ(
1038 8,
1039 Distance(
1040 p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
1041 }
1042 }
1043
TEST(Layout,MutableSliceByIndexData)1044 TEST(Layout, MutableSliceByIndexData) {
1045 alignas(max_align_t) unsigned char p[100] = {0};
1046 {
1047 using L = Layout<int32_t>;
1048 EXPECT_EQ(
1049 0, Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
1050 EXPECT_EQ(
1051 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
1052 EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));
1053 }
1054 {
1055 using L = Layout<int32_t, int32_t>;
1056 EXPECT_EQ(
1057 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
1058 EXPECT_EQ(
1059 0,
1060 Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
1061 EXPECT_EQ(
1062 12,
1063 Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
1064 EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<0>(p)).data()));
1065 EXPECT_EQ(12, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<1>(p)).data()));
1066 }
1067 {
1068 using L = Layout<int8_t, int32_t, Int128>;
1069 EXPECT_EQ(
1070 0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
1071 EXPECT_EQ(
1072 0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
1073 EXPECT_EQ(
1074 0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
1075 EXPECT_EQ(
1076 0,
1077 Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
1078 EXPECT_EQ(
1079 0,
1080 Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
1081 EXPECT_EQ(
1082 0,
1083 Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
1084 EXPECT_EQ(
1085 4,
1086 Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
1087 EXPECT_EQ(
1088 0,
1089 Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
1090 EXPECT_EQ(
1091 8,
1092 Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
1093 EXPECT_EQ(
1094 0, Distance(
1095 p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
1096 EXPECT_EQ(
1097 0, Distance(
1098 p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
1099 EXPECT_EQ(
1100 0, Distance(
1101 p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
1102 EXPECT_EQ(
1103 0, Distance(
1104 p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
1105 EXPECT_EQ(
1106 4, Distance(
1107 p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
1108 EXPECT_EQ(
1109 8, Distance(
1110 p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
1111 EXPECT_EQ(
1112 0, Distance(
1113 p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
1114 EXPECT_EQ(
1115 24, Distance(
1116 p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
1117 EXPECT_EQ(
1118 8, Distance(
1119 p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
1120 EXPECT_EQ(0,
1121 Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
1122 EXPECT_EQ(24,
1123 Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
1124 EXPECT_EQ(8,
1125 Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
1126 }
1127 }
1128
TEST(Layout,MutableSliceByTypeData)1129 TEST(Layout, MutableSliceByTypeData) {
1130 alignas(max_align_t) unsigned char p[100] = {0};
1131 {
1132 using L = Layout<int32_t>;
1133 EXPECT_EQ(
1134 0, Distance(
1135 p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
1136 EXPECT_EQ(
1137 0, Distance(
1138 p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
1139 EXPECT_EQ(0,
1140 Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
1141 }
1142 {
1143 using L = Layout<int8_t, int32_t, Int128>;
1144 EXPECT_EQ(
1145 0,
1146 Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
1147 EXPECT_EQ(
1148 0,
1149 Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
1150 EXPECT_EQ(
1151 0,
1152 Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
1153 EXPECT_EQ(
1154 0,
1155 Distance(p,
1156 Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
1157 EXPECT_EQ(
1158 0,
1159 Distance(
1160 p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
1161 EXPECT_EQ(
1162 0,
1163 Distance(p,
1164 Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
1165 EXPECT_EQ(
1166 4,
1167 Distance(
1168 p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
1169 EXPECT_EQ(
1170 0,
1171 Distance(p,
1172 Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
1173 EXPECT_EQ(
1174 8,
1175 Distance(
1176 p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
1177 EXPECT_EQ(
1178 0,
1179 Distance(
1180 p,
1181 Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
1182 EXPECT_EQ(
1183 0,
1184 Distance(
1185 p,
1186 Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
1187 EXPECT_EQ(
1188 0,
1189 Distance(
1190 p,
1191 Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));
1192 EXPECT_EQ(
1193 0,
1194 Distance(
1195 p,
1196 Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
1197 EXPECT_EQ(
1198 4,
1199 Distance(
1200 p,
1201 Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
1202 EXPECT_EQ(
1203 8,
1204 Distance(
1205 p,
1206 Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));
1207 EXPECT_EQ(
1208 0,
1209 Distance(
1210 p,
1211 Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
1212 EXPECT_EQ(
1213 24,
1214 Distance(
1215 p,
1216 Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<Int128>(p)).data()));
1217 EXPECT_EQ(
1218 8,
1219 Distance(
1220 p,
1221 Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
1222 EXPECT_EQ(
1223 0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
1224 EXPECT_EQ(
1225 24,
1226 Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
1227 EXPECT_EQ(
1228 8,
1229 Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
1230 }
1231 }
1232
1233 MATCHER_P(IsSameSlice, slice, "") {
1234 return arg.size() == slice.size() && arg.data() == slice.data();
1235 }
1236
1237 template <typename... M>
1238 class TupleMatcher {
1239 public:
TupleMatcher(M...matchers)1240 explicit TupleMatcher(M... matchers) : matchers_(std::move(matchers)...) {}
1241
1242 template <typename Tuple>
MatchAndExplain(const Tuple & p,testing::MatchResultListener *) const1243 bool MatchAndExplain(const Tuple& p,
1244 testing::MatchResultListener* /* listener */) const {
1245 static_assert(std::tuple_size<Tuple>::value == sizeof...(M), "");
1246 return MatchAndExplainImpl(
1247 p, absl::make_index_sequence<std::tuple_size<Tuple>::value>{});
1248 }
1249
1250 // For the matcher concept. Left empty as we don't really need the diagnostics
1251 // right now.
DescribeTo(::std::ostream * os) const1252 void DescribeTo(::std::ostream* os) const {}
DescribeNegationTo(::std::ostream * os) const1253 void DescribeNegationTo(::std::ostream* os) const {}
1254
1255 private:
1256 template <typename Tuple, size_t... Is>
MatchAndExplainImpl(const Tuple & p,absl::index_sequence<Is...>) const1257 bool MatchAndExplainImpl(const Tuple& p, absl::index_sequence<Is...>) const {
1258 // Using std::min as a simple variadic "and".
1259 return std::min(
1260 {true, testing::SafeMatcherCast<
1261 const typename std::tuple_element<Is, Tuple>::type&>(
1262 std::get<Is>(matchers_))
1263 .Matches(std::get<Is>(p))...});
1264 }
1265
1266 std::tuple<M...> matchers_;
1267 };
1268
1269 template <typename... M>
Tuple(M...matchers)1270 testing::PolymorphicMatcher<TupleMatcher<M...>> Tuple(M... matchers) {
1271 return testing::MakePolymorphicMatcher(
1272 TupleMatcher<M...>(std::move(matchers)...));
1273 }
1274
TEST(Layout,Slices)1275 TEST(Layout, Slices) {
1276 alignas(max_align_t) const unsigned char p[100] = {0};
1277 using L = Layout<int8_t, int8_t, Int128>;
1278 {
1279 const auto x = L::Partial();
1280 EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
1281 }
1282 {
1283 const auto x = L::Partial(1);
1284 EXPECT_THAT(Type<std::tuple<Span<const int8_t>>>(x.Slices(p)),
1285 Tuple(IsSameSlice(x.Slice<0>(p))));
1286 }
1287 {
1288 const auto x = L::Partial(1, 2);
1289 EXPECT_THAT(
1290 (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(x.Slices(p))),
1291 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
1292 }
1293 {
1294 const auto x = L::Partial(1, 2, 3);
1295 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1296 Span<const Int128>>>(x.Slices(p))),
1297 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1298 IsSameSlice(x.Slice<2>(p))));
1299 }
1300 {
1301 const L x(1, 2, 3);
1302 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
1303 Span<const Int128>>>(x.Slices(p))),
1304 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1305 IsSameSlice(x.Slice<2>(p))));
1306 }
1307 }
1308
TEST(Layout,MutableSlices)1309 TEST(Layout, MutableSlices) {
1310 alignas(max_align_t) unsigned char p[100] = {0};
1311 using L = Layout<int8_t, int8_t, Int128>;
1312 {
1313 const auto x = L::Partial();
1314 EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
1315 }
1316 {
1317 const auto x = L::Partial(1);
1318 EXPECT_THAT(Type<std::tuple<Span<int8_t>>>(x.Slices(p)),
1319 Tuple(IsSameSlice(x.Slice<0>(p))));
1320 }
1321 {
1322 const auto x = L::Partial(1, 2);
1323 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))),
1324 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
1325 }
1326 {
1327 const auto x = L::Partial(1, 2, 3);
1328 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
1329 x.Slices(p))),
1330 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1331 IsSameSlice(x.Slice<2>(p))));
1332 }
1333 {
1334 const L x(1, 2, 3);
1335 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
1336 x.Slices(p))),
1337 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
1338 IsSameSlice(x.Slice<2>(p))));
1339 }
1340 }
1341
TEST(Layout,UnalignedTypes)1342 TEST(Layout, UnalignedTypes) {
1343 constexpr Layout<unsigned char, unsigned char, unsigned char> x(1, 2, 3);
1344 alignas(max_align_t) unsigned char p[x.AllocSize() + 1];
1345 EXPECT_THAT(x.Pointers(p + 1), Tuple(p + 1, p + 2, p + 4));
1346 }
1347
TEST(Layout,CustomAlignment)1348 TEST(Layout, CustomAlignment) {
1349 constexpr Layout<unsigned char, Aligned<unsigned char, 8>> x(1, 2);
1350 alignas(max_align_t) unsigned char p[x.AllocSize()];
1351 EXPECT_EQ(10, x.AllocSize());
1352 EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 8));
1353 }
1354
TEST(Layout,OverAligned)1355 TEST(Layout, OverAligned) {
1356 constexpr size_t M = alignof(max_align_t);
1357 constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
1358 #ifdef __GNUC__
1359 // Using __attribute__ ((aligned ())) instead of alignas to bypass a gcc bug:
1360 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89357
1361 __attribute__((aligned(2 * M))) unsigned char p[x.AllocSize()];
1362 #else
1363 alignas(2 * M) unsigned char p[x.AllocSize()];
1364 #endif
1365 EXPECT_EQ(2 * M + 3, x.AllocSize());
1366 EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 2 * M));
1367 }
1368
TEST(Layout,Alignment)1369 TEST(Layout, Alignment) {
1370 static_assert(Layout<int8_t>::Alignment() == 1, "");
1371 static_assert(Layout<int32_t>::Alignment() == 4, "");
1372 static_assert(Layout<Int64>::Alignment() == 8, "");
1373 static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, "");
1374 static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, "");
1375 static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, "");
1376 static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, "");
1377 static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, "");
1378 static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, "");
1379 static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
1380 }
1381
TEST(Layout,ConstexprPartial)1382 TEST(Layout, ConstexprPartial) {
1383 constexpr size_t M = alignof(max_align_t);
1384 constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
1385 static_assert(x.Partial(1).template Offset<1>() == 2 * M, "");
1386 }
1387 // [from, to)
1388 struct Region {
1389 size_t from;
1390 size_t to;
1391 };
1392
ExpectRegionPoisoned(const unsigned char * p,size_t n,bool poisoned)1393 void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) {
1394 #ifdef ABSL_HAVE_ADDRESS_SANITIZER
1395 for (size_t i = 0; i != n; ++i) {
1396 EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i));
1397 }
1398 #endif
1399 }
1400
1401 template <size_t N>
ExpectPoisoned(const unsigned char (& buf)[N],std::initializer_list<Region> reg)1402 void ExpectPoisoned(const unsigned char (&buf)[N],
1403 std::initializer_list<Region> reg) {
1404 size_t prev = 0;
1405 for (const Region& r : reg) {
1406 ExpectRegionPoisoned(buf + prev, r.from - prev, false);
1407 ExpectRegionPoisoned(buf + r.from, r.to - r.from, true);
1408 prev = r.to;
1409 }
1410 ExpectRegionPoisoned(buf + prev, N - prev, false);
1411 }
1412
TEST(Layout,PoisonPadding)1413 TEST(Layout, PoisonPadding) {
1414 using L = Layout<int8_t, Int64, int32_t, Int128>;
1415
1416 constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
1417 {
1418 constexpr auto x = L::Partial();
1419 alignas(max_align_t) const unsigned char c[n] = {};
1420 x.PoisonPadding(c);
1421 EXPECT_EQ(x.Slices(c), x.Slices(c));
1422 ExpectPoisoned(c, {});
1423 }
1424 {
1425 constexpr auto x = L::Partial(1);
1426 alignas(max_align_t) const unsigned char c[n] = {};
1427 x.PoisonPadding(c);
1428 EXPECT_EQ(x.Slices(c), x.Slices(c));
1429 ExpectPoisoned(c, {{1, 8}});
1430 }
1431 {
1432 constexpr auto x = L::Partial(1, 2);
1433 alignas(max_align_t) const unsigned char c[n] = {};
1434 x.PoisonPadding(c);
1435 EXPECT_EQ(x.Slices(c), x.Slices(c));
1436 ExpectPoisoned(c, {{1, 8}});
1437 }
1438 {
1439 constexpr auto x = L::Partial(1, 2, 3);
1440 alignas(max_align_t) const unsigned char c[n] = {};
1441 x.PoisonPadding(c);
1442 EXPECT_EQ(x.Slices(c), x.Slices(c));
1443 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1444 }
1445 {
1446 constexpr auto x = L::Partial(1, 2, 3, 4);
1447 alignas(max_align_t) const unsigned char c[n] = {};
1448 x.PoisonPadding(c);
1449 EXPECT_EQ(x.Slices(c), x.Slices(c));
1450 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1451 }
1452 {
1453 constexpr L x(1, 2, 3, 4);
1454 alignas(max_align_t) const unsigned char c[n] = {};
1455 x.PoisonPadding(c);
1456 EXPECT_EQ(x.Slices(c), x.Slices(c));
1457 ExpectPoisoned(c, {{1, 8}, {36, 40}});
1458 }
1459 }
1460
TEST(Layout,DebugString)1461 TEST(Layout, DebugString) {
1462 {
1463 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial();
1464 EXPECT_EQ("@0<signed char>(1)", x.DebugString());
1465 }
1466 {
1467 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1);
1468 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString());
1469 }
1470 {
1471 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2);
1472 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
1473 x.DebugString());
1474 }
1475 {
1476 constexpr auto x =
1477 Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
1478 EXPECT_EQ(
1479 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1480 "@16" +
1481 Int128::Name() + "(16)",
1482 x.DebugString());
1483 }
1484 {
1485 constexpr auto x =
1486 Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
1487 EXPECT_EQ(
1488 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1489 "@16" +
1490 Int128::Name() + "(16)[4]",
1491 x.DebugString());
1492 }
1493 {
1494 constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4);
1495 EXPECT_EQ(
1496 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
1497 "@16" +
1498 Int128::Name() + "(16)[4]",
1499 x.DebugString());
1500 }
1501 }
1502
TEST(Layout,CharTypes)1503 TEST(Layout, CharTypes) {
1504 constexpr Layout<int32_t> x(1);
1505 alignas(max_align_t) char c[x.AllocSize()] = {};
1506 alignas(max_align_t) unsigned char uc[x.AllocSize()] = {};
1507 alignas(max_align_t) signed char sc[x.AllocSize()] = {};
1508 alignas(max_align_t) const char cc[x.AllocSize()] = {};
1509 alignas(max_align_t) const unsigned char cuc[x.AllocSize()] = {};
1510 alignas(max_align_t) const signed char csc[x.AllocSize()] = {};
1511
1512 Type<int32_t*>(x.Pointer<0>(c));
1513 Type<int32_t*>(x.Pointer<0>(uc));
1514 Type<int32_t*>(x.Pointer<0>(sc));
1515 Type<const int32_t*>(x.Pointer<0>(cc));
1516 Type<const int32_t*>(x.Pointer<0>(cuc));
1517 Type<const int32_t*>(x.Pointer<0>(csc));
1518
1519 Type<int32_t*>(x.Pointer<int32_t>(c));
1520 Type<int32_t*>(x.Pointer<int32_t>(uc));
1521 Type<int32_t*>(x.Pointer<int32_t>(sc));
1522 Type<const int32_t*>(x.Pointer<int32_t>(cc));
1523 Type<const int32_t*>(x.Pointer<int32_t>(cuc));
1524 Type<const int32_t*>(x.Pointer<int32_t>(csc));
1525
1526 Type<std::tuple<int32_t*>>(x.Pointers(c));
1527 Type<std::tuple<int32_t*>>(x.Pointers(uc));
1528 Type<std::tuple<int32_t*>>(x.Pointers(sc));
1529 Type<std::tuple<const int32_t*>>(x.Pointers(cc));
1530 Type<std::tuple<const int32_t*>>(x.Pointers(cuc));
1531 Type<std::tuple<const int32_t*>>(x.Pointers(csc));
1532
1533 Type<Span<int32_t>>(x.Slice<0>(c));
1534 Type<Span<int32_t>>(x.Slice<0>(uc));
1535 Type<Span<int32_t>>(x.Slice<0>(sc));
1536 Type<Span<const int32_t>>(x.Slice<0>(cc));
1537 Type<Span<const int32_t>>(x.Slice<0>(cuc));
1538 Type<Span<const int32_t>>(x.Slice<0>(csc));
1539
1540 Type<std::tuple<Span<int32_t>>>(x.Slices(c));
1541 Type<std::tuple<Span<int32_t>>>(x.Slices(uc));
1542 Type<std::tuple<Span<int32_t>>>(x.Slices(sc));
1543 Type<std::tuple<Span<const int32_t>>>(x.Slices(cc));
1544 Type<std::tuple<Span<const int32_t>>>(x.Slices(cuc));
1545 Type<std::tuple<Span<const int32_t>>>(x.Slices(csc));
1546 }
1547
TEST(Layout,ConstElementType)1548 TEST(Layout, ConstElementType) {
1549 constexpr Layout<const int32_t> x(1);
1550 alignas(int32_t) char c[x.AllocSize()] = {};
1551 const char* cc = c;
1552 const int32_t* p = reinterpret_cast<const int32_t*>(cc);
1553
1554 EXPECT_EQ(alignof(int32_t), x.Alignment());
1555
1556 EXPECT_EQ(0, x.Offset<0>());
1557 EXPECT_EQ(0, x.Offset<const int32_t>());
1558
1559 EXPECT_THAT(x.Offsets(), ElementsAre(0));
1560
1561 EXPECT_EQ(1, x.Size<0>());
1562 EXPECT_EQ(1, x.Size<const int32_t>());
1563
1564 EXPECT_THAT(x.Sizes(), ElementsAre(1));
1565
1566 EXPECT_EQ(sizeof(int32_t), x.AllocSize());
1567
1568 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(c)));
1569 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(cc)));
1570
1571 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(c)));
1572 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(cc)));
1573
1574 EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(c)), Tuple(p));
1575 EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(cc)), Tuple(p));
1576
1577 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(c)),
1578 IsSameSlice(Span<const int32_t>(p, 1)));
1579 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(cc)),
1580 IsSameSlice(Span<const int32_t>(p, 1)));
1581
1582 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(c)),
1583 IsSameSlice(Span<const int32_t>(p, 1)));
1584 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(cc)),
1585 IsSameSlice(Span<const int32_t>(p, 1)));
1586
1587 EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(c)),
1588 Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
1589 EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)),
1590 Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
1591 }
1592
1593 namespace example {
1594
1595 // Immutable move-only string with sizeof equal to sizeof(void*). The string
1596 // size and the characters are kept in the same heap allocation.
1597 class CompactString {
1598 public:
CompactString(const char * s="")1599 CompactString(const char* s = "") { // NOLINT
1600 const size_t size = strlen(s);
1601 // size_t[1], followed by char[size + 1].
1602 // This statement doesn't allocate memory.
1603 const L layout(1, size + 1);
1604 // AllocSize() tells us how much memory we need to allocate for all our
1605 // data.
1606 p_.reset(new unsigned char[layout.AllocSize()]);
1607 // If running under ASAN, mark the padding bytes, if any, to catch memory
1608 // errors.
1609 layout.PoisonPadding(p_.get());
1610 // Store the size in the allocation.
1611 // Pointer<size_t>() is a synonym for Pointer<0>().
1612 *layout.Pointer<size_t>(p_.get()) = size;
1613 // Store the characters in the allocation.
1614 memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
1615 }
1616
size() const1617 size_t size() const {
1618 // Equivalent to reinterpret_cast<size_t&>(*p).
1619 return *L::Partial().Pointer<size_t>(p_.get());
1620 }
1621
c_str() const1622 const char* c_str() const {
1623 // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
1624 // The argument in Partial(1) specifies that we have size_t[1] in front of
1625 // the characters.
1626 return L::Partial(1).Pointer<char>(p_.get());
1627 }
1628
1629 private:
1630 // Our heap allocation contains a size_t followed by an array of chars.
1631 using L = Layout<size_t, char>;
1632 std::unique_ptr<unsigned char[]> p_;
1633 };
1634
TEST(CompactString,Works)1635 TEST(CompactString, Works) {
1636 CompactString s = "hello";
1637 EXPECT_EQ(5, s.size());
1638 EXPECT_STREQ("hello", s.c_str());
1639 }
1640
1641 } // namespace example
1642
1643 } // namespace
1644 } // namespace container_internal
1645 ABSL_NAMESPACE_END
1646 } // namespace absl
1647