Home | History | Annotate | Download | only in base
      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