You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
libshit/test/bitfield.cpp

111 lines
3.0 KiB
C++

#include "libshit/bitfield.hpp"
#include "libshit/doctest.hpp"
#include <cstdint>
namespace Libshit
{
TEST_SUITE_BEGIN("Libshit::Bitfield");
TEST_CASE("Empty BF")
{
Bitfield<> BF;
(void) BF;
}
namespace
{
enum class EnumA { A, B, C, D, ENUM_MAX = D };
enum EnumB { X, Y, Z };
using BF = Bitfield<
BitBool<struct Bool1>,
BitOptBool<struct OptBool>,
BitUInt<struct UInt, 2>,
BitEnum<struct Enum1, EnumA>,
BitEnum<struct Enum2, EnumB, EnumB::Z>,
BitOptEnum<struct Enum3, EnumA>,
BitBool<struct Bool2>>;
static_assert(sizeof(BF) == sizeof(std::uint16_t));
}
TEST_CASE("Simple test")
{
BF bf;
auto check = [&](bool b1, std::optional<bool> ob, unsigned u, EnumA a,
EnumB b, std::optional<EnumA> o, bool b2, unsigned raw)
{
CAPTURE(bf);
CHECK(bf.Get<Bool1>() == b1);
CHECK(bf.Get<OptBool>() == ob);
CHECK(bf.Get<UInt>() == u);
CHECK(bf.Get<Enum1>() == a);
CHECK(bf.Get<Enum2>() == b);
CHECK(bf.Get<Enum3>() == o);
CHECK(bf.Get<Bool2>() == b2);
BF exp(b1, ob, u, a, b, o, b2);
CHECK(bf == exp);
CHECK(!(bf != exp));
CHECK(bf.GetRaw() == raw);
};
check(false, {}, 0, EnumA::A, EnumB::X, {}, false, 0);
bf.Set<Bool1>(true);
check(true, {}, 0, EnumA::A, EnumB::X, {}, false, 0b0'000'00'00'00'00'1);
bf.Set<OptBool>(false);
check(true, false, 0, EnumA::A, EnumB::X, {}, false, 0b0'000'00'00'00'10'1);
bf.Set<OptBool>(true);
check(true, true, 0, EnumA::A, EnumB::X, {}, false, 0b0'000'00'00'00'11'1);
bf.Set<OptBool>({});
check(true, {}, 0, EnumA::A, EnumB::X, {}, false, 0b0'000'00'00'00'00'1);
bf.Set<UInt>(3);
check(true, {}, 3, EnumA::A, EnumB::X, {}, false, 0b0'000'00'00'11'00'1);
bf.Set<Enum3>(EnumA::B);
check(true, {}, 3, EnumA::A, EnumB::X, EnumA::B, false, 0b0'010'00'00'11'00'1);
bf.Set<Bool2>(false);
check(true, {}, 3, EnumA::A, EnumB::X, EnumA::B, false, 0b0'010'00'00'11'00'1);
bf.Set<Bool2>(true);
check(true, {}, 3, EnumA::A, EnumB::X, EnumA::B, true, 0b1'010'00'00'11'00'1);
bf.Set<Enum2>(EnumB::Z);
check(true, {}, 3, EnumA::A, EnumB::Z, EnumA::B, true, 0b1'010'10'00'11'00'1);
bf.Set<Enum3>({});
check(true, {}, 3, EnumA::A, EnumB::Z, {}, true, 0b1'000'10'00'11'00'1);
bf.Set<UInt>(18); // should this be an error instead?
check(true, {}, 2, EnumA::A, EnumB::Z, {}, true, 0b1'000'10'00'10'00'1);
bf.Set<Bool1>(false);
check(false, {}, 2, EnumA::A, EnumB::Z, {}, true, 0b1'000'10'00'10'00'0);
bf = BF{true, {}, 3, EnumA::C, EnumB::X, EnumA::A, false};
check(true, {}, 3, EnumA::C, EnumB::X, EnumA::A, false, 0b0'001'00'10'11'00'1);
}
// just because I can
static constexpr BF Test0()
{
BF bf;
bf.Set<Bool1>(true);
return bf;
}
static_assert(Test0().Get<Bool1>());
static_assert(!Test0().Get<Bool2>());
TEST_CASE("BitNop")
{
Bitfield<BitBool<Bool1>, BitNop> bf(true);
CHECK(bf.Get<Bool1>() == true);
}
TEST_SUITE_END();
}