132 lines
4.6 KiB
C++
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>());
|
|
};
|
|
};
|