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