parselink-old/tests/msgpack/test_token.cpp

150 lines
5.5 KiB
C++

#include "parselink/msgpack/token.h"
#include <boost/ut.hpp>
using namespace boost::ut;
namespace {
template <typename... Bytes>
constexpr std::array<std::byte, sizeof...(Bytes)> make_bytes(Bytes&&... bytes) {
return {std::byte(std::forward<Bytes>(bytes))...};
}
template <typename First, typename... Others>
constexpr bool wrong_types(auto const& obj) {
auto err = tl::make_unexpected(msgpack::error::wrong_type);
if (obj.template get<First>() != err) return false;
if constexpr (sizeof...(Others)) {
return wrong_types<Others...>(obj);
} else {
return true;
}
}
template <typename T, typename E>
std::ostream& operator<<(std::ostream& os, tl::expected<T, E> const& exp) {
if (exp.has_value()) {
os << "Value: '" << *exp << "'";
} else {
os << "Error";
}
return os;
}
} // namespace
enum class foo : std::uint8_t { a, b, c, d, e };
suite size_and_enum = [] {
"expected use case"_test = [] {
msgpack::size_and_enum<std::uint32_t, foo> value;
expect(sizeof(value) == 8);
expect(value.rep() == uintptr_t{});
expect(value.get_size() == std::uint32_t{});
expect(value.get_enum() == foo::a);
value.set_size(std::uint32_t(-1));
expect(value.get_size() == std::uint32_t(-1));
expect(value.get_enum() == foo::a);
expect(value.rep() == 0xffffffff00000000);
value.set_enum(foo::c);
expect(value.get_size() == std::uint32_t(-1));
expect(value.get_enum() == foo::c);
expect(value.rep() == 0xffffffff00000002);
value.set_both(0xaa, foo::e);
expect(value.get_size() == 0xaa);
expect(value.get_enum() == foo::e);
expect(value.rep() == 0x000000aa00000004);
};
};
suite assignment_and_access = [] {
"token::token()"_test = [] {
msgpack::token obj;
expect(obj.type() == msgpack::format::type::invalid);
};
"token::token(bool)"_test = [] {
msgpack::token obj(true);
expect(obj.type() == msgpack::format::type::boolean);
auto retrieved = obj.get<bool>();
expect(retrieved && *retrieved);
expect(wrong_types<int, unsigned, char, std::string_view>(obj));
};
"token::token(std::int8_t)"_test = [] {
std::int8_t val = 0x32;
msgpack::token obj(val);
expect(obj.type() == msgpack::format::type::signed_int);
auto retrieved = obj.get<std::int8_t>();
expect(retrieved && *retrieved == val);
expect(wrong_types<bool, unsigned, std::string_view>(obj));
};
"token::token(std::uint8_t)"_test = [] {
std::uint8_t val = 0xaa;
msgpack::token obj(val);
expect(obj.type() == msgpack::format::type::unsigned_int);
auto retrieved = obj.get<std::uint8_t>();
expect(retrieved && *retrieved == val);
expect(wrong_types<bool, int, std::string_view>(obj));
};
"token::token(char const*)"_test = [] {
std::string extracted_val;
{
char const* val = "hello world";
msgpack::token obj(val);
expect(obj.type() == msgpack::format::type::string);
auto retrieved = obj.get<std::string_view>();
expect(bool(retrieved));
if (*retrieved != std::string_view(val)) {
expect(false);
}
expect(wrong_types<bool, int, unsigned>(obj));
auto string_retrieved = obj.get<std::string>();
expect(bool(string_retrieved));
extracted_val = std::move(*string_retrieved);
}
expect(extracted_val == "hello world");
};
"token::token(std::string)"_test = [] {
std::string val = "std::string";
msgpack::token obj(val);
expect(obj.type() == msgpack::format::type::string);
auto retrieved = obj.get<std::string_view>();
expect(bool(retrieved));
expect(*retrieved == val);
expect(wrong_types<bool, int, unsigned>(obj));
};
"token::token(std::span<byte const>)"_test = [] {
auto expected_val = make_bytes(0x32, 0xff, 0xaa, 0xce);
std::vector<std::byte> extracted_val;
{
auto val = make_bytes(0x32, 0xff, 0xaa, 0xce);
msgpack::token obj(val);
expect(obj.type() == msgpack::format::type::binary);
auto retrieved = obj.get<std::span<std::byte const>>();
expect(bool(retrieved));
expect(std::equal(retrieved->begin(), retrieved->end(), val.begin(),
val.end()));
expect(wrong_types<bool, int, unsigned, std::string_view>(obj));
auto bytes_retrieved = obj.get<std::vector<std::byte>>();
expect(bool(bytes_retrieved));
extracted_val = std::move(*bytes_retrieved);
}
expect(std::equal(expected_val.begin(), expected_val.end(),
extracted_val.begin(), extracted_val.end()));
};
};
suite int_truncation = [] {
"unsigned truncation"_test = [] {
msgpack::token obj(0xffffffffu);
expect(obj.type() == msgpack::format::type::unsigned_int);
auto retrieved = obj.get<std::uint8_t>();
auto err = tl::make_unexpected(msgpack::error::will_truncate);
expect(retrieved == err);
};
"signed truncation"_test = [] {
msgpack::token obj(-0xffff);
expect(obj.type() == msgpack::format::type::signed_int);
auto retrieved = obj.get<std::int8_t>();
auto err = tl::make_unexpected(msgpack::error::will_truncate);
expect(retrieved == err);
};
};