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