2
0
mirror of https://github.com/boostorg/redis.git synced 2026-01-19 04:42:09 +00:00

Adds support for PUNSUBSCRIBE (#339)

Adds a test covering UNSUBSCRIBE and PUNSUBSCRIBE

close #306
This commit is contained in:
Anarthal (Rubén Pérez)
2025-10-25 00:41:49 +02:00
committed by GitHub
parent 0460b38e14
commit 6791e759f9
5 changed files with 94 additions and 15 deletions

View File

@@ -68,3 +68,19 @@ void run_coroutine_test(net::awaitable<void> op, std::chrono::steady_clock::dura
throw std::runtime_error("Coroutine test did not finish");
}
#endif // BOOST_ASIO_HAS_CO_AWAIT
// Finds a value in the output of the CLIENT INFO command
// format: key1=value1 key2=value2
// TODO: duplicated
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);
}

View File

@@ -11,6 +11,7 @@
#include <chrono>
#include <memory>
#include <string_view>
// The timeout for tests involving communication to a real server.
// Some tests use a longer timeout by multiplying this value by some
@@ -35,3 +36,7 @@ void run(
boost::redis::config cfg = make_test_config(),
boost::system::error_code ec = boost::asio::error::operation_aborted,
boost::redis::operation op = boost::redis::operation::receive);
// 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);

View File

@@ -6,10 +6,14 @@
#include <boost/redis/connection.hpp>
#include <boost/redis/logger.hpp>
#include <boost/redis/request.hpp>
#include <boost/redis/response.hpp>
#include <boost/asio/experimental/channel_error.hpp>
#include <boost/system/errc.hpp>
#include <string>
#define BOOST_TEST_MODULE conn_push
#include <boost/test/included/unit_test.hpp>
@@ -327,4 +331,71 @@ BOOST_AUTO_TEST_CASE(many_subscribers)
BOOST_TEST(finished);
}
BOOST_AUTO_TEST_CASE(test_unsubscribe)
{
net::io_context ioc;
connection conn{ioc};
// Subscribe to 3 channels and 2 patterns. Use CLIENT INFO to verify this took effect
request req_subscribe;
req_subscribe.push("SUBSCRIBE", "ch1", "ch2", "ch3");
req_subscribe.push("PSUBSCRIBE", "ch1*", "ch2*");
req_subscribe.push("CLIENT", "INFO");
// Then, unsubscribe from some of them, and verify again
request req_unsubscribe;
req_unsubscribe.push("UNSUBSCRIBE", "ch1");
req_unsubscribe.push("PUNSUBSCRIBE", "ch2*");
req_unsubscribe.push("CLIENT", "INFO");
// Finally, ping to verify that the connection is still usable
request req_ping;
req_ping.push("PING", "test_unsubscribe");
response<std::string> resp_subscribe, resp_unsubscribe, resp_ping;
bool subscribe_finished = false, unsubscribe_finished = false, ping_finished = false,
run_finished = false;
auto on_ping = [&](error_code ec, std::size_t) {
BOOST_TEST(ec == error_code());
ping_finished = true;
BOOST_TEST(std::get<0>(resp_ping).has_value());
BOOST_TEST(std::get<0>(resp_ping).value() == "test_unsubscribe");
conn.cancel();
};
auto on_unsubscribe = [&](error_code ec, std::size_t) {
unsubscribe_finished = true;
BOOST_TEST(ec == error_code());
BOOST_TEST(std::get<0>(resp_unsubscribe).has_value());
BOOST_TEST(find_client_info(std::get<0>(resp_unsubscribe).value(), "sub") == "2");
BOOST_TEST(find_client_info(std::get<0>(resp_unsubscribe).value(), "psub") == "1");
conn.async_exec(req_ping, resp_ping, on_ping);
};
auto on_subscribe = [&](error_code ec, std::size_t) {
subscribe_finished = true;
BOOST_TEST(ec == error_code());
BOOST_TEST(std::get<0>(resp_subscribe).has_value());
BOOST_TEST(find_client_info(std::get<0>(resp_subscribe).value(), "sub") == "3");
BOOST_TEST(find_client_info(std::get<0>(resp_subscribe).value(), "psub") == "2");
conn.async_exec(req_unsubscribe, resp_unsubscribe, on_unsubscribe);
};
conn.async_exec(req_subscribe, resp_subscribe, on_subscribe);
conn.async_run(make_test_config(), [&run_finished](error_code ec) {
BOOST_TEST(ec == net::error::operation_aborted);
run_finished = true;
});
ioc.run_for(test_timeout);
BOOST_TEST(subscribe_finished);
BOOST_TEST(unsubscribe_finished);
BOOST_TEST(ping_finished);
BOOST_TEST(run_finished);
}
} // namespace

View File

@@ -29,21 +29,6 @@ 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()
{