/*
* Copyright ( C ) 2017 The Android Open Source Project
*
* Licensed under the Apache License , Version 2 . 0 ( the " License " ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an " AS IS " BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
*/
#include "bit_struct.h"
#include "gtest/gtest.h"
namespace art {
// A copy of detail::ValidateBitStructSize that uses EXPECT for a more
// human-readable message.
template <typename T>
static constexpr bool ValidateBitStructSize(const char * name) {
const size_t kBitStructSizeOf = BitStructSizeOf<T>();
const size_t kExpectedSize = (BitStructSizeOf<T>() < kBitsPerByte)
? kBitsPerByte
: RoundUpToPowerOfTwo(kBitStructSizeOf);
// Ensure no extra fields were added in between START/END.
const size_t kActualSize = sizeof (T) * kBitsPerByte;
EXPECT_EQ(kExpectedSize, kActualSize) << name;
return true ;
}
#define VALIDATE_BITSTRUCT_SIZE(type) ValidateBitStructSize<type>(#type )
TEST(BitStructs, MinimumType) {
EXPECT_EQ(1 u, sizeof (typename detail::MinimumTypeUnsignedHelper<1 >::type));
EXPECT_EQ(1 u, sizeof (typename detail::MinimumTypeUnsignedHelper<2 >::type));
EXPECT_EQ(1 u, sizeof (typename detail::MinimumTypeUnsignedHelper<3 >::type));
EXPECT_EQ(1 u, sizeof (typename detail::MinimumTypeUnsignedHelper<8 >::type));
EXPECT_EQ(2 u, sizeof (typename detail::MinimumTypeUnsignedHelper<9 >::type));
EXPECT_EQ(2 u, sizeof (typename detail::MinimumTypeUnsignedHelper<10 >::type));
EXPECT_EQ(2 u, sizeof (typename detail::MinimumTypeUnsignedHelper<15 >::type));
EXPECT_EQ(2 u, sizeof (typename detail::MinimumTypeUnsignedHelper<16 >::type));
EXPECT_EQ(4 u, sizeof (typename detail::MinimumTypeUnsignedHelper<17 >::type));
EXPECT_EQ(4 u, sizeof (typename detail::MinimumTypeUnsignedHelper<32 >::type));
EXPECT_EQ(8 u, sizeof (typename detail::MinimumTypeUnsignedHelper<33 >::type));
EXPECT_EQ(8 u, sizeof (typename detail::MinimumTypeUnsignedHelper<64 >::type));
}
template <typename T>
size_t AsUint(const T& value) {
size_t uint_value = 0 ;
memcpy(&uint_value, &value, sizeof (value));
return uint_value;
}
struct CustomBitStruct {
CustomBitStruct() = default ;
explicit CustomBitStruct(uint8_t data) : data(data) {}
static constexpr size_t BitStructSizeOf() {
return 4 ;
}
uint8_t data;
};
TEST(BitStructs, Custom) {
CustomBitStruct expected(0 b1111u);
BitStructField<CustomBitStruct, /*lsb=*/4, /*width=*/4, uint8_t> f{};
EXPECT_EQ(1 u, sizeof (f));
f = CustomBitStruct(0 b1111u);
CustomBitStruct read_out = f;
EXPECT_EQ(read_out.data, 0 b1111u);
EXPECT_EQ(AsUint(f), 0 b11110000u);
}
BITSTRUCT_DEFINE_START(TestTwoCustom, /* size= */ 8)
BITSTRUCT_FIELD(CustomBitStruct, /*lsb=*/0, /*width=*/4) f4_a;
BITSTRUCT_FIELD(CustomBitStruct, /*lsb=*/4, /*width=*/4) f4_b;
BITSTRUCT_DEFINE_END(TestTwoCustom);
TEST(BitStructs, TwoCustom) {
EXPECT_EQ(sizeof (TestTwoCustom), 1 u);
VALIDATE_BITSTRUCT_SIZE(TestTwoCustom);
TestTwoCustom cst{};
// Test the write to most-significant field doesn't clobber least-significant.
cst.f4_a = CustomBitStruct(0 b0110);
cst.f4_b = CustomBitStruct(0 b0101);
int8_t read_out = static_cast <CustomBitStruct>(cst.f4_a).data;
int8_t read_out_b = static_cast <CustomBitStruct>(cst.f4_b).data;
EXPECT_EQ(0 b0110, static_cast <int >(read_out));
EXPECT_EQ(0 b0101, static_cast <int >(read_out_b));
EXPECT_EQ(AsUint(cst), 0 b01010110u);
// Test write to least-significant field doesn't clobber most-significant.
cst.f4_a = CustomBitStruct(0 );
read_out = static_cast <CustomBitStruct>(cst.f4_a).data;
read_out_b = static_cast <CustomBitStruct>(cst.f4_b).data;
EXPECT_EQ(0 b0, static_cast <int >(read_out));
EXPECT_EQ(0 b0101, static_cast <int >(read_out_b));
EXPECT_EQ(AsUint(cst), 0 b01010000u);
}
TEST(BitStructs, Number) {
BitStructNumber<uint16_t, /*lsb=*/4, /*width=*/4, uint16_t> bsn{};
EXPECT_EQ(2 u, sizeof (bsn));
bsn = 0 b1111;
uint32_t read_out = static_cast <uint32_t>(bsn);
uint32_t read_out_impl = bsn;
EXPECT_EQ(read_out, read_out_impl);
EXPECT_EQ(read_out, 0 b1111u);
EXPECT_EQ(AsUint(bsn), 0 b11110000u);
}
TEST(BitStructs, NumberNarrowStorage) {
BitStructNumber<uint16_t, /*lsb=*/4, /*width=*/4, uint8_t> bsn{};
EXPECT_EQ(1 u, sizeof (bsn));
bsn = 0 b1111;
uint32_t read_out = static_cast <uint32_t>(bsn);
uint32_t read_out_impl = bsn;
EXPECT_EQ(read_out, read_out_impl);
EXPECT_EQ(read_out, 0 b1111u);
EXPECT_EQ(AsUint(bsn), 0 b11110000u);
}
BITSTRUCT_DEFINE_START(TestBitStruct, /* size= */ 8)
BITSTRUCT_INT(/*lsb=*/0, /*width=*/3) i3;
BITSTRUCT_UINT(/*lsb=*/3, /*width=*/4) u4;
BITSTRUCT_UINT(/*lsb=*/0, /*width=*/7) alias_all;
BITSTRUCT_DEFINE_END(TestBitStruct);
TEST(BitStructs, Test1) {
TestBitStruct tst{};
// Check minimal size selection is correct.
EXPECT_EQ(1 u, sizeof (TestBitStruct));
EXPECT_EQ(1 u, sizeof (tst._));
EXPECT_EQ(1 u, sizeof (tst.i3));
EXPECT_EQ(1 u, sizeof (tst.u4));
EXPECT_EQ(1 u, sizeof (tst.alias_all));
// Check operator assignment.
tst.i3 = -1 ;
tst.u4 = 0 b1010;
// Check implicit operator conversion.
int8_t read_i3 = tst.i3;
uint8_t read_u4 = tst.u4;
// Ensure read-out values were correct.
EXPECT_EQ(static_cast <int8_t>(-1 ), read_i3);
EXPECT_EQ(0 b1010, read_u4);
// Ensure aliasing is working.
EXPECT_EQ(0 b1010111, static_cast <uint8_t>(tst.alias_all));
// Ensure the bit pattern is correct.
EXPECT_EQ(0 b1010111u, AsUint(tst));
// Math operator checks
{
// In-place
++tst.u4;
EXPECT_EQ(static_cast <uint8_t>(0 b1011), static_cast <uint8_t>(tst.u4));
--tst.u4;
EXPECT_EQ(static_cast <uint8_t>(0 b1010), static_cast <uint8_t>(tst.u4));
// Copy
uint8_t read_and_convert = tst.u4++;
EXPECT_EQ(static_cast <uint8_t>(0 b1011), read_and_convert);
EXPECT_EQ(static_cast <uint8_t>(0 b1010), static_cast <uint8_t>(tst.u4));
read_and_convert = tst.u4--;
EXPECT_EQ(static_cast <uint8_t>(0 b1001), read_and_convert);
EXPECT_EQ(static_cast <uint8_t>(0 b1010), static_cast <uint8_t>(tst.u4));
// Check boolean operator conversion.
tst.u4 = 0 b1010;
EXPECT_TRUE(static_cast <bool >(tst.u4));
bool succ = tst.u4 ? true : false ;
EXPECT_TRUE(succ);
tst.u4 = 0 ;
EXPECT_FALSE(static_cast <bool >(tst.u4));
/*
// Disabled: Overflow is caught by the BitFieldInsert DCHECKs.
// Check overflow for uint.
tst . u4 = 0 b1111 ;
+ + tst . u4 ;
EXPECT_EQ ( static_cast < uint8_t > ( 0 ) , static_cast < uint8_t > ( tst . u4 ) ) ;
*/
}
}
BITSTRUCT_DEFINE_START(MixedSizeBitStruct, /* size= */ 32)
BITSTRUCT_UINT(/*lsb=*/0, /*width=*/3) u3;
BITSTRUCT_UINT(/*lsb=*/3, /*width=*/10) u10;
BITSTRUCT_UINT(/*lsb=*/13, /*width=*/19) u19;
BITSTRUCT_UINT(/*lsb=*/0, /*width=*/32) alias_all;
BITSTRUCT_DEFINE_END(MixedSizeBitStruct);
// static_assert(sizeof(MixedSizeBitStruct) == sizeof(uint32_t), "TestBitStructs#MixedSize");
TEST(BitStructs, Mixed) {
EXPECT_EQ(4 u, sizeof (MixedSizeBitStruct));
MixedSizeBitStruct tst{};
// Check operator assignment.
tst.u3 = 0 b111u;
tst.u10 = 0 b1111010100u;
tst.u19 = 0 b1010101010101010101u;
// Check implicit operator conversion.
uint8_t read_u3 = tst.u3;
uint16_t read_u10 = tst.u10;
uint32_t read_u19 = tst.u19;
// Ensure read-out values were correct.
EXPECT_EQ(0 b111u, read_u3);
EXPECT_EQ(0 b1111010100u, read_u10);
EXPECT_EQ(0 b1010101010101010101u, read_u19);
uint32_t read_all = tst.alias_all;
// Ensure aliasing is working.
EXPECT_EQ(0 b10101010101010101011111010100111u, read_all);
// Ensure the bit pattern is correct.
EXPECT_EQ(0 b10101010101010101011111010100111u, AsUint(tst));
}
BITSTRUCT_DEFINE_START(TestBitStruct_u8, /* size= */ 8)
BITSTRUCT_INT(/*lsb=*/0, /*width=*/3) i3;
BITSTRUCT_UINT(/*lsb=*/3, /*width=*/4) u4;
BITSTRUCT_UINT(/*lsb=*/0, /*width=*/8) alias_all;
BITSTRUCT_DEFINE_END(TestBitStruct_u8);
TEST(BitStructs, FieldAssignment) {
TestBitStruct_u8 all_1s{};
all_1s.alias_all = 0 xffu;
{
TestBitStruct_u8 tst{};
tst.i3 = all_1s.i3;
// Copying a single bitfield does not copy all bitfields.
EXPECT_EQ(0 b111, tst.alias_all);
}
{
TestBitStruct_u8 tst{};
tst.u4 = all_1s.u4;
// Copying a single bitfield does not copy all bitfields.
EXPECT_EQ(0 b1111000, tst.alias_all);
}
}
BITSTRUCT_DEFINE_START(NestedStruct, /* size= */ 2 * MixedSizeBitStruct::BitStructSizeOf())
BITSTRUCT_FIELD(MixedSizeBitStruct,
/*lsb=*/0,
/*width=*/MixedSizeBitStruct::BitStructSizeOf()) mixed_lower;
BITSTRUCT_FIELD(MixedSizeBitStruct,
/*lsb=*/MixedSizeBitStruct::BitStructSizeOf(),
/*width=*/MixedSizeBitStruct::BitStructSizeOf()) mixed_upper;
BITSTRUCT_UINT(/*lsb=*/0, /*width=*/ 2 * MixedSizeBitStruct::BitStructSizeOf()) alias_all;
BITSTRUCT_DEFINE_END(NestedStruct);
TEST(BitStructs, NestedFieldAssignment) {
MixedSizeBitStruct mixed_all_1s{};
mixed_all_1s.alias_all = 0 xFFFFFFFFu;
{
NestedStruct xyz{};
NestedStruct other{};
other.mixed_upper = mixed_all_1s;
other.mixed_lower = mixed_all_1s;
// Copying a single bitfield does not copy all bitfields.
xyz.mixed_lower = other.mixed_lower;
EXPECT_EQ(0 xFFFFFFFFu, xyz.alias_all);
}
{
NestedStruct xyz{};
NestedStruct other{};
other.mixed_upper = mixed_all_1s;
other.mixed_lower = mixed_all_1s;
// Copying a single bitfield does not copy all bitfields.
xyz.mixed_upper = other.mixed_upper;
EXPECT_EQ(0 xFFFFFFFF00000000u, xyz.alias_all);
}
}
} // namespace art
Messung V0.5 in Prozent C=90 H=95 G=92
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-06-29)
¤
*© Formatika GbR, Deutschland