blob: 2055782ed37c7fd9beff4ab732522a2f0f743a20 [file] [log] [blame]
Igor Murashkin1e77d272017-10-07 14:09:43 +00001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "bit_struct.h"
18
19#include "gtest/gtest.h"
20
21namespace art {
22
23// A copy of detail::ValidateBitStructSize that uses EXPECT for a more
24// human-readable message.
25template <typename T>
26static constexpr bool ValidateBitStructSize(const char* name) {
27 const size_t kBitStructSizeOf = BitStructSizeOf<T>();
28 const size_t kExpectedSize = (BitStructSizeOf<T>() < kBitsPerByte)
29 ? kBitsPerByte
30 : RoundUpToPowerOfTwo(kBitStructSizeOf);
31
32 // Ensure no extra fields were added in between START/END.
33 const size_t kActualSize = sizeof(T) * kBitsPerByte;
34 EXPECT_EQ(kExpectedSize, kActualSize) << name;
35 return true;
36}
37
38#define VALIDATE_BITSTRUCT_SIZE(type) ValidateBitStructSize<type>(#type)
39
40TEST(BitStructs, MinimumType) {
41 EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<1>::type));
42 EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<2>::type));
43 EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<3>::type));
44 EXPECT_EQ(1u, sizeof(typename detail::MinimumTypeUnsignedHelper<8>::type));
45 EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<9>::type));
46 EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<10>::type));
47 EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<15>::type));
48 EXPECT_EQ(2u, sizeof(typename detail::MinimumTypeUnsignedHelper<16>::type));
49 EXPECT_EQ(4u, sizeof(typename detail::MinimumTypeUnsignedHelper<17>::type));
50 EXPECT_EQ(4u, sizeof(typename detail::MinimumTypeUnsignedHelper<32>::type));
51 EXPECT_EQ(8u, sizeof(typename detail::MinimumTypeUnsignedHelper<33>::type));
52 EXPECT_EQ(8u, sizeof(typename detail::MinimumTypeUnsignedHelper<64>::type));
53}
54
55template <typename T>
56size_t AsUint(const T& value) {
57 size_t uint_value = 0;
58 memcpy(&uint_value, &value, sizeof(value));
59 return uint_value;
60}
61
62struct CustomBitStruct {
63 CustomBitStruct() = default;
Vladimir Markoe4207a72020-01-24 14:42:03 +000064 explicit CustomBitStruct(uint8_t data) : data(data) {}
Igor Murashkin1e77d272017-10-07 14:09:43 +000065
66 static constexpr size_t BitStructSizeOf() {
67 return 4;
68 }
69
Vladimir Markoe4207a72020-01-24 14:42:03 +000070 uint8_t data;
Igor Murashkin1e77d272017-10-07 14:09:43 +000071};
72
Igor Murashkin1e77d272017-10-07 14:09:43 +000073TEST(BitStructs, Custom) {
Vladimir Markoe4207a72020-01-24 14:42:03 +000074 CustomBitStruct expected(0b1111u);
Igor Murashkin1e77d272017-10-07 14:09:43 +000075
Vladimir Markoe4207a72020-01-24 14:42:03 +000076 BitStructField<CustomBitStruct, /*lsb=*/4, /*width=*/4, uint8_t> f{};
Igor Murashkin1e77d272017-10-07 14:09:43 +000077
78 EXPECT_EQ(1u, sizeof(f));
79
Vladimir Markoe4207a72020-01-24 14:42:03 +000080 f = CustomBitStruct(0b1111u);
Igor Murashkin1e77d272017-10-07 14:09:43 +000081
82 CustomBitStruct read_out = f;
Vladimir Markoe4207a72020-01-24 14:42:03 +000083 EXPECT_EQ(read_out.data, 0b1111u);
Igor Murashkin1e77d272017-10-07 14:09:43 +000084
85 EXPECT_EQ(AsUint(f), 0b11110000u);
86}
87
Andreas Gampe0de385f2018-10-11 11:11:13 -070088BITSTRUCT_DEFINE_START(TestTwoCustom, /* size= */ 8)
Vladimir Markoe4207a72020-01-24 14:42:03 +000089 BITSTRUCT_FIELD(CustomBitStruct, /*lsb=*/0, /*width=*/4) f4_a;
90 BITSTRUCT_FIELD(CustomBitStruct, /*lsb=*/4, /*width=*/4) f4_b;
Igor Murashkin1e77d272017-10-07 14:09:43 +000091BITSTRUCT_DEFINE_END(TestTwoCustom);
92
93TEST(BitStructs, TwoCustom) {
94 EXPECT_EQ(sizeof(TestTwoCustom), 1u);
95
96 VALIDATE_BITSTRUCT_SIZE(TestTwoCustom);
97
Igor Murashkin5573c372017-11-16 13:34:30 -080098 TestTwoCustom cst{};
Igor Murashkin1e77d272017-10-07 14:09:43 +000099
100 // Test the write to most-significant field doesn't clobber least-significant.
101 cst.f4_a = CustomBitStruct(0b0110);
102 cst.f4_b = CustomBitStruct(0b0101);
103
104 int8_t read_out = static_cast<CustomBitStruct>(cst.f4_a).data;
105 int8_t read_out_b = static_cast<CustomBitStruct>(cst.f4_b).data;
106
107 EXPECT_EQ(0b0110, static_cast<int>(read_out));
108 EXPECT_EQ(0b0101, static_cast<int>(read_out_b));
109
110 EXPECT_EQ(AsUint(cst), 0b01010110u);
111
112 // Test write to least-significant field doesn't clobber most-significant.
113 cst.f4_a = CustomBitStruct(0);
114
115 read_out = static_cast<CustomBitStruct>(cst.f4_a).data;
116 read_out_b = static_cast<CustomBitStruct>(cst.f4_b).data;
117
118 EXPECT_EQ(0b0, static_cast<int>(read_out));
119 EXPECT_EQ(0b0101, static_cast<int>(read_out_b));
120
121 EXPECT_EQ(AsUint(cst), 0b01010000u);
122}
123
124TEST(BitStructs, Number) {
Vladimir Markoe4207a72020-01-24 14:42:03 +0000125 BitStructNumber<uint16_t, /*lsb=*/4, /*width=*/4, uint16_t> bsn{};
Igor Murashkin1e77d272017-10-07 14:09:43 +0000126 EXPECT_EQ(2u, sizeof(bsn));
127
128 bsn = 0b1111;
129
130 uint32_t read_out = static_cast<uint32_t>(bsn);
131 uint32_t read_out_impl = bsn;
132
133 EXPECT_EQ(read_out, read_out_impl);
134 EXPECT_EQ(read_out, 0b1111u);
135 EXPECT_EQ(AsUint(bsn), 0b11110000u);
136}
137
Vladimir Markoe4207a72020-01-24 14:42:03 +0000138TEST(BitStructs, NumberNarrowStorage) {
139 BitStructNumber<uint16_t, /*lsb=*/4, /*width=*/4, uint8_t> bsn{};
140 EXPECT_EQ(1u, sizeof(bsn));
Igor Murashkin1e77d272017-10-07 14:09:43 +0000141
Vladimir Markoe4207a72020-01-24 14:42:03 +0000142 bsn = 0b1111;
143
144 uint32_t read_out = static_cast<uint32_t>(bsn);
145 uint32_t read_out_impl = bsn;
146
147 EXPECT_EQ(read_out, read_out_impl);
148 EXPECT_EQ(read_out, 0b1111u);
149 EXPECT_EQ(AsUint(bsn), 0b11110000u);
150}
151
152BITSTRUCT_DEFINE_START(TestBitStruct, /* size= */ 8)
153 BITSTRUCT_INT(/*lsb=*/0, /*width=*/3) i3;
154 BITSTRUCT_UINT(/*lsb=*/3, /*width=*/4) u4;
155
156 BITSTRUCT_UINT(/*lsb=*/0, /*width=*/7) alias_all;
Igor Murashkin1e77d272017-10-07 14:09:43 +0000157BITSTRUCT_DEFINE_END(TestBitStruct);
158
159TEST(BitStructs, Test1) {
Igor Murashkin5573c372017-11-16 13:34:30 -0800160 TestBitStruct tst{};
Igor Murashkin1e77d272017-10-07 14:09:43 +0000161
162 // Check minimal size selection is correct.
163 EXPECT_EQ(1u, sizeof(TestBitStruct));
164 EXPECT_EQ(1u, sizeof(tst._));
165 EXPECT_EQ(1u, sizeof(tst.i3));
166 EXPECT_EQ(1u, sizeof(tst.u4));
167 EXPECT_EQ(1u, sizeof(tst.alias_all));
168
169 // Check operator assignment.
170 tst.i3 = -1;
171 tst.u4 = 0b1010;
172
173 // Check implicit operator conversion.
174 int8_t read_i3 = tst.i3;
175 uint8_t read_u4 = tst.u4;
176
177 // Ensure read-out values were correct.
178 EXPECT_EQ(static_cast<int8_t>(-1), read_i3);
179 EXPECT_EQ(0b1010, read_u4);
180
181 // Ensure aliasing is working.
182 EXPECT_EQ(0b1010111, static_cast<uint8_t>(tst.alias_all));
183
184 // Ensure the bit pattern is correct.
185 EXPECT_EQ(0b1010111u, AsUint(tst));
186
187 // Math operator checks
188 {
189 // In-place
190 ++tst.u4;
191 EXPECT_EQ(static_cast<uint8_t>(0b1011), static_cast<uint8_t>(tst.u4));
192 --tst.u4;
193 EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
194
195 // Copy
196 uint8_t read_and_convert = tst.u4++;
197 EXPECT_EQ(static_cast<uint8_t>(0b1011), read_and_convert);
198 EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
199 read_and_convert = tst.u4--;
200 EXPECT_EQ(static_cast<uint8_t>(0b1001), read_and_convert);
201 EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
202
203 // Check boolean operator conversion.
204 tst.u4 = 0b1010;
205 EXPECT_TRUE(static_cast<bool>(tst.u4));
206 bool succ = tst.u4 ? true : false;
207 EXPECT_TRUE(succ);
208
209 tst.u4 = 0;
210 EXPECT_FALSE(static_cast<bool>(tst.u4));
211
212/*
213 // Disabled: Overflow is caught by the BitFieldInsert DCHECKs.
214 // Check overflow for uint.
215 tst.u4 = 0b1111;
216 ++tst.u4;
217 EXPECT_EQ(static_cast<uint8_t>(0), static_cast<uint8_t>(tst.u4));
218*/
219 }
220}
221
Andreas Gampe0de385f2018-10-11 11:11:13 -0700222BITSTRUCT_DEFINE_START(MixedSizeBitStruct, /* size= */ 32)
Vladimir Markoe4207a72020-01-24 14:42:03 +0000223 BITSTRUCT_UINT(/*lsb=*/0, /*width=*/3) u3;
224 BITSTRUCT_UINT(/*lsb=*/3, /*width=*/10) u10;
225 BITSTRUCT_UINT(/*lsb=*/13, /*width=*/19) u19;
Igor Murashkin1e77d272017-10-07 14:09:43 +0000226
Vladimir Markoe4207a72020-01-24 14:42:03 +0000227 BITSTRUCT_UINT(/*lsb=*/0, /*width=*/32) alias_all;
Igor Murashkin1e77d272017-10-07 14:09:43 +0000228BITSTRUCT_DEFINE_END(MixedSizeBitStruct);
229
230// static_assert(sizeof(MixedSizeBitStruct) == sizeof(uint32_t), "TestBitStructs#MixedSize");
231
232TEST(BitStructs, Mixed) {
233 EXPECT_EQ(4u, sizeof(MixedSizeBitStruct));
234
Igor Murashkin5573c372017-11-16 13:34:30 -0800235 MixedSizeBitStruct tst{};
Igor Murashkin1e77d272017-10-07 14:09:43 +0000236
237 // Check operator assignment.
238 tst.u3 = 0b111u;
239 tst.u10 = 0b1111010100u;
240 tst.u19 = 0b1010101010101010101u;
241
242 // Check implicit operator conversion.
243 uint8_t read_u3 = tst.u3;
244 uint16_t read_u10 = tst.u10;
245 uint32_t read_u19 = tst.u19;
246
247 // Ensure read-out values were correct.
248 EXPECT_EQ(0b111u, read_u3);
249 EXPECT_EQ(0b1111010100u, read_u10);
250 EXPECT_EQ(0b1010101010101010101u, read_u19);
251
252 uint32_t read_all = tst.alias_all;
253
254 // Ensure aliasing is working.
255 EXPECT_EQ(0b10101010101010101011111010100111u, read_all);
256
257 // Ensure the bit pattern is correct.
258 EXPECT_EQ(0b10101010101010101011111010100111u, AsUint(tst));
259}
260
Andreas Gampe0de385f2018-10-11 11:11:13 -0700261BITSTRUCT_DEFINE_START(TestBitStruct_u8, /* size= */ 8)
Vladimir Markoe4207a72020-01-24 14:42:03 +0000262 BITSTRUCT_INT(/*lsb=*/0, /*width=*/3) i3;
263 BITSTRUCT_UINT(/*lsb=*/3, /*width=*/4) u4;
Igor Murashkindfabcc52017-10-26 14:51:52 -0700264
Vladimir Markoe4207a72020-01-24 14:42:03 +0000265 BITSTRUCT_UINT(/*lsb=*/0, /*width=*/8) alias_all;
Igor Murashkindfabcc52017-10-26 14:51:52 -0700266BITSTRUCT_DEFINE_END(TestBitStruct_u8);
267
268TEST(BitStructs, FieldAssignment) {
Igor Murashkin5573c372017-11-16 13:34:30 -0800269 TestBitStruct_u8 all_1s{};
Igor Murashkindfabcc52017-10-26 14:51:52 -0700270 all_1s.alias_all = 0xffu;
271
272 {
Igor Murashkin5573c372017-11-16 13:34:30 -0800273 TestBitStruct_u8 tst{};
Igor Murashkindfabcc52017-10-26 14:51:52 -0700274 tst.i3 = all_1s.i3;
275
276 // Copying a single bitfield does not copy all bitfields.
277 EXPECT_EQ(0b111, tst.alias_all);
278 }
279
280 {
Igor Murashkin5573c372017-11-16 13:34:30 -0800281 TestBitStruct_u8 tst{};
Igor Murashkindfabcc52017-10-26 14:51:52 -0700282 tst.u4 = all_1s.u4;
283
284 // Copying a single bitfield does not copy all bitfields.
285 EXPECT_EQ(0b1111000, tst.alias_all);
286 }
287}
288
Vladimir Markoe4207a72020-01-24 14:42:03 +0000289BITSTRUCT_DEFINE_START(NestedStruct, /* size= */ 2 * MixedSizeBitStruct::BitStructSizeOf())
290 BITSTRUCT_FIELD(MixedSizeBitStruct,
291 /*lsb=*/0,
292 /*width=*/MixedSizeBitStruct::BitStructSizeOf()) mixed_lower;
293 BITSTRUCT_FIELD(MixedSizeBitStruct,
294 /*lsb=*/MixedSizeBitStruct::BitStructSizeOf(),
295 /*width=*/MixedSizeBitStruct::BitStructSizeOf()) mixed_upper;
Igor Murashkindfabcc52017-10-26 14:51:52 -0700296
Vladimir Markoe4207a72020-01-24 14:42:03 +0000297 BITSTRUCT_UINT(/*lsb=*/0, /*width=*/ 2 * MixedSizeBitStruct::BitStructSizeOf()) alias_all;
Igor Murashkindfabcc52017-10-26 14:51:52 -0700298BITSTRUCT_DEFINE_END(NestedStruct);
299
Igor Murashkin066dd9062020-01-23 01:40:02 +0000300TEST(BitStructs, NestedFieldAssignment) {
Igor Murashkin5573c372017-11-16 13:34:30 -0800301 MixedSizeBitStruct mixed_all_1s{};
Igor Murashkindfabcc52017-10-26 14:51:52 -0700302 mixed_all_1s.alias_all = 0xFFFFFFFFu;
303
304 {
Igor Murashkin5573c372017-11-16 13:34:30 -0800305 NestedStruct xyz{};
Igor Murashkindfabcc52017-10-26 14:51:52 -0700306
Igor Murashkin5573c372017-11-16 13:34:30 -0800307 NestedStruct other{};
Igor Murashkindfabcc52017-10-26 14:51:52 -0700308 other.mixed_upper = mixed_all_1s;
309 other.mixed_lower = mixed_all_1s;
310
311 // Copying a single bitfield does not copy all bitfields.
312 xyz.mixed_lower = other.mixed_lower;
313 EXPECT_EQ(0xFFFFFFFFu, xyz.alias_all);
314 }
315
316 {
Igor Murashkin5573c372017-11-16 13:34:30 -0800317 NestedStruct xyz{};
Igor Murashkindfabcc52017-10-26 14:51:52 -0700318
Igor Murashkin5573c372017-11-16 13:34:30 -0800319 NestedStruct other{};
Igor Murashkindfabcc52017-10-26 14:51:52 -0700320 other.mixed_upper = mixed_all_1s;
321 other.mixed_lower = mixed_all_1s;
322
323 // Copying a single bitfield does not copy all bitfields.
324 xyz.mixed_upper = other.mixed_upper;
325 EXPECT_EQ(0xFFFFFFFF00000000u, xyz.alias_all);
326 }
327}
328
Igor Murashkin1e77d272017-10-07 14:09:43 +0000329} // namespace art