parselink-old/tests/msgpack/unpacker/unsigned.cpp

132 lines
4.6 KiB
C++

//-----------------------------------------------------------------------------
// ___ __ _ _
// / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __
// / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ /
// / ___/ (_| | | \__ \ __/ /__| | | | | <
// \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ .
//
//-----------------------------------------------------------------------------
// Author: Kurt Sassenrath
// Module: msgpack
//
// Default packer tests.
//
// Copyright (c) 2023 Kurt Sassenrath.
//
// License TBD.
//-----------------------------------------------------------------------------
#include "test_unpacker.h"
#include <rapidcheck.h>
using namespace boost::ut;
namespace {
constexpr auto equal(auto a, auto b) {
return std::equal(std::begin(a), std::end(a), std::begin(b), std::end(b));
}
template <typename... Bytes>
constexpr std::array<std::byte, sizeof...(Bytes)> make_bytes(Bytes&&... bytes) {
return {std::byte(std::forward<Bytes>(bytes))...};
}
template <typename T, typename U>
constexpr bool test_unpack(msgpack::unpacker unpacker) noexcept {
auto wrong_type = tl::make_unexpected(msgpack::error::wrong_type);
return std::same_as<T, U> || unpacker.unpack<U>() == wrong_type;
}
template <typename Expected, typename... OtherTypes>
constexpr bool test_types(msgpack::unpacker unpacker) noexcept {
return ((test_unpack<Expected, OtherTypes>(unpacker)) && ...);
}
template <typename Expected>
constexpr bool expect_invalid(msgpack::unpacker unpacker) noexcept {
return test_types<Expected, msgpack::nil, msgpack::invalid, bool,
std::uint8_t, std::string_view>(unpacker);
}
template <typename T>
struct get_marker;
template <>
struct get_marker<std::uint8_t> {
static constexpr std::byte marker = msgpack::format::uint8::marker;
};
template <>
struct get_marker<std::uint16_t> {
static constexpr std::byte marker = msgpack::format::uint16::marker;
};
template <>
struct get_marker<std::uint32_t> {
static constexpr std::byte marker = msgpack::format::uint32::marker;
};
template <>
struct get_marker<std::uint64_t> {
static constexpr std::byte marker = msgpack::format::uint64::marker;
};
// Utilize rapidcheck to generate random packed payloads, and unpacking the
// correct value
template <typename PackType, typename UnpackType>
auto check_unpack_integer() noexcept {
auto result = rc::check([](PackType value) {
std::vector<std::byte> payload = {get_marker<PackType>::marker};
auto bytes = host_to_be(
std::bit_cast<std::array<std::byte, sizeof(PackType)>>(value));
std::copy(bytes.begin(), bytes.end(), std::back_inserter(payload));
msgpack::unpacker unpacker(payload);
auto unpacked_value = unpacker.unpack<UnpackType>();
if (std::numeric_limits<UnpackType>::max() < value
|| std::numeric_limits<UnpackType>::min() > value) {
return unpacked_value
== tl::make_unexpected(msgpack::error::will_truncate);
} else {
return unpacked_value.has_value() && unpacked_value == value;
}
});
if (!result) {
fmt::print("Failed on {}\n",
std::source_location::current().function_name());
}
return result;
}
} // anonymous namespace
suite unpack_unsigned_types = [] {
"unpacker::unpack<std::uint8_t>"_test = [] {
expect(check_unpack_integer<std::uint8_t, std::uint8_t>());
expect(check_unpack_integer<std::uint16_t, std::uint8_t>());
expect(check_unpack_integer<std::uint32_t, std::uint8_t>());
expect(check_unpack_integer<std::uint64_t, std::uint8_t>());
};
"unpacker::unpack<std::uint16_t>"_test = [] {
expect(check_unpack_integer<std::uint8_t, std::uint16_t>());
expect(check_unpack_integer<std::uint16_t, std::uint16_t>());
expect(check_unpack_integer<std::uint32_t, std::uint16_t>());
expect(check_unpack_integer<std::uint64_t, std::uint16_t>());
};
"unpacker::unpack<std::uint32_t>"_test = [] {
expect(check_unpack_integer<std::uint8_t, std::uint32_t>());
expect(check_unpack_integer<std::uint16_t, std::uint32_t>());
expect(check_unpack_integer<std::uint32_t, std::uint32_t>());
expect(check_unpack_integer<std::uint64_t, std::uint32_t>());
};
"unpacker::unpack<std::uint64_t>"_test = [] {
expect(check_unpack_integer<std::uint8_t, std::uint64_t>());
expect(check_unpack_integer<std::uint16_t, std::uint64_t>());
expect(check_unpack_integer<std::uint32_t, std::uint64_t>());
expect(check_unpack_integer<std::uint64_t, std::uint64_t>());
};
};