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