2
0
mirror of https://github.com/boostorg/redis.git synced 2026-01-19 04:42:09 +00:00
Files
redis/test/test_serialization.cpp
Anarthal (Rubén Pérez) 6005ebd04a Fixes std::tuple serialization and adds tests (#363)
* Fixes a problem that caused passing ranges containing tuples into `request::push_range` to generate invalid commands.
* Adds test_serialization
* Updates request reference docs to reflect the requirements of the types passed to push and push_range

close #360
2025-12-02 11:20:01 +01:00

194 lines
4.4 KiB
C++

//
// Copyright (c) 2025 Marcelo Zimbres Silva (mzimbres@gmail.com),
// Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/redis/request.hpp>
#include <boost/redis/resp3/serialization.hpp>
#include <boost/core/lightweight_test.hpp>
#include <cstdint>
#include <limits>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
using boost::redis::request;
namespace other {
struct my_struct {
int value;
};
void boost_redis_to_bulk(std::string& to, my_struct value)
{
boost::redis::resp3::boost_redis_to_bulk(to, value.value);
}
} // namespace other
namespace {
// --- Strings ---
void test_string_view()
{
request req;
req.push("GET", std::string_view("key"));
BOOST_TEST_EQ(req.payload(), "*2\r\n$3\r\nGET\r\n$3\r\nkey\r\n");
}
void test_string()
{
std::string s{"k1"};
const std::string s2{"k2"};
request req;
req.push("GET", s, s2, std::string("k3"));
BOOST_TEST_EQ(req.payload(), "*4\r\n$3\r\nGET\r\n$2\r\nk1\r\n$2\r\nk2\r\n$2\r\nk3\r\n");
}
void test_c_string()
{
request req;
req.push("GET", "k1", static_cast<const char*>("k2"));
BOOST_TEST_EQ(req.payload(), "*3\r\n$3\r\nGET\r\n$2\r\nk1\r\n$2\r\nk2\r\n");
}
void test_string_empty()
{
request req;
req.push("GET", std::string_view{});
BOOST_TEST_EQ(req.payload(), "*2\r\n$3\r\nGET\r\n$0\r\n\r\n");
}
// --- Integers ---
void test_signed_ints()
{
request req;
req.push("GET", static_cast<signed char>(20), static_cast<short>(-42), -1, 80l, 200ll);
BOOST_TEST_EQ(
req.payload(),
"*6\r\n$3\r\nGET\r\n$2\r\n20\r\n$3\r\n-42\r\n$2\r\n-1\r\n$2\r\n80\r\n$3\r\n200\r\n");
}
void test_unsigned_ints()
{
request req;
req.push(
"GET",
static_cast<unsigned char>(20),
static_cast<unsigned short>(42),
50u,
80ul,
200ull);
BOOST_TEST_EQ(
req.payload(),
"*6\r\n$3\r\nGET\r\n$2\r\n20\r\n$2\r\n42\r\n$2\r\n50\r\n$2\r\n80\r\n$3\r\n200\r\n");
}
// We don't overflow for big ints
void test_signed_ints_minmax()
{
using lims = std::numeric_limits<std::int64_t>;
request req;
req.push("GET", (lims::min)(), (lims::max)());
BOOST_TEST_EQ(
req.payload(),
"*3\r\n$3\r\nGET\r\n$20\r\n-9223372036854775808\r\n$19\r\n9223372036854775807\r\n");
}
void test_unsigned_ints_max()
{
request req;
req.push("GET", (std::numeric_limits<std::uint64_t>::max)());
BOOST_TEST_EQ(req.payload(), "*2\r\n$3\r\nGET\r\n$20\r\n18446744073709551615\r\n");
}
// Custom type
void test_custom()
{
request req;
req.push("GET", other::my_struct{42});
BOOST_TEST_EQ(req.payload(), "*2\r\n$3\r\nGET\r\n$2\r\n42\r\n");
}
// --- Pairs and tuples (only supported in the range versions) ---
// Nested structures are not supported (compile time error)
void test_pair()
{
std::vector<std::pair<std::string_view, int>> vec{
{"k1", 42}
};
request req;
req.push_range("GET", vec);
BOOST_TEST_EQ(req.payload(), "*3\r\n$3\r\nGET\r\n$2\r\nk1\r\n$2\r\n42\r\n");
}
void test_pair_custom()
{
std::vector<std::pair<std::string_view, other::my_struct>> vec{
{"k1", {42}}
};
request req;
req.push_range("GET", vec);
BOOST_TEST_EQ(req.payload(), "*3\r\n$3\r\nGET\r\n$2\r\nk1\r\n$2\r\n42\r\n");
}
void test_tuple()
{
std::vector<std::tuple<std::string_view, int, unsigned char>> vec{
{"k1", 42, 1}
};
request req;
req.push_range("GET", vec);
BOOST_TEST_EQ(req.payload(), "*4\r\n$3\r\nGET\r\n$2\r\nk1\r\n$2\r\n42\r\n$1\r\n1\r\n");
}
void test_tuple_custom()
{
std::vector<std::tuple<std::string_view, other::my_struct>> vec{
{"k1", {42}}
};
request req;
req.push_range("GET", vec);
BOOST_TEST_EQ(req.payload(), "*3\r\n$3\r\nGET\r\n$2\r\nk1\r\n$2\r\n42\r\n");
}
void test_tuple_empty()
{
std::vector<std::tuple<>> vec{{}};
request req;
req.push_range("GET", vec);
BOOST_TEST_EQ(req.payload(), "*1\r\n$3\r\nGET\r\n");
}
} // namespace
int main()
{
test_string_view();
test_string();
test_c_string();
test_string_empty();
test_signed_ints();
test_unsigned_ints();
test_signed_ints_minmax();
test_unsigned_ints_max();
test_custom();
test_pair();
test_pair_custom();
test_tuple();
test_tuple_custom();
test_tuple_empty();
return boost::report_errors();
}