• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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