mirror of
https://github.com/boostorg/redis.git
synced 2026-01-19 04:42:09 +00:00
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
This commit is contained in:
committed by
GitHub
parent
755d14a10d
commit
6005ebd04a
@@ -35,6 +35,7 @@ endmacro()
|
||||
# Unit tests
|
||||
make_test(test_low_level)
|
||||
make_test(test_request)
|
||||
make_test(test_serialization)
|
||||
make_test(test_low_level_sync_sans_io)
|
||||
make_test(test_any_adapter)
|
||||
make_test(test_log_to_file)
|
||||
|
||||
@@ -52,6 +52,7 @@ lib redis_test_common
|
||||
local tests =
|
||||
test_low_level
|
||||
test_request
|
||||
test_serialization
|
||||
test_low_level_sync_sans_io
|
||||
test_any_adapter
|
||||
test_log_to_file
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
using boost::redis::request;
|
||||
|
||||
// TODO: Serialization.
|
||||
|
||||
namespace {
|
||||
|
||||
void test_push_no_args()
|
||||
|
||||
193
test/test_serialization.cpp
Normal file
193
test/test_serialization.cpp
Normal file
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// 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();
|
||||
}
|
||||
Reference in New Issue
Block a user