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> 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 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> 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; 64 explicit CustomBitStruct(int8_t data) : data(data) {} 65 66 static constexpr size_t BitStructSizeOf() { 67 return 4; 68 } 69 70 int8_t data; 71 }; 72 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 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 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 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 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 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 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