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(int8_t data) : data(data) {}
65
BitStructSizeOfart::CustomBitStruct66 static constexpr size_t BitStructSizeOf() {
67 return 4;
68 }
69
70 int8_t data;
71 };
72
TEST(BitStructs,Custom)73 TEST(BitStructs, Custom) {
74 CustomBitStruct expected(0b1111);
75
76 BitStructField<CustomBitStruct, /*lsb=*/4, /*width=*/4> f{};
77
78 EXPECT_EQ(1u, sizeof(f));
79
80 f = CustomBitStruct(0b1111);
81
82 CustomBitStruct read_out = f;
83 EXPECT_EQ(read_out.data, 0b1111);
84
85 EXPECT_EQ(AsUint(f), 0b11110000u);
86 }
87
88 BITSTRUCT_DEFINE_START(TestTwoCustom, /* size= */ 8)
89 BitStructField<CustomBitStruct, /*lsb=*/0, /*width=*/4> f4_a;
90 BitStructField<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> 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
138 BITSTRUCT_DEFINE_START(TestBitStruct, /* size= */ 8)
139 BitStructInt</*lsb=*/0, /*width=*/3> i3;
140 BitStructUint</*lsb=*/3, /*width=*/4> u4;
141
142 BitStructUint</*lsb=*/0, /*width=*/7> alias_all;
143 BITSTRUCT_DEFINE_END(TestBitStruct);
144
TEST(BitStructs,Test1)145 TEST(BitStructs, Test1) {
146 {
147 // Check minimal size selection is correct.
148 BitStructInt</*lsb=*/0, /*width=*/3> i3;
149 BitStructUint</*lsb=*/3, /*width=*/4> u4;
150
151 BitStructUint</*lsb=*/0, /*width=*/7> alias_all;
152
153 EXPECT_EQ(1u, sizeof(i3));
154 EXPECT_EQ(1u, sizeof(u4));
155 EXPECT_EQ(1u, sizeof(alias_all));
156 }
157 TestBitStruct tst{};
158
159 // Check minimal size selection is correct.
160 EXPECT_EQ(1u, sizeof(TestBitStruct));
161 EXPECT_EQ(1u, sizeof(tst._));
162 EXPECT_EQ(1u, sizeof(tst.i3));
163 EXPECT_EQ(1u, sizeof(tst.u4));
164 EXPECT_EQ(1u, sizeof(tst.alias_all));
165
166 // Check operator assignment.
167 tst.i3 = -1;
168 tst.u4 = 0b1010;
169
170 // Check implicit operator conversion.
171 int8_t read_i3 = tst.i3;
172 uint8_t read_u4 = tst.u4;
173
174 // Ensure read-out values were correct.
175 EXPECT_EQ(static_cast<int8_t>(-1), read_i3);
176 EXPECT_EQ(0b1010, read_u4);
177
178 // Ensure aliasing is working.
179 EXPECT_EQ(0b1010111, static_cast<uint8_t>(tst.alias_all));
180
181 // Ensure the bit pattern is correct.
182 EXPECT_EQ(0b1010111u, AsUint(tst));
183
184 // Math operator checks
185 {
186 // In-place
187 ++tst.u4;
188 EXPECT_EQ(static_cast<uint8_t>(0b1011), static_cast<uint8_t>(tst.u4));
189 --tst.u4;
190 EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
191
192 // Copy
193 uint8_t read_and_convert = tst.u4++;
194 EXPECT_EQ(static_cast<uint8_t>(0b1011), read_and_convert);
195 EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
196 read_and_convert = tst.u4--;
197 EXPECT_EQ(static_cast<uint8_t>(0b1001), read_and_convert);
198 EXPECT_EQ(static_cast<uint8_t>(0b1010), static_cast<uint8_t>(tst.u4));
199
200 // Check boolean operator conversion.
201 tst.u4 = 0b1010;
202 EXPECT_TRUE(static_cast<bool>(tst.u4));
203 bool succ = tst.u4 ? true : false;
204 EXPECT_TRUE(succ);
205
206 tst.u4 = 0;
207 EXPECT_FALSE(static_cast<bool>(tst.u4));
208
209 /*
210 // Disabled: Overflow is caught by the BitFieldInsert DCHECKs.
211 // Check overflow for uint.
212 tst.u4 = 0b1111;
213 ++tst.u4;
214 EXPECT_EQ(static_cast<uint8_t>(0), static_cast<uint8_t>(tst.u4));
215 */
216 }
217 }
218
219 BITSTRUCT_DEFINE_START(MixedSizeBitStruct, /* size= */ 32)
220 BitStructUint</*lsb=*/0, /*width=*/3> u3;
221 BitStructUint</*lsb=*/3, /*width=*/10> u10;
222 BitStructUint</*lsb=*/13, /*width=*/19> u19;
223
224 BitStructUint</*lsb=*/0, /*width=*/32> alias_all;
225 BITSTRUCT_DEFINE_END(MixedSizeBitStruct);
226
227 // static_assert(sizeof(MixedSizeBitStruct) == sizeof(uint32_t), "TestBitStructs#MixedSize");
228
TEST(BitStructs,Mixed)229 TEST(BitStructs, Mixed) {
230 EXPECT_EQ(4u, sizeof(MixedSizeBitStruct));
231
232 MixedSizeBitStruct tst{};
233
234 // Check operator assignment.
235 tst.u3 = 0b111u;
236 tst.u10 = 0b1111010100u;
237 tst.u19 = 0b1010101010101010101u;
238
239 // Check implicit operator conversion.
240 uint8_t read_u3 = tst.u3;
241 uint16_t read_u10 = tst.u10;
242 uint32_t read_u19 = tst.u19;
243
244 // Ensure read-out values were correct.
245 EXPECT_EQ(0b111u, read_u3);
246 EXPECT_EQ(0b1111010100u, read_u10);
247 EXPECT_EQ(0b1010101010101010101u, read_u19);
248
249 uint32_t read_all = tst.alias_all;
250
251 // Ensure aliasing is working.
252 EXPECT_EQ(0b10101010101010101011111010100111u, read_all);
253
254 // Ensure the bit pattern is correct.
255 EXPECT_EQ(0b10101010101010101011111010100111u, AsUint(tst));
256 }
257
258 BITSTRUCT_DEFINE_START(TestBitStruct_u8, /* size= */ 8)
259 BitStructInt</*lsb=*/0, /*width=*/3> i3;
260 BitStructUint</*lsb=*/3, /*width=*/4> u4;
261
262 BitStructUint</*lsb=*/0, /*width=*/8> alias_all;
263 BITSTRUCT_DEFINE_END(TestBitStruct_u8);
264
TEST(BitStructs,FieldAssignment)265 TEST(BitStructs, FieldAssignment) {
266 TestBitStruct_u8 all_1s{};
267 all_1s.alias_all = 0xffu;
268
269 {
270 TestBitStruct_u8 tst{};
271 tst.i3 = all_1s.i3;
272
273 // Copying a single bitfield does not copy all bitfields.
274 EXPECT_EQ(0b111, tst.alias_all);
275 }
276
277 {
278 TestBitStruct_u8 tst{};
279 tst.u4 = all_1s.u4;
280
281 // Copying a single bitfield does not copy all bitfields.
282 EXPECT_EQ(0b1111000, tst.alias_all);
283 }
284 }
285
286 BITSTRUCT_DEFINE_START(NestedStruct, /* size= */ 64)
287 BitStructField<MixedSizeBitStruct, /*lsb=*/0> mixed_lower;
288 BitStructField<MixedSizeBitStruct, /*lsb=*/32> mixed_upper;
289
290 BitStructUint</*lsb=*/0, /*width=*/64> alias_all;
291 BITSTRUCT_DEFINE_END(NestedStruct);
292
TEST(BitStructs,NestedFieldAssignment)293 TEST(BitStructs, NestedFieldAssignment) {
294 MixedSizeBitStruct mixed_all_1s{};
295 mixed_all_1s.alias_all = 0xFFFFFFFFu;
296
297 {
298 NestedStruct xyz{};
299
300 NestedStruct other{};
301 other.mixed_upper = mixed_all_1s;
302 other.mixed_lower = mixed_all_1s;
303
304 // Copying a single bitfield does not copy all bitfields.
305 xyz.mixed_lower = other.mixed_lower;
306 EXPECT_EQ(0xFFFFFFFFu, xyz.alias_all);
307 }
308
309 {
310 NestedStruct xyz{};
311
312 NestedStruct other{};
313 other.mixed_upper = mixed_all_1s;
314 other.mixed_lower = mixed_all_1s;
315
316 // Copying a single bitfield does not copy all bitfields.
317 xyz.mixed_upper = other.mixed_upper;
318 EXPECT_EQ(0xFFFFFFFF00000000u, xyz.alias_all);
319 }
320 }
321
322 } // namespace art
323