Path: blob/master/src/common-tests/bitutils_tests.cpp
4212 views
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#include "common/align.h"4#include "common/bitfield.h"5#include "common/bitutils.h"67#include "gtest/gtest.h"89#include <type_traits>1011// Test fixture for BitField tests12namespace {13// Simple test structs using different backing types and field configurations14union TestUnion815{16u8 bits;17BitField<u8, bool, 0, 1> flag;18BitField<u8, u8, 1, 3> value3bit;19BitField<u8, u8, 4, 4> value4bit;20BitField<u8, s8, 4, 4> signed4bit;21};2223union TestUnion1624{25u16 bits;26BitField<u16, bool, 0, 1> flag;27BitField<u16, u8, 1, 8> value8bit;28BitField<u16, u8, 9, 7> value7bit;29BitField<u16, s8, 8, 8> signed8bit;30};3132union TestUnion3233{34u32 bits;35BitField<u32, bool, 0, 1> flag;36BitField<u32, u16, 1, 16> value16bit;37BitField<u32, u32, 17, 15> value15bit;38BitField<u32, s16, 16, 16> signed16bit;39};4041union TestUnion6442{43u64 bits;44BitField<u64, bool, 0, 1> flag;45BitField<u64, u32, 1, 32> value32bit;46BitField<u64, u64, 33, 31> value31bit;47BitField<u64, s32, 32, 32> signed32bit;48};49} // namespace5051// Tests for GetMask method52TEST(BitField, GetMask)53{54TestUnion8 test8{};55EXPECT_EQ(test8.flag.GetMask(), 0x01u);56EXPECT_EQ(test8.value3bit.GetMask(), 0x0Eu);57EXPECT_EQ(test8.value4bit.GetMask(), 0xF0u);5859TestUnion16 test16{};60EXPECT_EQ(test16.flag.GetMask(), 0x0001u);61EXPECT_EQ(test16.value8bit.GetMask(), 0x01FEu);62EXPECT_EQ(test16.value7bit.GetMask(), 0xFE00u);6364TestUnion32 test32{};65EXPECT_EQ(test32.flag.GetMask(), 0x00000001u);66EXPECT_EQ(test32.value16bit.GetMask(), 0x0001FFFEu);67EXPECT_EQ(test32.value15bit.GetMask(), 0xFFFE0000u);6869TestUnion64 test64{};70EXPECT_EQ(test64.flag.GetMask(), 0x0000000000000001ULL);71EXPECT_EQ(test64.value32bit.GetMask(), 0x00000001FFFFFFFEULL);72EXPECT_EQ(test64.value31bit.GetMask(), 0xFFFFFFFE00000000ULL);73}7475// Tests for implicit conversion operator (operator DataType())76TEST(BitField, ImplicitConversion)77{78TestUnion8 test8{};79test8.bits = 0xFF;8081bool flag_value = test8.flag;82EXPECT_TRUE(flag_value);8384u8 value3bit_value = test8.value3bit;85EXPECT_EQ(value3bit_value, 7);8687u8 value4bit_value = test8.value4bit;88EXPECT_EQ(value4bit_value, 15);8990// Test with zeros91test8.bits = 0x00;92flag_value = test8.flag;93EXPECT_FALSE(flag_value);9495value3bit_value = test8.value3bit;96EXPECT_EQ(value3bit_value, 0);97}9899// Tests for assignment operator (operator=)100TEST(BitField, Assignment)101{102TestUnion8 test8{};103test8.bits = 0x00;104105test8.flag = true;106EXPECT_EQ(test8.bits, 0x01);107108test8.value3bit = 5;109EXPECT_EQ(test8.bits, 0x0B); // 0001 (flag) + 1010 (5 << 1)110111test8.value4bit = 12;112EXPECT_EQ(test8.bits, 0xCB); // Previous + 1100 (12 << 4)113114// Test overwriting115test8.flag = false;116EXPECT_EQ(test8.bits, 0xCA);117}118119// Tests for prefix increment operator (operator++())120TEST(BitField, PrefixIncrement)121{122TestUnion8 test8{};123test8.bits = 0x00;124test8.value3bit = 3;125126u8 result = ++test8.value3bit;127EXPECT_EQ(result, 4);128EXPECT_EQ(static_cast<u8>(test8.value3bit), 4);129130// Test overflow handling131test8.value3bit = 7; // Maximum for 3 bits132result = ++test8.value3bit;133EXPECT_EQ(result, 0); // Should wrap around134EXPECT_EQ(static_cast<u8>(test8.value3bit), 0);135}136137// Tests for postfix increment operator (operator++(int))138TEST(BitField, PostfixIncrement)139{140TestUnion8 test8{};141test8.bits = 0x00;142test8.value3bit = 3;143144u8 result = test8.value3bit++;145EXPECT_EQ(result, 3); // Should return old value146EXPECT_EQ(static_cast<u8>(test8.value3bit), 4); // Should increment147148// Test overflow handling149test8.value3bit = 7; // Maximum for 3 bits150result = test8.value3bit++;151EXPECT_EQ(result, 7); // Should return old value152EXPECT_EQ(static_cast<u8>(test8.value3bit), 0); // Should wrap around153}154155// Tests for prefix decrement operator (operator--())156TEST(BitField, PrefixDecrement)157{158TestUnion8 test8{};159test8.bits = 0x00;160test8.value3bit = 4;161162u8 result = --test8.value3bit;163EXPECT_EQ(result, 3);164EXPECT_EQ(static_cast<u8>(test8.value3bit), 3);165166// Test underflow handling167test8.value3bit = 0;168result = --test8.value3bit;169EXPECT_EQ(result, 7); // Should wrap around170EXPECT_EQ(static_cast<u8>(test8.value3bit), 7);171}172173// Tests for postfix decrement operator (operator--(int))174TEST(BitField, PostfixDecrement)175{176TestUnion8 test8{};177test8.bits = 0x00;178test8.value3bit = 4;179180u8 result = test8.value3bit--;181EXPECT_EQ(result, 4); // Should return old value182EXPECT_EQ(static_cast<u8>(test8.value3bit), 3); // Should decrement183184// Test underflow handling185test8.value3bit = 0;186result = test8.value3bit--;187EXPECT_EQ(result, 0); // Should return old value188EXPECT_EQ(static_cast<u8>(test8.value3bit), 7); // Should wrap around189}190191// Tests for compound assignment operators (+=, -=, *=, /=)192TEST(BitField, CompoundArithmeticOperators)193{194TestUnion8 test8{};195test8.bits = 0x00;196test8.value4bit = 5;197198// Test +=199test8.value4bit += 3;200EXPECT_EQ(static_cast<u8>(test8.value4bit), 8);201202// Test -=203test8.value4bit -= 2;204EXPECT_EQ(static_cast<u8>(test8.value4bit), 6);205206// Test *=207test8.value4bit *= 2;208EXPECT_EQ(static_cast<u8>(test8.value4bit), 12);209210// Test / =211test8.value4bit /= 3;212EXPECT_EQ(static_cast<u8>(test8.value4bit), 4);213214// Test overflow with +=215test8.value4bit = 14;216test8.value4bit += 5; // Should overflow and wrap217EXPECT_EQ(static_cast<u8>(test8.value4bit), 3); // (14 + 5) & 0xF = 19 & 0xF = 3218}219220// Tests for compound bitwise operators (&=, |=, ^=, <<=, >>=)221TEST(BitField, CompoundBitwiseOperators)222{223TestUnion8 test8{};224test8.bits = 0x00;225test8.value4bit = 12; // 1100226227// Test & =228test8.value4bit &= 10; // 1100 & 1010 = 1000229EXPECT_EQ(static_cast<u8>(test8.value4bit), 8);230231// Test |=232test8.value4bit |= 3; // 1000 | 0011 = 1011233EXPECT_EQ(static_cast<u8>(test8.value4bit), 11);234235// Test ^ =236test8.value4bit ^= 5; // 1011 ^ 0101 = 1110237EXPECT_EQ(static_cast<u8>(test8.value4bit), 14);238239// Test << =240test8.value4bit = 3; // 0011241test8.value4bit <<= 2; // 0011 << 2 = 1100242EXPECT_EQ(static_cast<u8>(test8.value4bit), 12);243244// Test >> =245test8.value4bit >>= 1; // 1100 >> 1 = 0110246EXPECT_EQ(static_cast<u8>(test8.value4bit), 6);247}248249// Tests for GetValue method with different data types250TEST(BitField, GetValue)251{252// Test unsigned values253TestUnion16 test16{};254test16.bits = 0xFFFF;255EXPECT_EQ(test16.flag.GetValue(), true);256EXPECT_EQ(test16.value8bit.GetValue(), 0xFF);257EXPECT_EQ(test16.value7bit.GetValue(), 0x7F);258259// Test signed values260test16.bits = 0xFF00; // Set upper 8 bits261EXPECT_EQ(test16.signed8bit.GetValue(), -1); // Should be sign-extended262263test16.bits = 0x7F00; // Set bit pattern for +127264EXPECT_EQ(test16.signed8bit.GetValue(), 127);265266test16.bits = 0x8000; // Set bit pattern for -128267EXPECT_EQ(test16.signed8bit.GetValue(), -128);268}269270// Tests for SetValue method271TEST(BitField, SetValue)272{273TestUnion16 test16{};274test16.bits = 0x0000;275276test16.flag.SetValue(true);277EXPECT_EQ(test16.bits, 0x0001);278279test16.value8bit.SetValue(0xAB);280EXPECT_EQ(test16.bits, 0x0157); // 0xAB << 1 | 0x0001281282test16.value7bit.SetValue(0x55);283EXPECT_EQ(test16.bits, 0xAB57); // 0x55 << 9 | previous284285// Test that setting doesn't affect other fields286test16.bits = 0xFFFF;287test16.flag.SetValue(false);288EXPECT_EQ(test16.bits, 0xFFFE); // Only bit 0 should be cleared289}290291// Tests for boolean BitFields (1-bit fields)292TEST(BitField, BooleanBitFields)293{294TestUnion8 test8{};295test8.bits = 0x00;296297// Test setting and getting boolean values298test8.flag.SetValue(true);299EXPECT_TRUE(test8.flag.GetValue());300EXPECT_TRUE(static_cast<bool>(test8.flag));301302test8.flag.SetValue(false);303EXPECT_FALSE(test8.flag.GetValue());304EXPECT_FALSE(static_cast<bool>(test8.flag));305306// Test that any non-zero value in the bit position is treated as true307test8.bits = 0x01;308EXPECT_TRUE(test8.flag.GetValue());309}310311// Tests for signed BitFields with sign extension312TEST(BitField, SignedBitFields)313{314TestUnion32 test32{};315test32.bits = 0x00000000;316317// Test positive signed values318test32.signed16bit.SetValue(12345);319EXPECT_EQ(test32.signed16bit.GetValue(), 12345);320321// Test negative signed values322test32.signed16bit.SetValue(-12345);323EXPECT_EQ(test32.signed16bit.GetValue(), -12345);324325// Test maximum positive value for 16-bit signed326test32.signed16bit.SetValue(32767);327EXPECT_EQ(test32.signed16bit.GetValue(), 32767);328329// Test minimum negative value for 16-bit signed330test32.signed16bit.SetValue(-32768);331EXPECT_EQ(test32.signed16bit.GetValue(), -32768);332333// Test sign extension with manual bit manipulation334test32.bits = 0xFFFF0000; // Set all bits in the signed field to 1335EXPECT_EQ(test32.signed16bit.GetValue(), -1);336}337338// Tests for edge cases and boundary conditions339TEST(BitField, EdgeCases)340{341TestUnion64 test64{};342test64.bits = 0x0000000000000000ULL;343344// Test maximum values345test64.value32bit.SetValue(0xFFFFFFFF);346EXPECT_EQ(test64.value32bit.GetValue(), 0xFFFFFFFFu);347348test64.value31bit.SetValue(0x7FFFFFFF);349EXPECT_EQ(test64.value31bit.GetValue(), 0x7FFFFFFFu);350351// Test that fields don't interfere with each other352test64.bits = 0x0000000000000000ULL;353test64.flag.SetValue(true);354test64.value32bit.SetValue(0x12345678);355test64.value31bit.SetValue(0x55555555);356357EXPECT_TRUE(test64.flag.GetValue());358EXPECT_EQ(test64.value32bit.GetValue(), 0x12345678u);359EXPECT_EQ(test64.value31bit.GetValue(), 0x55555555u);360}361362// Tests for arithmetic operations that may cause overflow363TEST(BitField, OverflowBehavior)364{365TestUnion8 test8{};366test8.bits = 0x00;367368// Test 3-bit field (max value 7)369test8.value3bit.SetValue(7);370test8.value3bit += 1; // Should overflow371EXPECT_EQ(static_cast<u8>(test8.value3bit), 0);372373test8.value3bit.SetValue(7);374test8.value3bit *= 2; // 7 * 2 = 14, should wrap to 6 (14 & 0x7)375EXPECT_EQ(static_cast<u8>(test8.value3bit), 6);376377// Test underflow378test8.value3bit.SetValue(0);379test8.value3bit -= 1; // Should underflow380EXPECT_EQ(static_cast<u8>(test8.value3bit), 7);381}382383// Tests for chaining operations384TEST(BitField, OperatorChaining)385{386TestUnion8 test8{};387test8.bits = 0x00;388389// Test chaining assignment operators390auto& result = test8.value3bit = 5;391EXPECT_EQ(&result, &test8.value3bit);392EXPECT_EQ(static_cast<u8>(test8.value3bit), 5);393394// Test chaining compound operators395auto& result2 = (test8.value3bit += 2);396EXPECT_EQ(&result2, &test8.value3bit);397EXPECT_EQ(static_cast<u8>(test8.value3bit), 7);398}399400// Tests for static_assert conditions401TEST(BitField, StaticAssertions)402{403// These should compile without issues due to the static_assert in BitField404405// Boolean fields should only be 1 bit406union TestBoolField407{408u8 bits;409BitField<u8, bool, 0, 1> valid_bool; // This should compile410};411412// This would fail to compile:413// BitField<u8, bool, 0, 2> invalid_bool; // static_assert should trigger414415TestBoolField test{};416test.bits = 0;417test.valid_bool = true;418EXPECT_TRUE(test.valid_bool);419}420421template<typename T>422static inline constexpr unsigned ManualCountLeadingZeros(T value)423{424constexpr unsigned BITS = sizeof(T) * 8u;425constexpr T MASK = T(1) << (BITS - 1);426427unsigned count = 0;428for (unsigned i = 0; i < BITS && (value & MASK) == 0; i++)429{430count++;431value <<= 1;432}433434return count;435}436437template<typename T>438static inline constexpr unsigned ManualCountTrailingZeros(T value)439{440constexpr unsigned BITS = sizeof(T) * 8u;441constexpr auto MASK = static_cast<std::make_unsigned_t<T>>(1);442443auto u_value = static_cast<std::make_unsigned_t<T>>(value);444445unsigned count = 0;446for (unsigned i = 0; i < BITS && (u_value & MASK) != MASK; i++)447{448count++;449u_value >>= 1;450}451452return count;453}454455TEST(BitUtils, Test8Bit)456{457ASSERT_EQ(CountLeadingZeros(u8(1)), ManualCountLeadingZeros(u8(1)));458ASSERT_EQ(CountLeadingZeros(u8(2)), ManualCountLeadingZeros(u8(2)));459ASSERT_EQ(CountLeadingZeros(u8(4)), ManualCountLeadingZeros(u8(4)));460ASSERT_EQ(CountLeadingZeros(u8(8)), ManualCountLeadingZeros(u8(8)));461ASSERT_EQ(CountLeadingZeros(u8(16)), ManualCountLeadingZeros(u8(16)));462ASSERT_EQ(CountLeadingZeros(u8(32)), ManualCountLeadingZeros(u8(32)));463ASSERT_EQ(CountLeadingZeros(u8(64)), ManualCountLeadingZeros(u8(64)));464ASSERT_EQ(CountLeadingZeros(u8(128)), ManualCountLeadingZeros(u8(128)));465466ASSERT_EQ(CountTrailingZeros(u8(1)), ManualCountTrailingZeros(u8(1)));467ASSERT_EQ(CountTrailingZeros(u8(2)), ManualCountTrailingZeros(u8(2)));468ASSERT_EQ(CountTrailingZeros(u8(4)), ManualCountTrailingZeros(u8(4)));469ASSERT_EQ(CountTrailingZeros(u8(8)), ManualCountTrailingZeros(u8(8)));470ASSERT_EQ(CountTrailingZeros(u8(16)), ManualCountTrailingZeros(u8(16)));471ASSERT_EQ(CountTrailingZeros(u8(32)), ManualCountTrailingZeros(u8(32)));472ASSERT_EQ(CountTrailingZeros(u8(64)), ManualCountTrailingZeros(u8(64)));473ASSERT_EQ(CountTrailingZeros(u8(128)), ManualCountTrailingZeros(u8(128)));474}475476TEST(BitUtils, Test16Bit)477{478for (u32 i = 1; i < 0x10000; i++)479{480u16 value = Truncate16(i);481ASSERT_EQ(CountLeadingZeros(value), ManualCountLeadingZeros(value));482ASSERT_EQ(CountTrailingZeros(value), ManualCountTrailingZeros(value));483}484}485486TEST(BitUtils, ZeroExtendHelpers)487{488EXPECT_EQ(ZeroExtend16(u8(0xFF)), 0x00FFu);489EXPECT_EQ(ZeroExtend32(u16(0xFFFF)), 0x0000FFFFu);490EXPECT_EQ(ZeroExtend64(u32(0xFFFFFFFF)), 0x00000000FFFFFFFFull);491}492493TEST(BitUtils, SignExtendHelpers)494{495EXPECT_EQ(SignExtend16(s8(-1)), 0xFFFFu);496EXPECT_EQ(SignExtend32(s16(-1)), 0xFFFFFFFFu);497EXPECT_EQ(SignExtend64(s32(-1)), 0xFFFFFFFFFFFFFFFFull);498}499500TEST(BitUtils, TruncateHelpers)501{502EXPECT_EQ(Truncate8(u16(0x1234)), 0x34u);503EXPECT_EQ(Truncate16(u32(0x12345678)), 0x5678u);504EXPECT_EQ(Truncate32(u64(0x123456789ABCDEF0)), 0x9ABCDEF0u);505}506507TEST(BitUtils, BinaryToBCD)508{509EXPECT_EQ(BinaryToBCD(0), 0x00u);510EXPECT_EQ(BinaryToBCD(9), 0x09u);511EXPECT_EQ(BinaryToBCD(12), 0x12u);512EXPECT_EQ(BinaryToBCD(99), 0x99u);513}514515TEST(BitUtils, PackedBCDToBinary)516{517EXPECT_EQ(PackedBCDToBinary(0x00), 0);518EXPECT_EQ(PackedBCDToBinary(0x09), 9);519EXPECT_EQ(PackedBCDToBinary(0x12), 12);520EXPECT_EQ(PackedBCDToBinary(0x99), 99);521}522523TEST(BitUtils, IsValidBCDDigit)524{525for (u8 i = 0; i < 10; ++i)526EXPECT_TRUE(IsValidBCDDigit(i));527for (u8 i = 10; i < 16; ++i)528EXPECT_FALSE(IsValidBCDDigit(i));529}530531TEST(BitUtils, IsValidPackedBCD)532{533EXPECT_TRUE(IsValidPackedBCD(0x12));534EXPECT_TRUE(IsValidPackedBCD(0x99));535EXPECT_FALSE(IsValidPackedBCD(0x1A));536EXPECT_FALSE(IsValidPackedBCD(0xA1));537}538539TEST(BitUtils, BoolToUInt)540{541EXPECT_EQ(BoolToUInt8(true), 1u);542EXPECT_EQ(BoolToUInt8(false), 0u);543EXPECT_EQ(BoolToUInt16(true), 1u);544EXPECT_EQ(BoolToUInt32(false), 0u);545EXPECT_EQ(BoolToUInt64(true), 1ull);546EXPECT_FLOAT_EQ(BoolToFloat(true), 1.0f);547EXPECT_FLOAT_EQ(BoolToFloat(false), 0.0f);548}549550TEST(BitUtils, ConvertToBool)551{552EXPECT_TRUE(ConvertToBool(1));553EXPECT_FALSE(ConvertToBool(0));554EXPECT_TRUE(ConvertToBool(-1));555EXPECT_TRUE(ConvertToBool(123));556}557558TEST(BitUtils, ConvertToBoolUnchecked)559{560u8 one = 1, zero = 0;561EXPECT_TRUE(ConvertToBoolUnchecked(one));562EXPECT_FALSE(ConvertToBoolUnchecked(zero));563}564565TEST(BitUtils, SignExtendN)566{567EXPECT_EQ(SignExtendN<4>(0b0111), 7);568EXPECT_EQ(SignExtendN<4>(0b1000), -8);569EXPECT_EQ(SignExtendN<8>(0xFF), -1);570EXPECT_EQ(SignExtendN<12>(0x800), -2048);571}572573TEST(BitUtils, CountLeadingZeros)574{575EXPECT_EQ(CountLeadingZeros<u8>(0b00010000), 3u);576EXPECT_EQ(CountLeadingZeros<u16>(0x0001), 15u);577EXPECT_EQ(CountLeadingZeros<u32>(0x80000000), 0u);578EXPECT_EQ(CountLeadingZeros<u64>(0x0000000100000000ull), 31u);579}580581TEST(BitUtils, CountTrailingZeros)582{583EXPECT_EQ(CountTrailingZeros<u8>(0b10000000), 7u);584EXPECT_EQ(CountTrailingZeros<u16>(0x8000), 15u);585EXPECT_EQ(CountTrailingZeros<u32>(0x00010000), 16u);586EXPECT_EQ(CountTrailingZeros<u64>(0x0000000100000000ull), 32u);587}588589TEST(BitUtils, ByteSwap)590{591EXPECT_EQ(ByteSwap<u16>(0x1234), 0x3412u);592EXPECT_EQ(ByteSwap<u32>(0x12345678), 0x78563412u);593EXPECT_EQ(ByteSwap<u64>(0x0123456789ABCDEFull), 0xEFCDAB8967452301ull);594EXPECT_EQ(ByteSwap<s16>(s16(0x1234)), s16(0x3412));595EXPECT_EQ(ByteSwap<s32>(s32(0x12345678)), s32(0x78563412));596EXPECT_EQ(ByteSwap<s64>(s64(0x0123456789ABCDEFll)), s64(0xEFCDAB8967452301ll));597}598599// Alignment function tests600TEST(Align, IsAligned)601{602// Test with various integer types and alignments603EXPECT_TRUE(Common::IsAligned(0u, 4u));604EXPECT_TRUE(Common::IsAligned(4u, 4u));605EXPECT_TRUE(Common::IsAligned(8u, 4u));606EXPECT_TRUE(Common::IsAligned(16u, 4u));607EXPECT_FALSE(Common::IsAligned(1u, 4u));608EXPECT_FALSE(Common::IsAligned(3u, 4u));609EXPECT_FALSE(Common::IsAligned(5u, 4u));610611// Test with pointer types612EXPECT_TRUE(Common::IsAligned(reinterpret_cast<uintptr_t>(nullptr), 8u));613EXPECT_TRUE(Common::IsAligned(0x1000ull, 16u));614EXPECT_FALSE(Common::IsAligned(0x1001ull, 16u));615616// Test with different alignments617EXPECT_TRUE(Common::IsAligned(15u, 1u));618EXPECT_TRUE(Common::IsAligned(16u, 8u));619EXPECT_FALSE(Common::IsAligned(15u, 8u));620}621622TEST(Align, AlignUp)623{624// Test basic alignment up625EXPECT_EQ(Common::AlignUp(0u, 4u), 0u);626EXPECT_EQ(Common::AlignUp(1u, 4u), 4u);627EXPECT_EQ(Common::AlignUp(3u, 4u), 4u);628EXPECT_EQ(Common::AlignUp(4u, 4u), 4u);629EXPECT_EQ(Common::AlignUp(5u, 4u), 8u);630EXPECT_EQ(Common::AlignUp(7u, 4u), 8u);631EXPECT_EQ(Common::AlignUp(8u, 4u), 8u);632633// Test with larger values634EXPECT_EQ(Common::AlignUp(1000u, 64u), 1024u);635EXPECT_EQ(Common::AlignUp(1024u, 64u), 1024u);636EXPECT_EQ(Common::AlignUp(1025u, 64u), 1088u);637638// Test with different types639EXPECT_EQ(Common::AlignUp(13ull, 8u), 16ull);640EXPECT_EQ(Common::AlignUp(size_t(100), 16u), size_t(112));641}642643TEST(Align, AlignDown)644{645// Test basic alignment down646EXPECT_EQ(Common::AlignDown(0u, 4u), 0u);647EXPECT_EQ(Common::AlignDown(1u, 4u), 0u);648EXPECT_EQ(Common::AlignDown(3u, 4u), 0u);649EXPECT_EQ(Common::AlignDown(4u, 4u), 4u);650EXPECT_EQ(Common::AlignDown(5u, 4u), 4u);651EXPECT_EQ(Common::AlignDown(7u, 4u), 4u);652EXPECT_EQ(Common::AlignDown(8u, 4u), 8u);653654// Test with larger values655EXPECT_EQ(Common::AlignDown(1000u, 64u), 960u);656EXPECT_EQ(Common::AlignDown(1024u, 64u), 1024u);657EXPECT_EQ(Common::AlignDown(1087u, 64u), 1024u);658659// Test with different types660EXPECT_EQ(Common::AlignDown(13ull, 8u), 8ull);661EXPECT_EQ(Common::AlignDown(size_t(100), 16u), size_t(96));662}663664TEST(Align, IsAlignedPow2)665{666// Test power-of-2 alignment checks667EXPECT_TRUE(Common::IsAlignedPow2(0u, 4u));668EXPECT_TRUE(Common::IsAlignedPow2(4u, 4u));669EXPECT_TRUE(Common::IsAlignedPow2(8u, 4u));670EXPECT_TRUE(Common::IsAlignedPow2(16u, 4u));671EXPECT_FALSE(Common::IsAlignedPow2(1u, 4u));672EXPECT_FALSE(Common::IsAlignedPow2(3u, 4u));673EXPECT_FALSE(Common::IsAlignedPow2(5u, 4u));674675// Test with different power-of-2 alignments676EXPECT_TRUE(Common::IsAlignedPow2(32u, 16u));677EXPECT_TRUE(Common::IsAlignedPow2(64u, 16u));678EXPECT_TRUE(Common::IsAlignedPow2(48u, 16u));679EXPECT_FALSE(Common::IsAlignedPow2(56u, 16u));680EXPECT_FALSE(Common::IsAlignedPow2(63u, 16u));681682// Test with larger values683EXPECT_TRUE(Common::IsAlignedPow2(1024u, 256u));684EXPECT_TRUE(Common::IsAlignedPow2(1280u, 256u));685EXPECT_FALSE(Common::IsAlignedPow2(1100u, 256u));686}687688TEST(Align, AlignUpPow2)689{690// Test power-of-2 alignment up691EXPECT_EQ(Common::AlignUpPow2(0u, 4u), 0u);692EXPECT_EQ(Common::AlignUpPow2(1u, 4u), 4u);693EXPECT_EQ(Common::AlignUpPow2(3u, 4u), 4u);694EXPECT_EQ(Common::AlignUpPow2(4u, 4u), 4u);695EXPECT_EQ(Common::AlignUpPow2(5u, 4u), 8u);696EXPECT_EQ(Common::AlignUpPow2(7u, 4u), 8u);697EXPECT_EQ(Common::AlignUpPow2(8u, 4u), 8u);698699// Test with larger power-of-2 alignments700EXPECT_EQ(Common::AlignUpPow2(1000u, 64u), 1024u);701EXPECT_EQ(Common::AlignUpPow2(1024u, 64u), 1024u);702EXPECT_EQ(Common::AlignUpPow2(1025u, 64u), 1088u);703704// Test with different types705EXPECT_EQ(Common::AlignUpPow2(13ull, 8u), 16ull);706EXPECT_EQ(Common::AlignUpPow2(size_t(100), 16u), size_t(112));707}708709TEST(Align, AlignDownPow2)710{711// Test power-of-2 alignment down712EXPECT_EQ(Common::AlignDownPow2(0u, 4u), 0u);713EXPECT_EQ(Common::AlignDownPow2(1u, 4u), 0u);714EXPECT_EQ(Common::AlignDownPow2(3u, 4u), 0u);715EXPECT_EQ(Common::AlignDownPow2(4u, 4u), 4u);716EXPECT_EQ(Common::AlignDownPow2(5u, 4u), 4u);717EXPECT_EQ(Common::AlignDownPow2(7u, 4u), 4u);718EXPECT_EQ(Common::AlignDownPow2(8u, 4u), 8u);719720// Test with larger power-of-2 alignments721EXPECT_EQ(Common::AlignDownPow2(1000u, 64u), 960u);722EXPECT_EQ(Common::AlignDownPow2(1024u, 64u), 1024u);723EXPECT_EQ(Common::AlignDownPow2(1087u, 64u), 1024u);724725// Test with different types726EXPECT_EQ(Common::AlignDownPow2(13ull, 8u), 8ull);727EXPECT_EQ(Common::AlignDownPow2(size_t(100), 16u), size_t(96));728}729730TEST(Align, IsPow2)731{732// Test power-of-2 detection733EXPECT_TRUE(Common::IsPow2(0u));734EXPECT_TRUE(Common::IsPow2(1u));735EXPECT_TRUE(Common::IsPow2(2u));736EXPECT_TRUE(Common::IsPow2(4u));737EXPECT_TRUE(Common::IsPow2(8u));738EXPECT_TRUE(Common::IsPow2(16u));739EXPECT_TRUE(Common::IsPow2(32u));740EXPECT_TRUE(Common::IsPow2(64u));741EXPECT_TRUE(Common::IsPow2(128u));742EXPECT_TRUE(Common::IsPow2(256u));743EXPECT_TRUE(Common::IsPow2(1024u));744745// Test non-power-of-2 values746EXPECT_FALSE(Common::IsPow2(3u));747EXPECT_FALSE(Common::IsPow2(5u));748EXPECT_FALSE(Common::IsPow2(6u));749EXPECT_FALSE(Common::IsPow2(7u));750EXPECT_FALSE(Common::IsPow2(9u));751EXPECT_FALSE(Common::IsPow2(15u));752EXPECT_FALSE(Common::IsPow2(31u));753EXPECT_FALSE(Common::IsPow2(1000u));754755// Test with different types756EXPECT_TRUE(Common::IsPow2(512ull));757EXPECT_FALSE(Common::IsPow2(513ull));758}759760TEST(Align, PreviousPow2)761{762// Test finding previous power-of-2763EXPECT_EQ(Common::PreviousPow2(1u), 1u);764EXPECT_EQ(Common::PreviousPow2(2u), 2u);765EXPECT_EQ(Common::PreviousPow2(3u), 2u);766EXPECT_EQ(Common::PreviousPow2(4u), 4u);767EXPECT_EQ(Common::PreviousPow2(5u), 4u);768EXPECT_EQ(Common::PreviousPow2(6u), 4u);769EXPECT_EQ(Common::PreviousPow2(7u), 4u);770EXPECT_EQ(Common::PreviousPow2(8u), 8u);771EXPECT_EQ(Common::PreviousPow2(15u), 8u);772EXPECT_EQ(Common::PreviousPow2(16u), 16u);773EXPECT_EQ(Common::PreviousPow2(31u), 16u);774EXPECT_EQ(Common::PreviousPow2(32u), 32u);775EXPECT_EQ(Common::PreviousPow2(1000u), 512u);776EXPECT_EQ(Common::PreviousPow2(1024u), 1024u);777778// Test with different types779EXPECT_EQ(Common::PreviousPow2(100ull), 64ull);780EXPECT_EQ(Common::PreviousPow2(static_cast<size_t>(2047)), static_cast<size_t>(1024));781EXPECT_EQ(Common::PreviousPow2(static_cast<size_t>(2048)), static_cast<size_t>(2048));782}783784TEST(Align, NextPow2)785{786// Test finding next power-of-2787EXPECT_EQ(Common::NextPow2(0u), 0u);788EXPECT_EQ(Common::NextPow2(1u), 1u);789EXPECT_EQ(Common::NextPow2(2u), 2u);790EXPECT_EQ(Common::NextPow2(3u), 4u);791EXPECT_EQ(Common::NextPow2(4u), 4u);792EXPECT_EQ(Common::NextPow2(5u), 8u);793EXPECT_EQ(Common::NextPow2(7u), 8u);794EXPECT_EQ(Common::NextPow2(8u), 8u);795EXPECT_EQ(Common::NextPow2(9u), 16u);796EXPECT_EQ(Common::NextPow2(15u), 16u);797EXPECT_EQ(Common::NextPow2(16u), 16u);798EXPECT_EQ(Common::NextPow2(17u), 32u);799EXPECT_EQ(Common::NextPow2(1000u), 1024u);800EXPECT_EQ(Common::NextPow2(1024u), 1024u);801802// Test with different types803EXPECT_EQ(Common::NextPow2(100ull), 128ull);804EXPECT_EQ(Common::NextPow2(size_t(1025)), size_t(2048));805}806807TEST(Align, AlignedMallocAndFree)808{809// Test aligned memory allocation and deallocation810void* ptr1 = Common::AlignedMalloc(128, 16);811ASSERT_NE(ptr1, nullptr);812EXPECT_TRUE(Common::IsAlignedPow2(reinterpret_cast<uintptr_t>(ptr1), 16u));813Common::AlignedFree(ptr1);814815void* ptr2 = Common::AlignedMalloc(256, 32);816ASSERT_NE(ptr2, nullptr);817EXPECT_TRUE(Common::IsAlignedPow2(reinterpret_cast<uintptr_t>(ptr2), 32u));818Common::AlignedFree(ptr2);819820void* ptr3 = Common::AlignedMalloc(1024, 64);821ASSERT_NE(ptr3, nullptr);822EXPECT_TRUE(Common::IsAlignedPow2(reinterpret_cast<uintptr_t>(ptr3), 64u));823Common::AlignedFree(ptr3);824825// Test with zero size (implementation-defined behavior)826void* ptr4 = Common::AlignedMalloc(0, 16);827Common::AlignedFree(ptr4); // Should not crash even if ptr4 is nullptr828829// Test AlignedFree with nullptr (should not crash)830Common::AlignedFree(nullptr);831}832833TEST(Align, UniqueAlignedPtr)834{835// Test make_unique_aligned for arrays836auto ptr1 = Common::make_unique_aligned<int[]>(16, 10);837ASSERT_NE(ptr1.get(), nullptr);838EXPECT_TRUE(Common::IsAlignedPow2(reinterpret_cast<uintptr_t>(ptr1.get()), 16u));839840// Test that we can write to the memory841for (int i = 0; i < 10; ++i)842{843ptr1[i] = i * 2;844}845for (int i = 0; i < 10; ++i)846{847EXPECT_EQ(ptr1[i], i * 2);848}849850auto ptr2 = Common::make_unique_aligned<u8[]>(32, 100);851ASSERT_NE(ptr2.get(), nullptr);852EXPECT_TRUE(Common::IsAlignedPow2(reinterpret_cast<uintptr_t>(ptr2.get()), 32u));853854// Test make_unique_aligned_for_overwrite855auto ptr3 = Common::make_unique_aligned_for_overwrite<u32[]>(64, 50);856ASSERT_NE(ptr3.get(), nullptr);857EXPECT_TRUE(Common::IsAlignedPow2(reinterpret_cast<uintptr_t>(ptr3.get()), 64u));858859// Test that we can write to the memory860for (u32 i = 0; i < 50; ++i)861{862ptr3[i] = i + 1000;863}864for (u32 i = 0; i < 50; ++i)865{866EXPECT_EQ(ptr3[i], i + 1000);867}868}869870