#include "source/include/parselink/msgpack/object.h" #include #include #include #include using namespace boost::ut; namespace { template constexpr std::array make_bytes(Bytes &&...bytes) { return {std::byte(std::forward(bytes))...}; } template constexpr bool wrong_types(auto const& obj) { auto err = tl::make_unexpected(msgpack::object_error::wrong_type); if (obj.template get() != err) return false; if constexpr (sizeof...(Others)) { return wrong_types(obj); } else { return true; } } template std::ostream &operator<<(std::ostream &os, tl::expected const &exp) { if (exp.has_value()) { os << "Value: '" << *exp << "'"; } else { os << "Error"; } return os; } } enum class foo : std::uint8_t { a, b, c, d, e }; suite size_and_enum = [] { "expected use case"_test = [] { msgpack::size_and_enum 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 = [] { "object::object()"_test = [] { msgpack::object obj; expect(obj.type() == msgpack::object_type::invalid); }; "object::object(bool)"_test = [] { msgpack::object obj(true); expect(obj.type() == msgpack::object_type::boolean); auto retrieved = obj.get(); expect(retrieved && *retrieved); expect(wrong_types(obj)); }; "object::object(std::int8_t)"_test = [] { std::int8_t val = 0x32; msgpack::object obj(val); expect(obj.type() == msgpack::object_type::signed_int); auto retrieved = obj.get(); expect(retrieved && *retrieved == val); expect(wrong_types(obj)); }; "object::object(std::uint8_t)"_test = [] { std::uint8_t val = 0xaa; msgpack::object obj(val); expect(obj.type() == msgpack::object_type::unsigned_int); auto retrieved = obj.get(); expect(retrieved && *retrieved == val); expect(wrong_types(obj)); }; "object::object(char const*)"_test = [] { std::string extracted_val; { char const* val = "hello world"; msgpack::object obj(val); expect(obj.type() == msgpack::object_type::string); auto retrieved = obj.get(); expect(bool(retrieved)); if (*retrieved != std::string_view(val)) { expect(false); } expect(wrong_types(obj)); auto string_retrieved = obj.get(); expect(bool(string_retrieved)); extracted_val = std::move(*string_retrieved); } expect(extracted_val == "hello world"); }; "object::object(std::string)"_test = [] { std::string val = "std::string"; msgpack::object obj(val); expect(obj.type() == msgpack::object_type::string); auto retrieved = obj.get(); expect(bool(retrieved)); expect(*retrieved == val); expect(wrong_types(obj)); }; "object::object(std::span)"_test = [] { auto expected_val = make_bytes(0x32, 0xff, 0xaa, 0xce); std::vector extracted_val; { auto val = make_bytes(0x32, 0xff, 0xaa, 0xce); msgpack::object obj(val); expect(obj.type() == msgpack::object_type::bytes); auto retrieved = obj.get>(); expect(bool(retrieved)); expect(std::equal(retrieved->begin(), retrieved->end(), val.begin(), val.end())); expect(wrong_types(obj)); auto bytes_retrieved = obj.get>(); 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::object obj(0xffffffffu); expect(obj.type() == msgpack::object_type::unsigned_int); auto retrieved = obj.get(); auto err = tl::make_unexpected(msgpack::object_error::will_truncate); expect(retrieved == err); }; "signed truncation"_test = [] { msgpack::object obj(-0xffff); expect(obj.type() == msgpack::object_type::signed_int); auto retrieved = obj.get(); auto err = tl::make_unexpected(msgpack::object_error::will_truncate); expect(retrieved == err); }; };