1 /*
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
21 namespace art {
22
23 // A copy of detail::ValidateBitStructSize that uses EXPECT for a more
24 // human-readable message.
25 template <typename T>
ValidateBitStructSize(const char * name)26 static 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
TEST(BitStructs,MinimumType)40 TEST(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
55 template <typename T>
AsUint(const T & value)56 size_t AsUint(const T& value) {
57 size_t uint_value = 0;
58 memcpy(&uint_value, &value, sizeof(value));
59 return uint_value;
60 }
61
62 struct CustomBitStruct {
63 CustomBitStruct() = default;
CustomBitStructart::CustomBitStruct64 explicit CustomBitStruct(uint8_t data) : data(data) {}
65
BitStructSizeOfart::CustomBitStruct66 static constexpr size_t BitStructSizeOf() {
67 return 4;
68 }
69
70 uint8_t data;
71 };
72
TEST(BitStructs,Custom)73 TEST(BitStructs, Custom) {
74 CustomBitStruct expected(0b1111u);
75
76 BitStructField<CustomBitStruct, /*lsb=*/4, /*width=*/4, uint8_t> f{};
77
78 EXPECT_EQ(1u, sizeof(f));
79
80 f = CustomBitStruct(0b1111u);
81
82 CustomBitStruct read_out = f;
83 EXPECT_EQ(read_out.data, 0b1111u);
84
85 EXPECT_EQ(AsUint(f), 0b11110000u);
86 }
87
88 BITSTRUCT_DEFINE_START(TestTwoCustom, /* size= */ 8)
89 BITSTRUCT_FIELD(CustomBitStruct, /*lsb=*/0, /*width=*/4) f4_a;
90 BITSTRUCT_FIELD(CustomBitStruct, /*lsb=*/4, /*width=*/4) f4_b;
91 BITSTRUCT_DEFINE_END(TestTwoCustom);
92
TEST(BitStructs,TwoCustom)93 TEST(BitStructs, TwoCustom) {
94 EXPECT_EQ(sizeof(TestTwoCustom), 1u);
95
96 VALIDATE_BITSTRUCT_SIZE(TestTwoCustom);
97
98 TestTwoCustom cst{};
99
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
TEST(BitStructs,Number)124 TEST(BitStructs, Number) {
125 BitStructNumber<uint16_t, /*lsb=*/4, /*width=*/4, uint16_t> bsn{};
126 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
TEST(BitStructs,NumberNarrowStorage)138 TEST(BitStructs, NumberNarrowStorage) {
139 BitStructNumber<uint16_t, /*lsb=*/4, /*width=*/4, uint8_t> bsn{};
140 EXPECT_EQ(1u, sizeof(bsn));
141
142 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
152 BITSTRUCT_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;
157 BITSTRUCT_DEFINE_END(TestBitStruct);
158
TEST(BitStructs,Test1)159 TEST(BitStructs, Test1) {
160 TestBitStruct tst{};
161
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
222 BITSTRUCT_DEFINE_START(MixedSizeBitStruct, /* size= */ 32)
223 BITSTRUCT_UINT(/*lsb=*/0, /*width=*/3) u3;
224 BITSTRUCT_UINT(/*lsb=*/3, /*width=*/10) u10;
225 BITSTRUCT_UINT(/*lsb=*/13, /*width=*/19) u19;
226
227 BITSTRUCT_UINT(/*lsb=*/0, /*width=*/32) alias_all;
228 BITSTRUCT_DEFINE_END(MixedSizeBitStruct);
229
230 // static_assert(sizeof(MixedSizeBitStruct) == sizeof(uint32_t), "TestBitStructs#MixedSize");
231
TEST(BitStructs,Mixed)232 TEST(BitStructs, Mixed) {
233 EXPECT_EQ(4u, sizeof(MixedSizeBitStruct));
234
235 MixedSizeBitStruct tst{};
236
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
261 BITSTRUCT_DEFINE_START(TestBitStruct_u8, /* size= */ 8)
262 BITSTRUCT_INT(/*lsb=*/0, /*width=*/3) i3;
263 BITSTRUCT_UINT(/*lsb=*/3, /*width=*/4) u4;
264
265 BITSTRUCT_UINT(/*lsb=*/0, /*width=*/8) alias_all;
266 BITSTRUCT_DEFINE_END(TestBitStruct_u8);
267
TEST(BitStructs,FieldAssignment)268 TEST(BitStructs, FieldAssignment) {
269 TestBitStruct_u8 all_1s{};
270 all_1s.alias_all = 0xffu;
271
272 {
273 TestBitStruct_u8 tst{};
274 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 {
281 TestBitStruct_u8 tst{};
282 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
289 BITSTRUCT_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;
296
297 BITSTRUCT_UINT(/*lsb=*/0, /*width=*/ 2 * MixedSizeBitStruct::BitStructSizeOf()) alias_all;
298 BITSTRUCT_DEFINE_END(NestedStruct);
299
TEST(BitStructs,NestedFieldAssignment)300 TEST(BitStructs, NestedFieldAssignment) {
301 MixedSizeBitStruct mixed_all_1s{};
302 mixed_all_1s.alias_all = 0xFFFFFFFFu;
303
304 {
305 NestedStruct xyz{};
306
307 NestedStruct other{};
308 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 {
317 NestedStruct xyz{};
318
319 NestedStruct other{};
320 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
329 } // namespace art
330