mirror of
https://github.com/LizardByte/Sunshine.git
synced 2026-11-04 03:06:58 +09:00
518 lines
17 KiB
C++
518 lines
17 KiB
C++
/**
|
|
* @file tests/unit/test_utility.cpp
|
|
* @brief Tests for general utility helpers.
|
|
*/
|
|
|
|
// test includes
|
|
#include "../tests_common.h"
|
|
|
|
// standard includes
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <tuple>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
// local includes
|
|
#include <src/utility.h>
|
|
|
|
/**
|
|
* @brief Whether a type has a supported empty-state sentinel.
|
|
*/
|
|
template<class T>
|
|
concept has_false_value = requires { util::__false_v<T>::value; };
|
|
|
|
/**
|
|
* @brief Sentinel constraints select empty states without accepting unrelated values.
|
|
*/
|
|
TEST(UtilityFalseValueTests, SelectsSentinelsForOptionalPointerAndBooleanTypes) {
|
|
static_assert(std::is_same_v<decltype(util::false_v<std::optional<int>>), const std::nullopt_t>);
|
|
static_assert(std::is_same_v<decltype(util::false_v<int *>), const std::nullptr_t>);
|
|
static_assert(std::is_same_v<decltype(util::false_v<std::unique_ptr<int>>), const std::nullptr_t>);
|
|
static_assert(std::is_same_v<decltype(util::false_v<std::shared_ptr<int>>), const std::nullptr_t>);
|
|
static_assert(std::is_same_v<decltype(util::false_v<util::uniq_ptr<int>>), const std::nullptr_t>);
|
|
static_assert(std::is_same_v<decltype(util::false_v<bool>), const bool>);
|
|
static_assert(!has_false_value<int>);
|
|
|
|
EXPECT_FALSE(std::optional<int> {util::false_v<std::optional<int>>});
|
|
EXPECT_EQ(util::false_v<int *>, nullptr);
|
|
EXPECT_EQ(util::false_v<std::unique_ptr<int>>, nullptr);
|
|
EXPECT_EQ(util::false_v<std::shared_ptr<int>>, nullptr);
|
|
EXPECT_EQ(util::false_v<util::uniq_ptr<int>>, nullptr);
|
|
EXPECT_FALSE(util::false_v<bool>);
|
|
}
|
|
|
|
/**
|
|
* @brief A const resource deleter invokes its release function exactly once per call.
|
|
*/
|
|
TEST(UtilityDestroyTest, ConstDeleterInvokesTheConfiguredReleaseFunction) {
|
|
const util::Destroy<int *, void, +[](int *value) {
|
|
++*value;
|
|
}>
|
|
destroy;
|
|
int releases = 0;
|
|
destroy(&releases);
|
|
EXPECT_EQ(releases, 1);
|
|
}
|
|
|
|
/**
|
|
* @brief Simulate the opposite byte order for a byte-array fixture.
|
|
*/
|
|
template<>
|
|
struct util::endian::endianness<std::array<std::byte, 4>> {
|
|
static constexpr bool little = !util::endian::endianness<>::little; ///< Opposite native byte order.
|
|
static constexpr bool big = !little; ///< Whether the fixture simulates big endian.
|
|
};
|
|
|
|
/**
|
|
* @brief Use the simulated byte order for optional byte-array fixtures.
|
|
*/
|
|
template<>
|
|
struct util::endian::endianness<std::optional<std::array<std::byte, 4>>>: util::endian::endianness<std::array<std::byte, 4>> {};
|
|
|
|
struct HexConversionTest: testing::TestWithParam<std::tuple<std::uint32_t, bool, std::string>> {};
|
|
|
|
TEST_P(HexConversionTest, ToStringProducesExpectedHex) {
|
|
const auto &[input, rev, expected] = GetParam();
|
|
const auto hex = util::hex(input, rev);
|
|
EXPECT_EQ(hex.to_string(), expected);
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
UtilityTests,
|
|
HexConversionTest,
|
|
testing::Values(
|
|
std::make_tuple(0x00000000, false, "00000000"),
|
|
std::make_tuple(0xDEADBEEF, false, "DEADBEEF"),
|
|
std::make_tuple(0x12345678, false, "12345678"),
|
|
std::make_tuple(0x000000FF, false, "000000FF"),
|
|
std::make_tuple(0xDEADBEEF, true, "EFBEADDE"),
|
|
std::make_tuple(0x12345678, true, "78563412")
|
|
)
|
|
);
|
|
|
|
struct HexUint8Test: testing::TestWithParam<std::tuple<std::uint8_t, bool, std::string>> {};
|
|
|
|
TEST_P(HexUint8Test, SingleByteHex) {
|
|
const auto &[input, rev, expected] = GetParam();
|
|
const auto hex = util::hex(input, rev);
|
|
EXPECT_EQ(hex.to_string(), expected);
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
UtilityTests,
|
|
HexUint8Test,
|
|
testing::Values(
|
|
std::make_tuple(std::uint8_t {0x00}, false, "00"),
|
|
std::make_tuple(std::uint8_t {0xFF}, false, "FF"),
|
|
std::make_tuple(std::uint8_t {0xAB}, false, "AB"),
|
|
std::make_tuple(std::uint8_t {0x0F}, false, "0F")
|
|
)
|
|
);
|
|
|
|
TEST(UtilityHexVecTests, PreservesByteOrderWhenRevIsTrue) {
|
|
const std::vector<std::uint8_t> data {0xDE, 0xAD, 0xBE, 0xEF};
|
|
const std::string result = util::hex_vec(data, true);
|
|
EXPECT_EQ(result, "DEADBEEF");
|
|
}
|
|
|
|
TEST(UtilityHexVecTests, ReversesByteOrderWhenRevIsFalse) {
|
|
const std::vector<std::uint8_t> data {0xDE, 0xAD, 0xBE, 0xEF};
|
|
const std::string result = util::hex_vec(data, false);
|
|
EXPECT_EQ(result, "EFBEADDE");
|
|
}
|
|
|
|
TEST(UtilityHexVecTests, EmptyVector) {
|
|
const std::vector<std::uint8_t> data;
|
|
EXPECT_TRUE(util::hex_vec(data, true).empty());
|
|
EXPECT_TRUE(util::hex_vec(data, false).empty());
|
|
}
|
|
|
|
TEST(UtilityHexVecTests, SingleByte) {
|
|
const std::vector<std::uint8_t> data {0x42};
|
|
const std::string result = util::hex_vec(data, true);
|
|
EXPECT_EQ(result, "42");
|
|
}
|
|
|
|
TEST(UtilityFromHexTests, ParseHexToUint32) {
|
|
const auto result = util::from_hex<std::uint32_t>("DEADBEEF", true);
|
|
EXPECT_EQ(result, util::endian::big(std::uint32_t {0xDEADBEEF}));
|
|
}
|
|
|
|
TEST(UtilityFromHexTests, ParseHexToUint32NonReversed) {
|
|
const auto result = util::from_hex<std::uint32_t>("DEADBEEF", false);
|
|
EXPECT_EQ(result, util::endian::little(std::uint32_t {0xDEADBEEF}));
|
|
}
|
|
|
|
TEST(UtilityFromHexTests, ParseHexLowercase) {
|
|
const auto result = util::from_hex<std::uint32_t>("deadbeef", true);
|
|
EXPECT_EQ(result, util::endian::big(std::uint32_t {0xDEADBEEF}));
|
|
}
|
|
|
|
TEST(UtilityFromHexTests, ParseHexToUint16) {
|
|
const auto result = util::from_hex<std::uint16_t>("ABCD", true);
|
|
EXPECT_EQ(result, util::endian::big(std::uint16_t {0xABCD}));
|
|
}
|
|
|
|
TEST(UtilityFromHexTests, ParseHexWithSeparators) {
|
|
// from_hex skips non-hex characters
|
|
const auto result = util::from_hex<std::uint32_t>("DE:AD:BE:EF", true);
|
|
EXPECT_EQ(result, util::endian::big(std::uint32_t {0xDEADBEEF}));
|
|
}
|
|
|
|
TEST(UtilityFromHexVecTests, ParseHexStringToBytes) {
|
|
const std::string result = util::from_hex_vec("DEADBEEF", true);
|
|
ASSERT_EQ(result.size(), 4U);
|
|
EXPECT_EQ(static_cast<std::uint8_t>(result[0]), 0xDE);
|
|
EXPECT_EQ(static_cast<std::uint8_t>(result[1]), 0xAD);
|
|
EXPECT_EQ(static_cast<std::uint8_t>(result[2]), 0xBE);
|
|
EXPECT_EQ(static_cast<std::uint8_t>(result[3]), 0xEF);
|
|
}
|
|
|
|
TEST(UtilityFromHexVecTests, ParseHexStringNonReversed) {
|
|
const std::string result = util::from_hex_vec("DEADBEEF", false);
|
|
ASSERT_EQ(result.size(), 4U);
|
|
EXPECT_EQ(static_cast<std::uint8_t>(result[0]), 0xEF);
|
|
EXPECT_EQ(static_cast<std::uint8_t>(result[1]), 0xBE);
|
|
EXPECT_EQ(static_cast<std::uint8_t>(result[2]), 0xAD);
|
|
EXPECT_EQ(static_cast<std::uint8_t>(result[3]), 0xDE);
|
|
}
|
|
|
|
struct FromViewTest: testing::TestWithParam<std::tuple<std::string_view, std::int64_t>> {};
|
|
|
|
TEST_P(FromViewTest, ParsesCorrectly) {
|
|
const auto &[input, expected] = GetParam();
|
|
EXPECT_EQ(util::from_view(input), expected);
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
UtilityTests,
|
|
FromViewTest,
|
|
testing::Values(
|
|
std::make_tuple("0", std::int64_t {0}),
|
|
std::make_tuple("1", std::int64_t {1}),
|
|
std::make_tuple("42", std::int64_t {42}),
|
|
std::make_tuple("12345", std::int64_t {12345}),
|
|
std::make_tuple("-1", std::int64_t {-1}),
|
|
std::make_tuple("-999", std::int64_t {-999}),
|
|
std::make_tuple("2147483647", std::int64_t {2147483647}),
|
|
std::make_tuple("-2147483648", std::int64_t {-2147483648LL})
|
|
)
|
|
);
|
|
|
|
TEST(UtilityFromViewTests, EmptyStringReturnsZero) {
|
|
EXPECT_EQ(util::from_view(""), 0);
|
|
}
|
|
|
|
TEST(UtilityEitherTests, HasLeftWhenConstructedWithLeft) {
|
|
util::Either<int, std::string> either {std::in_place_type<int>, 42};
|
|
EXPECT_TRUE(either.has_left());
|
|
EXPECT_FALSE(either.has_right());
|
|
EXPECT_EQ(either.left(), 42);
|
|
}
|
|
|
|
TEST(UtilityEitherTests, HasRightWhenConstructedWithRight) {
|
|
util::Either<int, std::string> either {std::in_place_type<std::string>, "hello"};
|
|
EXPECT_FALSE(either.has_left());
|
|
EXPECT_TRUE(either.has_right());
|
|
EXPECT_EQ(either.right(), "hello");
|
|
}
|
|
|
|
TEST(UtilityEitherTests, DefaultConstructedHasNeither) {
|
|
util::Either<int, std::string> either;
|
|
EXPECT_FALSE(either.has_left());
|
|
EXPECT_FALSE(either.has_right());
|
|
}
|
|
|
|
TEST(UtilityFailGuardTests, ExecutesOnDestruction) {
|
|
bool executed = false;
|
|
{
|
|
auto guard = util::fail_guard([&executed]() {
|
|
executed = true;
|
|
});
|
|
}
|
|
EXPECT_TRUE(executed);
|
|
}
|
|
|
|
TEST(UtilityFailGuardTests, DoesNotExecuteWhenDisabled) {
|
|
bool executed = false;
|
|
{
|
|
auto guard = util::fail_guard([&executed]() {
|
|
executed = true;
|
|
});
|
|
guard.disable();
|
|
}
|
|
EXPECT_FALSE(executed);
|
|
}
|
|
|
|
TEST(UtilityFailGuardTests, MoveDoesNotDoubleExecute) {
|
|
int count = 0;
|
|
{
|
|
auto guard1 = util::fail_guard([&count]() {
|
|
count++;
|
|
});
|
|
auto guard2 = std::move(guard1);
|
|
}
|
|
EXPECT_EQ(count, 1);
|
|
}
|
|
|
|
TEST(UtilityBufferTests, ConstructWithSize) {
|
|
util::buffer_t<int> buf(10);
|
|
EXPECT_EQ(buf.size(), 10U);
|
|
}
|
|
|
|
TEST(UtilityBufferTests, ConstructWithSizeAndValue) {
|
|
util::buffer_t buf(5, 42);
|
|
for (const auto value : buf) {
|
|
EXPECT_EQ(value, 42);
|
|
}
|
|
}
|
|
|
|
TEST(UtilityBufferTests, DefaultConstructIsEmpty) {
|
|
util::buffer_t<int> buf;
|
|
EXPECT_EQ(buf.size(), 0U);
|
|
}
|
|
|
|
TEST(UtilityBufferTests, IndexAccess) {
|
|
util::buffer_t<int> buf(3);
|
|
buf[0] = 10;
|
|
buf[1] = 20;
|
|
buf[2] = 30;
|
|
EXPECT_EQ(buf[0], 10);
|
|
EXPECT_EQ(buf[1], 20);
|
|
EXPECT_EQ(buf[2], 30);
|
|
}
|
|
|
|
TEST(UtilityBufferTests, BeginEndIterators) {
|
|
util::buffer_t buf(3, 7);
|
|
int sum = 0;
|
|
for (const auto value : buf) {
|
|
sum += value;
|
|
}
|
|
EXPECT_EQ(sum, 21);
|
|
}
|
|
|
|
TEST(UtilityBufferTests, MoveConstruction) {
|
|
util::buffer_t buf1(3, 99);
|
|
util::buffer_t<int> buf2(std::move(buf1));
|
|
EXPECT_EQ(buf2.size(), 3U);
|
|
EXPECT_EQ(buf2[0], 99);
|
|
}
|
|
|
|
TEST(UtilityBufferTests, CopyConstruction) {
|
|
util::buffer_t buf1(3, 55);
|
|
buf1[1] = 66;
|
|
buf1[2] = 77;
|
|
util::buffer_t<int> buf2(buf1);
|
|
EXPECT_EQ(buf2.size(), 3U);
|
|
EXPECT_EQ(buf2[0], 55);
|
|
EXPECT_EQ(buf2[1], 66);
|
|
EXPECT_EQ(buf2[2], 77);
|
|
EXPECT_EQ(buf1.size(), 3U);
|
|
EXPECT_EQ(buf1[0], 55);
|
|
}
|
|
|
|
TEST(UtilityBufferTests, CopiesAnEmptyLogicalRange) {
|
|
util::buffer_t buf(3, 42);
|
|
buf.fake_resize(0);
|
|
const util::buffer_t<int> copy(buf);
|
|
EXPECT_EQ(copy.size(), 0U);
|
|
EXPECT_EQ(copy.begin(), copy.end());
|
|
EXPECT_EQ(buf[0], 42);
|
|
}
|
|
|
|
TEST(UtilityBufferTests, SizeConstructionValueInitializesEveryElement) {
|
|
const util::buffer_t<int> buf(4);
|
|
EXPECT_EQ(buf.end() - buf.begin(), 4);
|
|
EXPECT_TRUE(std::ranges::all_of(buf, [](int value) {
|
|
return value == 0;
|
|
}));
|
|
}
|
|
|
|
TEST(UtilityBufferTests, LogicalResizeRetainsAllocationAndHiddenElements) {
|
|
util::buffer_t buf(4, 7);
|
|
auto *allocation = buf.begin();
|
|
buf[3] = 99;
|
|
buf.fake_resize(2);
|
|
EXPECT_EQ(buf.size(), 2U);
|
|
EXPECT_EQ(buf.begin(), allocation);
|
|
EXPECT_EQ(buf.end(), allocation + 2);
|
|
|
|
const util::buffer_t<int> copy(buf);
|
|
EXPECT_EQ(copy.size(), 2U);
|
|
EXPECT_NE(copy.begin(), allocation);
|
|
EXPECT_EQ(copy[0], 7);
|
|
EXPECT_EQ(copy[1], 7);
|
|
buf[0] = 10;
|
|
EXPECT_EQ(copy[0], 7);
|
|
|
|
buf.fake_resize(0);
|
|
EXPECT_EQ(buf.begin(), buf.end());
|
|
buf.fake_resize(4);
|
|
EXPECT_EQ(buf.begin(), allocation);
|
|
EXPECT_EQ(buf[3], 99);
|
|
}
|
|
|
|
TEST(UtilityBufferTests, MoveConstructionTransfersAllocationAndEmptiesSource) {
|
|
util::buffer_t source(4, 9);
|
|
source.fake_resize(2);
|
|
auto *allocation = source.begin();
|
|
const util::buffer_t<int> destination(std::move(source));
|
|
EXPECT_EQ(destination.size(), 2U);
|
|
EXPECT_EQ(destination.begin(), allocation);
|
|
EXPECT_EQ(destination[1], 9);
|
|
EXPECT_EQ(source.size(), 0U); // NOSONAR(cpp:S5272): buffer_t specifies a zero logical count after move construction.
|
|
EXPECT_EQ(source.begin(), source.end());
|
|
}
|
|
|
|
TEST(UtilityBufferTests, MoveAssignmentExchangesBothAllocationsAndLogicalSizes) {
|
|
util::buffer_t source(4, 9);
|
|
source.fake_resize(2);
|
|
util::buffer_t destination(3, 7);
|
|
auto *source_allocation = source.begin();
|
|
auto *destination_allocation = destination.begin();
|
|
|
|
EXPECT_EQ(&(destination = std::move(source)), &destination);
|
|
EXPECT_EQ(destination.size(), 2U);
|
|
EXPECT_EQ(destination.begin(), source_allocation);
|
|
EXPECT_EQ(destination[1], 9);
|
|
EXPECT_EQ(source.size(), 3U); // NOSONAR(cpp:S5272): buffer_t move assignment exchanges both allocations and logical counts.
|
|
EXPECT_EQ(source.begin(), destination_allocation);
|
|
EXPECT_EQ(source[2], 7);
|
|
}
|
|
|
|
TEST(UtilityHexTests, IteratorsAndViewsExposeExactlyTheFormattedBytes) {
|
|
auto hex = util::hex(std::uint16_t {0xABCD});
|
|
EXPECT_EQ(hex.end() - hex.begin(), 4);
|
|
EXPECT_EQ(std::string(hex.begin(), hex.end()), "ABCD");
|
|
*hex.begin() = '0';
|
|
const auto &constant_hex = hex;
|
|
EXPECT_EQ(constant_hex.end() - constant_hex.begin(), 4);
|
|
EXPECT_EQ(constant_hex.cbegin(), constant_hex.begin());
|
|
EXPECT_EQ(constant_hex.cend(), constant_hex.end());
|
|
EXPECT_EQ(constant_hex.to_string_view(), "0BCD");
|
|
EXPECT_EQ(constant_hex.to_string(), "0BCD");
|
|
}
|
|
|
|
TEST(UtilityFromHexTests, ShortInputPadsUnusedBytesWithZeros) {
|
|
EXPECT_EQ(util::from_hex<std::uint64_t>("ABCD"), util::endian::little(std::uint64_t {0xABCD}));
|
|
EXPECT_EQ(util::from_hex<std::uint64_t>("ABCD", true), util::endian::big(std::uint64_t {0xABCD}));
|
|
}
|
|
|
|
TEST(UtilityFromHexTests, LongInputKeepsTheLowOrderBytes) {
|
|
EXPECT_EQ(util::from_hex<std::uint32_t>("123456789A"), util::endian::little(std::uint32_t {0x3456789A}));
|
|
EXPECT_EQ(util::from_hex<std::uint32_t>("123456789A", true), util::endian::big(std::uint32_t {0x3456789A}));
|
|
}
|
|
|
|
TEST(UtilityFromHexTests, DecodesIntoAByteArrayWithoutPointerTypePunning) {
|
|
const auto bytes = util::from_hex<std::array<std::uint8_t, 4>>("12:34:56:78", true);
|
|
EXPECT_EQ(bytes, (std::array<std::uint8_t, 4> {0x12, 0x34, 0x56, 0x78}));
|
|
}
|
|
|
|
TEST(UtilityFromHexTests, DecodesMixedCaseNibblesAndSkipsSeparators) {
|
|
const auto bytes = util::from_hex<std::array<std::byte, 6>>("0a:B1-cD.2e 3F 49", true);
|
|
const std::array expected {std::byte {0x0A}, std::byte {0xB1}, std::byte {0xCD}, std::byte {0x2E}, std::byte {0x3F}, std::byte {0x49}};
|
|
EXPECT_EQ(bytes, expected);
|
|
EXPECT_EQ(util::from_hex<std::uint32_t>(""), 0U);
|
|
}
|
|
|
|
TEST(UtilityFromHexVecTests, PreservesBinaryBytesWithMixedCaseAndSeparators) {
|
|
const std::string expected {0, static_cast<char>(0x80), static_cast<char>(0xFF), static_cast<char>(0xAB), 0x19};
|
|
EXPECT_EQ(util::from_hex_vec("00:80-fF aB.19", true), expected);
|
|
EXPECT_EQ(util::from_hex_vec("00:80-fF aB.19"), (std::string {expected.rbegin(), expected.rend()}));
|
|
EXPECT_TRUE(util::from_hex_vec("").empty());
|
|
}
|
|
|
|
TEST(UtilityHashTests, MatchesStringViewHashOfAllObjectBytes) {
|
|
const std::array<std::uint8_t, 6> value {0x00, 0x80, 0xFF, 0x12, 0x00, 0xAB};
|
|
const std::string expected_bytes {0, static_cast<char>(0x80), static_cast<char>(0xFF), 0x12, 0, static_cast<char>(0xAB)};
|
|
EXPECT_EQ(util::hash<decltype(value)> {}(value), std::hash<std::string_view> {}(expected_bytes));
|
|
}
|
|
|
|
TEST(UtilityAppendStructTests, AppendsDataCorrectly) {
|
|
struct test_struct_t {
|
|
std::uint8_t a;
|
|
std::uint8_t b;
|
|
std::uint8_t c;
|
|
};
|
|
|
|
const test_struct_t s {0xAA, 0xBB, 0xCC};
|
|
std::vector<std::uint8_t> buf {0x11};
|
|
util::append_struct(buf, s);
|
|
|
|
const std::vector<std::uint8_t> expected {0x11, 0xAA, 0xBB, 0xCC};
|
|
EXPECT_EQ(buf, expected);
|
|
}
|
|
|
|
TEST(UtilityEndianTests, BigEndianConversion) {
|
|
constexpr std::uint32_t val = 0x01020304;
|
|
const auto big = util::endian::big(val);
|
|
|
|
if constexpr (util::endian::endianness<>::little) {
|
|
EXPECT_EQ(big, 0x04030201);
|
|
} else {
|
|
EXPECT_EQ(big, val);
|
|
}
|
|
}
|
|
|
|
TEST(UtilityEndianTests, LittleEndianConversion) {
|
|
constexpr std::uint32_t val = 0x01020304;
|
|
const auto little_val = util::endian::little(val);
|
|
|
|
if constexpr (util::endian::endianness<>::little) {
|
|
EXPECT_EQ(little_val, val);
|
|
} else {
|
|
EXPECT_EQ(little_val, 0x04030201);
|
|
}
|
|
}
|
|
|
|
TEST(UtilityEndianTests, OptionalValuesPreserveEmptyStateAndConvertContainedBytes) {
|
|
const std::optional<std::uint32_t> value {0x01020304};
|
|
EXPECT_EQ(util::endian::big(value), std::optional {util::endian::big(*value)});
|
|
EXPECT_EQ(util::endian::little(value), std::optional {util::endian::little(*value)});
|
|
EXPECT_FALSE(util::endian::big(std::optional<std::uint32_t> {}));
|
|
EXPECT_FALSE(util::endian::little(std::optional<std::uint32_t> {}));
|
|
}
|
|
|
|
TEST(UtilityEndianTests, ConvertsValuesAndOptionalsOnTheOppositeByteOrder) {
|
|
const std::array value {std::byte {0x12}, std::byte {0x34}, std::byte {0x56}, std::byte {0x78}};
|
|
const std::array reversed {std::byte {0x78}, std::byte {0x56}, std::byte {0x34}, std::byte {0x12}};
|
|
const std::optional optional_value {value};
|
|
if constexpr (util::endian::endianness<>::little) {
|
|
EXPECT_EQ(util::endian::little(value), reversed);
|
|
EXPECT_EQ(util::endian::big(value), value);
|
|
EXPECT_EQ(util::endian::little(optional_value), std::optional {reversed});
|
|
EXPECT_EQ(util::endian::big(optional_value), optional_value);
|
|
} else {
|
|
EXPECT_EQ(util::endian::big(value), reversed);
|
|
EXPECT_EQ(util::endian::little(value), value);
|
|
EXPECT_EQ(util::endian::big(optional_value), std::optional {reversed});
|
|
EXPECT_EQ(util::endian::little(optional_value), optional_value);
|
|
}
|
|
}
|
|
|
|
TEST(UtilityLogHexTests, FormatsWithPrefix) {
|
|
constexpr std::uint8_t val = 0xAB;
|
|
const std::string result = util::log_hex(val);
|
|
EXPECT_EQ(result, "0xAB");
|
|
}
|
|
|
|
TEST(UtilityLogHexTests, FormatsZero) {
|
|
constexpr std::uint8_t val = 0x00;
|
|
const std::string result = util::log_hex(val);
|
|
EXPECT_EQ(result, "0x00");
|
|
}
|
|
|
|
TEST(UtilityLogHexTests, Formats16Bit) {
|
|
constexpr std::uint16_t val = 0x1234;
|
|
const std::string result = util::log_hex(val);
|
|
EXPECT_EQ(result, "0x1234");
|
|
}
|