mirror of
https://github.com/boostorg/redis.git
synced 2026-01-19 04:42:09 +00:00
Adds custom setup requests (#303)
Adds config::setup and config::use_setup, to run arbitrary Redis commands on connection establishment
Improves docs for config::{username, password, clientname, database_index}
Splits all connection establishment tests into test_conn_hello
close #302
This commit is contained in:
committed by
GitHub
parent
0cf2441ed2
commit
6a1a07f95a
@@ -41,7 +41,7 @@ make_test(test_exec_fsm)
|
||||
make_test(test_log_to_file)
|
||||
make_test(test_conn_logging)
|
||||
make_test(test_reader_fsm)
|
||||
make_test(test_hello_utils)
|
||||
make_test(test_setup_request_utils)
|
||||
|
||||
# Tests that require a real Redis server
|
||||
make_test(test_conn_quit)
|
||||
@@ -56,7 +56,7 @@ make_test(test_conn_exec_cancel)
|
||||
make_test(test_conn_exec_cancel2)
|
||||
make_test(test_conn_echo_stress)
|
||||
make_test(test_conn_move)
|
||||
make_test(test_conn_auth)
|
||||
make_test(test_conn_setup)
|
||||
make_test(test_issue_50)
|
||||
make_test(test_issue_181)
|
||||
make_test(test_conversions)
|
||||
|
||||
@@ -57,7 +57,7 @@ local tests =
|
||||
test_log_to_file
|
||||
test_conn_logging
|
||||
test_reader_fsm
|
||||
test_hello_utils
|
||||
test_setup_request_utils
|
||||
;
|
||||
|
||||
# Build and run the tests
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
//
|
||||
// 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/connection.hpp>
|
||||
#include <boost/redis/logger.hpp>
|
||||
#include <boost/redis/request.hpp>
|
||||
#include <boost/redis/response.hpp>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace asio = boost::asio;
|
||||
namespace redis = boost::redis;
|
||||
using namespace std::chrono_literals;
|
||||
using boost::system::error_code;
|
||||
|
||||
namespace {
|
||||
|
||||
// Creates a user with a known password. Harmless if the user already exists
|
||||
void setup_password()
|
||||
{
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn{ioc};
|
||||
|
||||
// Enable the user and grant them permissions on everything
|
||||
redis::request req;
|
||||
req.push("ACL", "SETUSER", "myuser", "on", ">mypass", "~*", "&*", "+@all");
|
||||
redis::generic_response resp;
|
||||
|
||||
bool run_finished = false, exec_finished = false;
|
||||
conn.async_run(make_test_config(), [&](error_code ec) {
|
||||
run_finished = true;
|
||||
BOOST_TEST_EQ(ec, asio::error::operation_aborted);
|
||||
});
|
||||
|
||||
conn.async_exec(req, resp, [&](error_code ec, std::size_t) {
|
||||
exec_finished = true;
|
||||
BOOST_TEST_EQ(ec, error_code());
|
||||
conn.cancel();
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
|
||||
BOOST_TEST(run_finished);
|
||||
BOOST_TEST(exec_finished);
|
||||
BOOST_TEST(resp.has_value());
|
||||
}
|
||||
|
||||
void test_auth_success()
|
||||
{
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn{ioc};
|
||||
|
||||
// This request should return the username we're logged in as
|
||||
redis::request req;
|
||||
req.push("ACL", "WHOAMI");
|
||||
redis::response<std::string> resp;
|
||||
|
||||
// These credentials are set up in main, before tests are run
|
||||
auto cfg = make_test_config();
|
||||
cfg.username = "myuser";
|
||||
cfg.password = "mypass";
|
||||
|
||||
bool exec_finished = false, run_finished = false;
|
||||
|
||||
conn.async_exec(req, resp, [&](error_code ec, std::size_t) {
|
||||
exec_finished = true;
|
||||
BOOST_TEST_EQ(ec, error_code());
|
||||
conn.cancel();
|
||||
});
|
||||
|
||||
conn.async_run(cfg, [&](error_code ec) {
|
||||
run_finished = true;
|
||||
BOOST_TEST_EQ(ec, asio::error::operation_aborted);
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
|
||||
BOOST_TEST(exec_finished);
|
||||
BOOST_TEST(run_finished);
|
||||
BOOST_TEST_EQ(std::get<0>(resp).value(), "myuser");
|
||||
}
|
||||
|
||||
void test_auth_failure()
|
||||
{
|
||||
// Verify that we log appropriately (see https://github.com/boostorg/redis/issues/297)
|
||||
std::ostringstream oss;
|
||||
redis::logger lgr(redis::logger::level::info, [&](redis::logger::level, std::string_view msg) {
|
||||
oss << msg << '\n';
|
||||
});
|
||||
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn{ioc, std::move(lgr)};
|
||||
|
||||
// Disable reconnection so the hello error causes the connection to exit
|
||||
auto cfg = make_test_config();
|
||||
cfg.username = "myuser";
|
||||
cfg.password = "wrongpass"; // wrong
|
||||
cfg.reconnect_wait_interval = 0s;
|
||||
|
||||
bool run_finished = false;
|
||||
|
||||
conn.async_run(cfg, [&](error_code ec) {
|
||||
run_finished = true;
|
||||
BOOST_TEST_EQ(ec, redis::error::resp3_hello);
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
|
||||
BOOST_TEST(run_finished);
|
||||
|
||||
// Check the log
|
||||
auto log = oss.str();
|
||||
if (!BOOST_TEST_NE(log.find("WRONGPASS"), std::string::npos)) {
|
||||
std::cerr << "Log was: " << log << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
setup_password();
|
||||
test_auth_success();
|
||||
test_auth_failure();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -141,49 +141,6 @@ BOOST_AUTO_TEST_CASE(cancel_request_if_not_connected)
|
||||
BOOST_TEST(finished);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(correct_database)
|
||||
{
|
||||
auto cfg = make_test_config();
|
||||
cfg.database_index = 2;
|
||||
|
||||
net::io_context ioc;
|
||||
|
||||
auto conn = std::make_shared<connection>(ioc);
|
||||
|
||||
request req;
|
||||
req.push("CLIENT", "LIST");
|
||||
|
||||
generic_response resp;
|
||||
|
||||
bool exec_finished = false, run_finished = false;
|
||||
|
||||
conn->async_exec(req, resp, [&](error_code ec, std::size_t n) {
|
||||
BOOST_TEST(ec == error_code());
|
||||
std::clog << "async_exec has completed: " << n << std::endl;
|
||||
conn->cancel();
|
||||
exec_finished = true;
|
||||
});
|
||||
|
||||
conn->async_run(cfg, {}, [&run_finished](error_code) {
|
||||
std::clog << "async_run has exited." << std::endl;
|
||||
run_finished = true;
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
BOOST_TEST_REQUIRE(exec_finished);
|
||||
BOOST_TEST_REQUIRE(run_finished);
|
||||
|
||||
BOOST_TEST_REQUIRE(!resp.value().empty());
|
||||
auto const& value = resp.value().front().value;
|
||||
auto const pos = value.find("db=");
|
||||
auto const index_str = value.substr(pos + 3, 1);
|
||||
auto const index = std::stoi(index_str);
|
||||
|
||||
// This check might fail if more than one client is connected to
|
||||
// redis when the CLIENT LIST command is run.
|
||||
BOOST_CHECK_EQUAL(cfg.database_index.value(), index);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(large_number_of_concurrent_requests_issue_170)
|
||||
{
|
||||
// See https://github.com/boostorg/redis/issues/170
|
||||
|
||||
344
test/test_conn_setup.cpp
Normal file
344
test/test_conn_setup.cpp
Normal file
@@ -0,0 +1,344 @@
|
||||
//
|
||||
// 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/connection.hpp>
|
||||
#include <boost/redis/logger.hpp>
|
||||
#include <boost/redis/request.hpp>
|
||||
#include <boost/redis/response.hpp>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace asio = boost::asio;
|
||||
namespace redis = boost::redis;
|
||||
using namespace std::chrono_literals;
|
||||
using boost::system::error_code;
|
||||
|
||||
namespace {
|
||||
|
||||
// Finds a value in the output of the CLIENT INFO command
|
||||
// format: key1=value1 key2=value2
|
||||
std::string_view find_client_info(std::string_view client_info, std::string_view key)
|
||||
{
|
||||
std::string prefix{key};
|
||||
prefix += '=';
|
||||
|
||||
auto const pos = client_info.find(prefix);
|
||||
if (pos == std::string_view::npos)
|
||||
return {};
|
||||
auto const pos_begin = pos + prefix.size();
|
||||
auto const pos_end = client_info.find(' ', pos_begin);
|
||||
return client_info.substr(pos_begin, pos_end - pos_begin);
|
||||
}
|
||||
|
||||
// Creates a user with a known password. Harmless if the user already exists
|
||||
void setup_password()
|
||||
{
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn{ioc};
|
||||
|
||||
// Enable the user and grant them permissions on everything
|
||||
redis::request req;
|
||||
req.push("ACL", "SETUSER", "myuser", "on", ">mypass", "~*", "&*", "+@all");
|
||||
redis::generic_response resp;
|
||||
|
||||
bool run_finished = false, exec_finished = false;
|
||||
conn.async_run(make_test_config(), [&](error_code ec) {
|
||||
run_finished = true;
|
||||
BOOST_TEST_EQ(ec, asio::error::operation_aborted);
|
||||
});
|
||||
|
||||
conn.async_exec(req, resp, [&](error_code ec, std::size_t) {
|
||||
exec_finished = true;
|
||||
BOOST_TEST_EQ(ec, error_code());
|
||||
conn.cancel();
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
|
||||
BOOST_TEST(run_finished);
|
||||
BOOST_TEST(exec_finished);
|
||||
BOOST_TEST(resp.has_value());
|
||||
}
|
||||
|
||||
void test_auth_success()
|
||||
{
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn{ioc};
|
||||
|
||||
// This request should return the username we're logged in as
|
||||
redis::request req;
|
||||
req.push("ACL", "WHOAMI");
|
||||
redis::response<std::string> resp;
|
||||
|
||||
// These credentials are set up in main, before tests are run
|
||||
auto cfg = make_test_config();
|
||||
cfg.username = "myuser";
|
||||
cfg.password = "mypass";
|
||||
|
||||
bool exec_finished = false, run_finished = false;
|
||||
|
||||
conn.async_exec(req, resp, [&](error_code ec, std::size_t) {
|
||||
exec_finished = true;
|
||||
BOOST_TEST_EQ(ec, error_code());
|
||||
conn.cancel();
|
||||
});
|
||||
|
||||
conn.async_run(cfg, [&](error_code ec) {
|
||||
run_finished = true;
|
||||
BOOST_TEST_EQ(ec, asio::error::operation_aborted);
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
|
||||
BOOST_TEST(exec_finished);
|
||||
BOOST_TEST(run_finished);
|
||||
BOOST_TEST_EQ(std::get<0>(resp).value(), "myuser");
|
||||
}
|
||||
|
||||
void test_auth_failure()
|
||||
{
|
||||
// Verify that we log appropriately (see https://github.com/boostorg/redis/issues/297)
|
||||
std::ostringstream oss;
|
||||
redis::logger lgr(redis::logger::level::info, [&](redis::logger::level, std::string_view msg) {
|
||||
oss << msg << '\n';
|
||||
});
|
||||
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn{ioc, std::move(lgr)};
|
||||
|
||||
// Disable reconnection so the hello error causes the connection to exit
|
||||
auto cfg = make_test_config();
|
||||
cfg.username = "myuser";
|
||||
cfg.password = "wrongpass"; // wrong
|
||||
cfg.reconnect_wait_interval = 0s;
|
||||
|
||||
bool run_finished = false;
|
||||
|
||||
conn.async_run(cfg, [&](error_code ec) {
|
||||
run_finished = true;
|
||||
BOOST_TEST_EQ(ec, redis::error::resp3_hello);
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
|
||||
BOOST_TEST(run_finished);
|
||||
|
||||
// Check the log
|
||||
auto log = oss.str();
|
||||
if (!BOOST_TEST_NE(log.find("WRONGPASS"), std::string::npos)) {
|
||||
std::cerr << "Log was: " << log << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void test_database_index()
|
||||
{
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn(ioc);
|
||||
|
||||
// Use a non-default database index
|
||||
auto cfg = make_test_config();
|
||||
cfg.database_index = 2;
|
||||
|
||||
redis::request req;
|
||||
req.push("CLIENT", "INFO");
|
||||
|
||||
redis::response<std::string> resp;
|
||||
|
||||
bool exec_finished = false, run_finished = false;
|
||||
|
||||
conn.async_exec(req, resp, [&](error_code ec, std::size_t n) {
|
||||
BOOST_TEST_EQ(ec, error_code());
|
||||
std::clog << "async_exec has completed: " << n << std::endl;
|
||||
conn.cancel();
|
||||
exec_finished = true;
|
||||
});
|
||||
|
||||
conn.async_run(cfg, {}, [&run_finished](error_code) {
|
||||
std::clog << "async_run has exited." << std::endl;
|
||||
run_finished = true;
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
BOOST_TEST(exec_finished);
|
||||
BOOST_TEST(run_finished);
|
||||
BOOST_TEST_EQ(find_client_info(std::get<0>(resp).value(), "db"), "2");
|
||||
}
|
||||
|
||||
// The user configured an empty setup request. No request should be sent
|
||||
void test_setup_empty()
|
||||
{
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn(ioc);
|
||||
|
||||
auto cfg = make_test_config();
|
||||
cfg.use_setup = true;
|
||||
cfg.setup.clear();
|
||||
|
||||
redis::request req;
|
||||
req.push("CLIENT", "INFO");
|
||||
|
||||
redis::response<std::string> resp;
|
||||
|
||||
bool exec_finished = false, run_finished = false;
|
||||
|
||||
conn.async_exec(req, resp, [&](error_code ec, std::size_t) {
|
||||
BOOST_TEST_EQ(ec, error_code());
|
||||
conn.cancel();
|
||||
exec_finished = true;
|
||||
});
|
||||
|
||||
conn.async_run(cfg, {}, [&run_finished](error_code) {
|
||||
run_finished = true;
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
BOOST_TEST(exec_finished);
|
||||
BOOST_TEST(run_finished);
|
||||
BOOST_TEST_EQ(find_client_info(std::get<0>(resp).value(), "resp"), "2"); // using RESP2
|
||||
}
|
||||
|
||||
// We can use the setup member to run commands at startup
|
||||
void test_setup_hello()
|
||||
{
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn(ioc);
|
||||
|
||||
auto cfg = make_test_config();
|
||||
cfg.use_setup = true;
|
||||
cfg.setup.clear();
|
||||
cfg.setup.push("HELLO", "3", "AUTH", "myuser", "mypass");
|
||||
cfg.setup.push("SELECT", 8);
|
||||
|
||||
redis::request req;
|
||||
req.push("CLIENT", "INFO");
|
||||
|
||||
redis::response<std::string> resp;
|
||||
|
||||
bool exec_finished = false, run_finished = false;
|
||||
|
||||
conn.async_exec(req, resp, [&](error_code ec, std::size_t) {
|
||||
BOOST_TEST_EQ(ec, error_code());
|
||||
conn.cancel();
|
||||
exec_finished = true;
|
||||
});
|
||||
|
||||
conn.async_run(cfg, {}, [&run_finished](error_code) {
|
||||
run_finished = true;
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
BOOST_TEST(exec_finished);
|
||||
BOOST_TEST(run_finished);
|
||||
BOOST_TEST_EQ(find_client_info(std::get<0>(resp).value(), "resp"), "3"); // using RESP3
|
||||
BOOST_TEST_EQ(find_client_info(std::get<0>(resp).value(), "user"), "myuser");
|
||||
BOOST_TEST_EQ(find_client_info(std::get<0>(resp).value(), "db"), "8");
|
||||
}
|
||||
|
||||
// Running a pipeline without a HELLO is okay (regression check: we set the priority flag)
|
||||
void test_setup_no_hello()
|
||||
{
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn(ioc);
|
||||
|
||||
auto cfg = make_test_config();
|
||||
cfg.use_setup = true;
|
||||
cfg.setup.clear();
|
||||
cfg.setup.push("SELECT", 8);
|
||||
|
||||
redis::request req;
|
||||
req.push("CLIENT", "INFO");
|
||||
|
||||
redis::response<std::string> resp;
|
||||
|
||||
bool exec_finished = false, run_finished = false;
|
||||
|
||||
conn.async_exec(req, resp, [&](error_code ec, std::size_t) {
|
||||
BOOST_TEST_EQ(ec, error_code());
|
||||
conn.cancel();
|
||||
exec_finished = true;
|
||||
});
|
||||
|
||||
conn.async_run(cfg, {}, [&run_finished](error_code) {
|
||||
run_finished = true;
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
BOOST_TEST(exec_finished);
|
||||
BOOST_TEST(run_finished);
|
||||
BOOST_TEST_EQ(find_client_info(std::get<0>(resp).value(), "resp"), "2"); // using RESP3
|
||||
BOOST_TEST_EQ(find_client_info(std::get<0>(resp).value(), "db"), "8");
|
||||
}
|
||||
|
||||
void test_setup_failure()
|
||||
{
|
||||
// Verify that we log appropriately (see https://github.com/boostorg/redis/issues/297)
|
||||
std::ostringstream oss;
|
||||
redis::logger lgr(redis::logger::level::info, [&](redis::logger::level, std::string_view msg) {
|
||||
oss << msg << '\n';
|
||||
});
|
||||
|
||||
// Setup
|
||||
asio::io_context ioc;
|
||||
redis::connection conn{ioc, std::move(lgr)};
|
||||
|
||||
// Disable reconnection so the hello error causes the connection to exit
|
||||
auto cfg = make_test_config();
|
||||
cfg.use_setup = true;
|
||||
cfg.setup.clear();
|
||||
cfg.setup.push("GET", "two", "args"); // GET only accepts one arg, so this will fail
|
||||
cfg.reconnect_wait_interval = 0s;
|
||||
|
||||
bool run_finished = false;
|
||||
|
||||
conn.async_run(cfg, [&](error_code ec) {
|
||||
run_finished = true;
|
||||
BOOST_TEST_EQ(ec, redis::error::resp3_hello);
|
||||
});
|
||||
|
||||
ioc.run_for(test_timeout);
|
||||
|
||||
BOOST_TEST(run_finished);
|
||||
|
||||
// Check the log
|
||||
auto log = oss.str();
|
||||
if (!BOOST_TEST_NE(log.find("wrong number of arguments"), std::string::npos)) {
|
||||
std::cerr << "Log was: " << log << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
setup_password();
|
||||
test_auth_success();
|
||||
test_auth_failure();
|
||||
test_database_index();
|
||||
test_setup_empty();
|
||||
test_setup_hello();
|
||||
test_setup_no_hello();
|
||||
test_setup_failure();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#include <boost/redis/adapter/result.hpp>
|
||||
#include <boost/redis/config.hpp>
|
||||
#include <boost/redis/detail/hello_utils.hpp>
|
||||
#include <boost/redis/detail/setup_request_utils.hpp>
|
||||
#include <boost/redis/error.hpp>
|
||||
#include <boost/redis/request.hpp>
|
||||
#include <boost/redis/resp3/type.hpp>
|
||||
@@ -20,95 +20,129 @@
|
||||
|
||||
namespace asio = boost::asio;
|
||||
namespace redis = boost::redis;
|
||||
using redis::detail::setup_hello_request;
|
||||
using redis::detail::compose_setup_request;
|
||||
using redis::detail::clear_response;
|
||||
using redis::detail::check_hello_response;
|
||||
using redis::detail::check_setup_response;
|
||||
using boost::system::error_code;
|
||||
|
||||
namespace {
|
||||
|
||||
void test_setup_hello_request()
|
||||
void test_compose_setup()
|
||||
{
|
||||
redis::config cfg;
|
||||
cfg.clientname = "";
|
||||
redis::request req;
|
||||
|
||||
setup_hello_request(cfg, req);
|
||||
compose_setup_request(cfg);
|
||||
|
||||
std::string_view const expected = "*2\r\n$5\r\nHELLO\r\n$1\r\n3\r\n";
|
||||
BOOST_TEST_EQ(req.payload(), expected);
|
||||
BOOST_TEST_EQ(cfg.setup.payload(), expected);
|
||||
BOOST_TEST(cfg.setup.has_hello_priority());
|
||||
}
|
||||
|
||||
void test_setup_hello_request_select()
|
||||
void test_compose_setup_select()
|
||||
{
|
||||
redis::config cfg;
|
||||
cfg.clientname = "";
|
||||
cfg.database_index = 10;
|
||||
redis::request req;
|
||||
|
||||
setup_hello_request(cfg, req);
|
||||
compose_setup_request(cfg);
|
||||
|
||||
std::string_view const expected =
|
||||
"*2\r\n$5\r\nHELLO\r\n$1\r\n3\r\n"
|
||||
"*2\r\n$6\r\nSELECT\r\n$2\r\n10\r\n";
|
||||
BOOST_TEST_EQ(req.payload(), expected);
|
||||
BOOST_TEST_EQ(cfg.setup.payload(), expected);
|
||||
BOOST_TEST(cfg.setup.has_hello_priority());
|
||||
}
|
||||
|
||||
void test_setup_hello_request_clientname()
|
||||
void test_compose_setup_clientname()
|
||||
{
|
||||
redis::config cfg;
|
||||
redis::request req;
|
||||
|
||||
setup_hello_request(cfg, req);
|
||||
compose_setup_request(cfg);
|
||||
|
||||
std::string_view const
|
||||
expected = "*4\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$7\r\nSETNAME\r\n$11\r\nBoost.Redis\r\n";
|
||||
BOOST_TEST_EQ(req.payload(), expected);
|
||||
BOOST_TEST_EQ(cfg.setup.payload(), expected);
|
||||
BOOST_TEST(cfg.setup.has_hello_priority());
|
||||
}
|
||||
|
||||
void test_setup_hello_request_auth()
|
||||
void test_compose_setup_auth()
|
||||
{
|
||||
redis::config cfg;
|
||||
cfg.clientname = "";
|
||||
cfg.username = "foo";
|
||||
cfg.password = "bar";
|
||||
redis::request req;
|
||||
|
||||
setup_hello_request(cfg, req);
|
||||
compose_setup_request(cfg);
|
||||
|
||||
std::string_view const
|
||||
expected = "*5\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$4\r\nAUTH\r\n$3\r\nfoo\r\n$3\r\nbar\r\n";
|
||||
BOOST_TEST_EQ(req.payload(), expected);
|
||||
BOOST_TEST_EQ(cfg.setup.payload(), expected);
|
||||
BOOST_TEST(cfg.setup.has_hello_priority());
|
||||
}
|
||||
|
||||
void test_setup_hello_request_auth_empty_password()
|
||||
void test_compose_setup_auth_empty_password()
|
||||
{
|
||||
redis::config cfg;
|
||||
cfg.clientname = "";
|
||||
cfg.username = "foo";
|
||||
redis::request req;
|
||||
|
||||
setup_hello_request(cfg, req);
|
||||
compose_setup_request(cfg);
|
||||
|
||||
std::string_view const
|
||||
expected = "*5\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$4\r\nAUTH\r\n$3\r\nfoo\r\n$0\r\n\r\n";
|
||||
BOOST_TEST_EQ(req.payload(), expected);
|
||||
BOOST_TEST_EQ(cfg.setup.payload(), expected);
|
||||
BOOST_TEST(cfg.setup.has_hello_priority());
|
||||
}
|
||||
|
||||
void test_setup_hello_request_auth_setname()
|
||||
void test_compose_setup_auth_setname()
|
||||
{
|
||||
redis::config cfg;
|
||||
cfg.clientname = "mytest";
|
||||
cfg.username = "foo";
|
||||
cfg.password = "bar";
|
||||
redis::request req;
|
||||
|
||||
setup_hello_request(cfg, req);
|
||||
compose_setup_request(cfg);
|
||||
|
||||
std::string_view const expected =
|
||||
"*7\r\n$5\r\nHELLO\r\n$1\r\n3\r\n$4\r\nAUTH\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$7\r\nSETNAME\r\n$"
|
||||
"6\r\nmytest\r\n";
|
||||
BOOST_TEST_EQ(req.payload(), expected);
|
||||
BOOST_TEST_EQ(cfg.setup.payload(), expected);
|
||||
BOOST_TEST(cfg.setup.has_hello_priority());
|
||||
}
|
||||
|
||||
void test_compose_setup_use_setup()
|
||||
{
|
||||
redis::config cfg;
|
||||
cfg.clientname = "mytest";
|
||||
cfg.username = "foo";
|
||||
cfg.password = "bar";
|
||||
cfg.database_index = 4;
|
||||
cfg.use_setup = true;
|
||||
cfg.setup.push("SELECT", 8);
|
||||
|
||||
compose_setup_request(cfg);
|
||||
|
||||
std::string_view const expected =
|
||||
"*2\r\n$5\r\nHELLO\r\n$1\r\n3\r\n"
|
||||
"*2\r\n$6\r\nSELECT\r\n$1\r\n8\r\n";
|
||||
BOOST_TEST_EQ(cfg.setup.payload(), expected);
|
||||
BOOST_TEST(cfg.setup.has_hello_priority());
|
||||
}
|
||||
|
||||
// Regression check: we set the priority flag
|
||||
void test_compose_setup_use_setup_no_hello()
|
||||
{
|
||||
redis::config cfg;
|
||||
cfg.use_setup = true;
|
||||
cfg.setup.clear();
|
||||
cfg.setup.push("SELECT", 8);
|
||||
|
||||
compose_setup_request(cfg);
|
||||
|
||||
std::string_view const expected = "*2\r\n$6\r\nSELECT\r\n$1\r\n8\r\n";
|
||||
BOOST_TEST_EQ(cfg.setup.payload(), expected);
|
||||
BOOST_TEST(cfg.setup.has_hello_priority());
|
||||
}
|
||||
|
||||
// clear response
|
||||
@@ -141,28 +175,28 @@ void test_clear_response_error()
|
||||
}
|
||||
|
||||
// check response
|
||||
void test_check_hello_response_success()
|
||||
void test_check_response_success()
|
||||
{
|
||||
redis::generic_response resp;
|
||||
resp->push_back({});
|
||||
auto ec = check_hello_response(error_code(), resp);
|
||||
auto ec = check_setup_response(error_code(), resp);
|
||||
BOOST_TEST_EQ(ec, error_code());
|
||||
}
|
||||
|
||||
void test_check_hello_response_io_error()
|
||||
void test_check_response_io_error()
|
||||
{
|
||||
redis::generic_response resp;
|
||||
auto ec = check_hello_response(asio::error::already_open, resp);
|
||||
auto ec = check_setup_response(asio::error::already_open, resp);
|
||||
BOOST_TEST_EQ(ec, asio::error::already_open);
|
||||
}
|
||||
|
||||
void test_check_hello_response_server_error()
|
||||
void test_check_response_server_error()
|
||||
{
|
||||
redis::generic_response resp{
|
||||
boost::system::in_place_error,
|
||||
redis::adapter::error{redis::resp3::type::simple_error, "wrong password"}
|
||||
};
|
||||
auto ec = check_hello_response(error_code(), resp);
|
||||
auto ec = check_setup_response(error_code(), resp);
|
||||
BOOST_TEST_EQ(ec, redis::error::resp3_hello);
|
||||
}
|
||||
|
||||
@@ -170,20 +204,22 @@ void test_check_hello_response_server_error()
|
||||
|
||||
int main()
|
||||
{
|
||||
test_setup_hello_request();
|
||||
test_setup_hello_request_select();
|
||||
test_setup_hello_request_clientname();
|
||||
test_setup_hello_request_auth();
|
||||
test_setup_hello_request_auth_empty_password();
|
||||
test_setup_hello_request_auth_setname();
|
||||
test_compose_setup();
|
||||
test_compose_setup_select();
|
||||
test_compose_setup_clientname();
|
||||
test_compose_setup_auth();
|
||||
test_compose_setup_auth_empty_password();
|
||||
test_compose_setup_auth_setname();
|
||||
test_compose_setup_use_setup();
|
||||
test_compose_setup_use_setup_no_hello();
|
||||
|
||||
test_clear_response_empty();
|
||||
test_clear_response_nonempty();
|
||||
test_clear_response_error();
|
||||
|
||||
test_check_hello_response_success();
|
||||
test_check_hello_response_io_error();
|
||||
test_check_hello_response_server_error();
|
||||
test_check_response_success();
|
||||
test_check_response_io_error();
|
||||
test_check_response_server_error();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
Reference in New Issue
Block a user