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


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:19