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

Progresses with coverage.

This commit is contained in:
Marcelo Zimbres
2022-08-24 22:41:17 +02:00
parent d00f26d3da
commit 8249360a52
12 changed files with 421 additions and 289 deletions

View File

@@ -38,6 +38,7 @@ add_executable(subscriber examples/subscriber.cpp)
add_executable(subscriber_sync examples/subscriber_sync.cpp)
add_executable(test_low_level tests/low_level.cpp)
add_executable(test_connection tests/connection.cpp)
add_executable(test_connection_push tests/connection_push.cpp)
add_executable(low_level_sync tests/low_level_sync.cpp)
# Tests
@@ -48,7 +49,7 @@ add_test(intro intro)
add_test(intro_sync intro_sync)
add_test(serialization serialization)
add_test(test_low_level test_low_level)
add_test(test_connection test_connection)
add_test(test_connection_push test_connection_push)
add_test(low_level_sync low_level_sync)
# Install

View File

@@ -21,6 +21,7 @@ check_PROGRAMS += containers
check_PROGRAMS += serialization
check_PROGRAMS += test_low_level
check_PROGRAMS += test_connection
check_PROGRAMS += test_connection_push
EXTRA_PROGRAMS =
if HAVE_COROUTINES
@@ -45,6 +46,7 @@ intro_sync_SOURCES = $(top_srcdir)/examples/intro_sync.cpp
containers_SOURCES = $(top_srcdir)/examples/containers.cpp
serialization_SOURCES = $(top_srcdir)/examples/serialization.cpp
test_connection_SOURCES = $(top_srcdir)/tests/connection.cpp
test_connection_push_SOURCES = $(top_srcdir)/tests/connection_push.cpp
subscriber_sync_SOURCES = $(top_srcdir)/examples/subscriber_sync.cpp
if HAVE_COROUTINES
subscriber_SOURCES = $(top_srcdir)/examples/subscriber.cpp

View File

@@ -73,6 +73,7 @@ public:
boost::system::error_code& ec)
{
using boost::variant2::visit;
// TODO: Output an error instead of an assert.
BOOST_ASSERT(i < adapters_.size());
visit([&](auto& arg){arg(nd, ec);}, adapters_.at(i));
}

View File

@@ -284,7 +284,7 @@ public:
if (is_aggregate(nd.data_type)) {
if (i_ != -1) {
ec = error::nested_aggregate_unsupported;
ec = error::nested_aggregate_not_supported;
return;
}

View File

@@ -371,6 +371,7 @@ public:
Adapter adapter = adapt(),
CompletionToken token = CompletionToken{})
{
// TODO: Use adapter::response_traits here instead of aedis::response_traits
auto f =
[adapter]
(resp3::node<boost::string_view> const& node, boost::system::error_code& ec) mutable

View File

@@ -105,6 +105,11 @@ struct receive_push_op {
resp3::async_read(*conn->socket_, conn->make_dynamic_buffer(), adapter, std::move(self));
if (ec) {
conn->cancel(Conn::operation::run);
// Needed to cancel the channel, otherwise the read
// operation will be blocked forever see
// test_push_adapter.
conn->cancel(Conn::operation::receive_push);
self.complete(ec, 0);
return;
}
@@ -493,6 +498,7 @@ struct run_op {
// Consider communicating the return of async_run_one as an
// event here.
// TODO: Add event trying_again and sent it here.
conn->ping_timer_.expires_after(conn->cfg_.reconnect_interval);
yield

View File

@@ -59,7 +59,7 @@ enum class error
expects_resp3_set,
/// Nested response not supported.
nested_aggregate_unsupported,
nested_aggregate_not_supported,
/// Got RESP3 simple error.
simple_error,

View File

@@ -33,7 +33,7 @@ struct error_category_impl : boost::system::error_category {
case error::expects_resp3_aggregate: return "Expects resp3 aggregate.";
case error::expects_resp3_map: return "Expects resp3 map.";
case error::expects_resp3_set: return "Expects resp3 set.";
case error::nested_aggregate_unsupported: return "Nested aggregate unsupported.";
case error::nested_aggregate_not_supported: return "Nested aggregate not_supported.";
case error::simple_error: return "Got RESP3 simple-error.";
case error::blob_error: return "Got RESP3 blob-error.";
case error::incompatible_size: return "Aggregate container has incompatible size.";

View File

@@ -80,9 +80,7 @@ char to_code(type t)
case type::attribute: return '|';
case type::map: return '%';
default:
BOOST_ASSERT(false);
return ' ';
default: BOOST_ASSERT(false); return ' ';
}
}

View File

@@ -125,56 +125,6 @@ BOOST_AUTO_TEST_CASE(test_quit)
test_quit2(cfg);
}
// Checks whether we get idle timeout when no push reader is set.
void test_missing_push_reader1(connection::config const& cfg)
{
std::cout << "test_missing_push_reader1" << std::endl;
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
request req;
req.push("SUBSCRIBE", "channel");
db->async_run(req, adapt(), [](auto ec, auto){
BOOST_TEST(!ec);
});
ioc.run();
}
void test_missing_push_reader2(connection::config const& cfg)
{
std::cout << "test_missing_push_reader2" << std::endl;
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
request req; // Wrong command syntax.
req.push("SUBSCRIBE");
db->async_run(req, adapt(), [](auto ec, auto){
BOOST_TEST(!ec);
});
ioc.run();
}
void test_missing_push_reader3(connection::config const& cfg)
{
std::cout << "test_missing_push_reader3" << std::endl;
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
request req; // Wrong command synthax.
req.push("PING", "Message");
req.push("SUBSCRIBE");
db->async_run(req, adapt(), [](auto ec, auto){
BOOST_TEST(!ec);
});
ioc.run();
}
BOOST_AUTO_TEST_CASE(test_idle)
{
std::chrono::milliseconds ms{5000};
@@ -228,138 +178,6 @@ BOOST_AUTO_TEST_CASE(test_idle)
}
#ifdef BOOST_ASIO_HAS_CO_AWAIT
net::awaitable<void> push_consumer1(std::shared_ptr<connection> db, bool& push_received)
{
{
auto [ec, ev] = co_await db->async_receive_push(adapt(), as_tuple(net::use_awaitable));
BOOST_TEST(!ec);
}
{
auto [ec, ev] = co_await db->async_receive_push(adapt(), as_tuple(net::use_awaitable));
BOOST_CHECK_EQUAL(ec, boost::asio::experimental::channel_errc::channel_cancelled);
}
push_received = true;
}
net::awaitable<void> event_consumer1(std::shared_ptr<connection> db, bool& event_received)
{
{
auto [ec, ev] = co_await db->async_receive_event(as_tuple(net::use_awaitable));
auto const r = ev == connection::event::resolve;
BOOST_TEST(r);
BOOST_TEST(!ec);
}
{
auto [ec, ev] = co_await db->async_receive_event(as_tuple(net::use_awaitable));
auto const r = ev == connection::event::connect;
BOOST_TEST(r);
BOOST_TEST(!ec);
}
{
auto [ec, ev] = co_await db->async_receive_event(as_tuple(net::use_awaitable));
auto const r = ev == connection::event::hello;
BOOST_TEST(r);
BOOST_TEST(!ec);
}
{
auto [ec, ev] = co_await db->async_receive_event(as_tuple(net::use_awaitable));
BOOST_CHECK_EQUAL(ec, boost::asio::experimental::channel_errc::channel_cancelled);
}
event_received = true;
}
void test_push_is_received1(connection::config const& cfg)
{
std::cout << "test_push_is_received1" << std::endl;
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
db->get_config().enable_events = true;
request req;
req.push("SUBSCRIBE", "channel");
req.push("QUIT");
db->async_run(req, adapt(), [db](auto ec, auto){
BOOST_TEST(!ec);
db->cancel(connection::operation::receive_event);
db->cancel(connection::operation::receive_push);
});
bool push_received = false;
net::co_spawn(
ioc.get_executor(),
push_consumer1(db, push_received),
net::detached);
bool event_received = false;
net::co_spawn(
ioc.get_executor(),
event_consumer1(db, event_received),
net::detached);
ioc.run();
BOOST_TEST(push_received);
BOOST_TEST(event_received);
}
void test_push_is_received2(connection::config const& cfg)
{
request req1;
req1.push("PING", "Message1");
request req2;
req2.push("SUBSCRIBE", "channel");
request req3;
req3.push("PING", "Message2");
req3.push("QUIT");
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
db->get_config().enable_events = true;
auto handler =[](auto ec, auto...)
{
BOOST_TEST(!ec);
};
db->async_exec(req1, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req3, adapt(), handler);
db->async_run([db](auto ec, auto...) {
BOOST_CHECK_EQUAL(ec, net::error::misc_errors::eof);
db->cancel(connection::operation::receive_event);
db->cancel(connection::operation::receive_push);
});
bool push_received = false;
net::co_spawn(
ioc.get_executor(),
push_consumer1(db, push_received),
net::detached);
bool event_received = false;
net::co_spawn(
ioc.get_executor(),
event_consumer1(db, event_received),
net::detached);
ioc.run();
BOOST_TEST(push_received);
BOOST_TEST(event_received);
}
net::awaitable<void> test_reconnect_impl(std::shared_ptr<connection> db)
{
request req;
@@ -412,80 +230,4 @@ void test_reconnect()
std::cout << "End: test_reconnect()" << std::endl;
}
net::awaitable<void>
push_consumer3(std::shared_ptr<connection> db)
{
for (;;)
co_await db->async_receive_push(adapt(), net::use_awaitable);
}
// Test many subscribe requests.
void test_push_many_subscribes(connection::config const& cfg)
{
std::cout << "test_push_many_subscribes" << std::endl;
request req0;
req0.push("HELLO", 3);
request req1;
req1.push("PING", "Message1");
request req2;
req2.push("SUBSCRIBE", "channel");
request req3;
req3.push("QUIT");
auto handler =[](auto ec, auto...)
{
BOOST_TEST(!ec);
};
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
db->async_exec(req0, adapt(), handler);
db->async_exec(req1, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req1, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req1, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req1, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req3, adapt(), handler);
db->async_run([db](auto ec, auto...) {
BOOST_CHECK_EQUAL(ec, net::error::misc_errors::eof);
db->cancel(connection::operation::receive_push);
});
net::co_spawn(ioc.get_executor(), push_consumer3(db), net::detached);
ioc.run();
}
#endif
BOOST_AUTO_TEST_CASE(test_push)
{
connection::config cfg;
cfg.coalesce_requests = true;
#ifdef BOOST_ASIO_HAS_CO_AWAIT
test_push_is_received1(cfg);
test_push_is_received2(cfg);
test_push_many_subscribes(cfg);
#endif
test_missing_push_reader1(cfg);
test_missing_push_reader3(cfg);
cfg.coalesce_requests = false;
#ifdef BOOST_ASIO_HAS_CO_AWAIT
test_push_is_received1(cfg);
test_push_is_received2(cfg);
test_push_many_subscribes(cfg);
#endif
test_missing_push_reader2(cfg);
test_missing_push_reader3(cfg);
}

314
tests/connection_push.cpp Normal file
View File

@@ -0,0 +1,314 @@
/* Copyright (c) 2018-2022 Marcelo Zimbres Silva (mzimbres@gmail.com)
*
* Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE.txt)
*/
// TODO: Avoid usage of co_await to improve tests is compilers that
// don't support it.
// TODO: Add reconnect test that kills the server and waits some
// seconds.
#include <iostream>
#include <boost/asio.hpp>
#include <boost/system/errc.hpp>
#include <boost/asio/experimental/as_tuple.hpp>
#define BOOST_TEST_MODULE low level
#include <boost/test/included/unit_test.hpp>
#include <aedis.hpp>
#include <aedis/src.hpp>
namespace net = boost::asio;
using aedis::resp3::request;
using aedis::adapt;
using connection = aedis::connection<>;
using error_code = boost::system::error_code;
using net::experimental::as_tuple;
// Checks whether we get idle timeout when no push reader is set.
void test_missing_push_reader1(connection::config const& cfg)
{
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
request req;
req.push("SUBSCRIBE", "channel");
db->async_run(req, adapt(), [](auto ec, auto){
BOOST_TEST(!ec);
});
ioc.run();
}
void test_missing_push_reader2(connection::config const& cfg)
{
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
request req; // Wrong command syntax.
req.push("SUBSCRIBE");
db->async_run(req, adapt(), [](auto ec, auto){
BOOST_TEST(!ec);
});
ioc.run();
}
void test_missing_push_reader3(connection::config const& cfg)
{
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
request req; // Wrong command synthax.
req.push("PING", "Message");
req.push("SUBSCRIBE");
db->async_run(req, adapt(), [](auto ec, auto){
BOOST_TEST(!ec);
});
ioc.run();
}
#ifdef BOOST_ASIO_HAS_CO_AWAIT
net::awaitable<void> push_consumer1(std::shared_ptr<connection> db, bool& push_received)
{
{
auto [ec, ev] = co_await db->async_receive_push(adapt(), as_tuple(net::use_awaitable));
BOOST_TEST(!ec);
}
{
auto [ec, ev] = co_await db->async_receive_push(adapt(), as_tuple(net::use_awaitable));
BOOST_CHECK_EQUAL(ec, boost::asio::experimental::channel_errc::channel_cancelled);
}
push_received = true;
}
net::awaitable<void> event_consumer1(std::shared_ptr<connection> db, bool& event_received)
{
{
auto [ec, ev] = co_await db->async_receive_event(as_tuple(net::use_awaitable));
auto const r = ev == connection::event::resolve;
BOOST_TEST(r);
BOOST_TEST(!ec);
}
{
auto [ec, ev] = co_await db->async_receive_event(as_tuple(net::use_awaitable));
auto const r = ev == connection::event::connect;
BOOST_TEST(r);
BOOST_TEST(!ec);
}
{
auto [ec, ev] = co_await db->async_receive_event(as_tuple(net::use_awaitable));
auto const r = ev == connection::event::hello;
BOOST_TEST(r);
BOOST_TEST(!ec);
}
{
auto [ec, ev] = co_await db->async_receive_event(as_tuple(net::use_awaitable));
BOOST_CHECK_EQUAL(ec, boost::asio::experimental::channel_errc::channel_cancelled);
}
event_received = true;
}
BOOST_AUTO_TEST_CASE(test_push_adapter)
{
net::io_context ioc;
auto db = std::make_shared<connection>(ioc);
request req;
req.push("PING");
req.push("SUBSCRIBE", "channel");
req.push("PING");
auto f = [](auto, auto, auto& ec)
{
ec = aedis::error::incompatible_size;
};
// TODO: We should be able to use adapt here.
db->async_receive_push(f, [](auto ec, auto) {
BOOST_CHECK_EQUAL(ec, aedis::error::incompatible_size);
});
db->async_run(req, adapt(), [db](auto, auto){
// TODO: use async_run and async_exec.
//BOOST_CHECK_EQUAL(ec, net::error::misc_errors::eof);
});
ioc.run();
// TODO: Reset the ioc reconnect and send a quit to ensure
// reconnection is possible after an error.
}
void test_push_is_received1(connection::config const& cfg)
{
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
db->get_config().enable_events = true;
request req;
req.push("SUBSCRIBE", "channel");
req.push("QUIT");
db->async_run(req, adapt(), [db](auto ec, auto){
BOOST_TEST(!ec);
db->cancel(connection::operation::receive_event);
db->cancel(connection::operation::receive_push);
});
bool push_received = false;
net::co_spawn(
ioc.get_executor(),
push_consumer1(db, push_received),
net::detached);
bool event_received = false;
net::co_spawn(
ioc.get_executor(),
event_consumer1(db, event_received),
net::detached);
ioc.run();
BOOST_TEST(push_received);
BOOST_TEST(event_received);
}
void test_push_is_received2(connection::config const& cfg)
{
request req1;
req1.push("PING", "Message1");
request req2;
req2.push("SUBSCRIBE", "channel");
request req3;
req3.push("PING", "Message2");
req3.push("QUIT");
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
db->get_config().enable_events = true;
auto handler =[](auto ec, auto...)
{
BOOST_TEST(!ec);
};
db->async_exec(req1, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req3, adapt(), handler);
db->async_run([db](auto ec, auto...) {
BOOST_CHECK_EQUAL(ec, net::error::misc_errors::eof);
db->cancel(connection::operation::receive_event);
db->cancel(connection::operation::receive_push);
});
bool push_received = false;
net::co_spawn(
ioc.get_executor(),
push_consumer1(db, push_received),
net::detached);
bool event_received = false;
net::co_spawn(
ioc.get_executor(),
event_consumer1(db, event_received),
net::detached);
ioc.run();
BOOST_TEST(push_received);
BOOST_TEST(event_received);
}
net::awaitable<void> push_consumer3(std::shared_ptr<connection> db)
{
for (;;)
co_await db->async_receive_push(adapt(), net::use_awaitable);
}
// Test many subscribe requests.
void test_push_many_subscribes(connection::config const& cfg)
{
request req0;
req0.push("HELLO", 3);
request req1;
req1.push("PING", "Message1");
request req2;
req2.push("SUBSCRIBE", "channel");
request req3;
req3.push("QUIT");
auto handler =[](auto ec, auto...)
{
BOOST_TEST(!ec);
};
net::io_context ioc;
auto db = std::make_shared<connection>(ioc, cfg);
db->async_exec(req0, adapt(), handler);
db->async_exec(req1, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req1, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req1, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req1, adapt(), handler);
db->async_exec(req2, adapt(), handler);
db->async_exec(req3, adapt(), handler);
db->async_run([db](auto ec, auto...) {
BOOST_CHECK_EQUAL(ec, net::error::misc_errors::eof);
db->cancel(connection::operation::receive_push);
});
net::co_spawn(ioc.get_executor(), push_consumer3(db), net::detached);
ioc.run();
}
#endif
BOOST_AUTO_TEST_CASE(test_push)
{
connection::config cfg;
cfg.coalesce_requests = true;
#ifdef BOOST_ASIO_HAS_CO_AWAIT
test_push_is_received1(cfg);
test_push_is_received2(cfg);
test_push_many_subscribes(cfg);
#endif
test_missing_push_reader1(cfg);
test_missing_push_reader3(cfg);
cfg.coalesce_requests = false;
#ifdef BOOST_ASIO_HAS_CO_AWAIT
test_push_is_received1(cfg);
test_push_is_received2(cfg);
test_push_many_subscribes(cfg);
#endif
test_missing_push_reader2(cfg);
test_missing_push_reader3(cfg);
}

View File

@@ -155,41 +155,43 @@ BOOST_AUTO_TEST_CASE(test_bool)
boost::optional<bool> ok;
ok = true;
// Success.
auto const in08 = expect<node_type>{"#f\r\n", node_type{resp3::type::boolean, 1UL, 0UL, {"f"}}, "bool.node (false)"};
auto const in09 = expect<node_type>{"#t\r\n", node_type{resp3::type::boolean, 1UL, 0UL, {"t"}}, "bool.node (true)"};
auto const in10 = expect<bool>{"#t\r\n", bool{true}, "bool.bool (true)"};
auto const in11 = expect<bool>{"#f\r\n", bool{false}, "bool.bool (true)"};
auto const in13 = expect<boost::optional<bool>>{"#t\r\n", ok, "optional.int"};
// Error
auto const in01 = expect<boost::optional<bool>>{"#11\r\n", boost::optional<bool>{}, "bool.error", aedis::make_error_code(aedis::error::unexpected_bool_value)};
auto const in03 = expect<std::set<int>>{"#t\r\n", std::set<int>{}, "bool.error", aedis::make_error_code(aedis::error::expects_resp3_set)};
auto const in04 = expect<std::unordered_set<int>>{"#t\r\n", std::unordered_set<int>{}, "bool.error", aedis::make_error_code(aedis::error::expects_resp3_set)};
auto const in05 = expect<std::map<int, int>>{"#t\r\n", std::map<int, int>{}, "bool.error", aedis::make_error_code(aedis::error::expects_resp3_map)};
auto const in06 = expect<std::unordered_map<int, int>>{"#t\r\n", std::unordered_map<int, int>{}, "bool.error", aedis::make_error_code(aedis::error::expects_resp3_map)};
auto const in02 = expect<std::set<int>>{"#t\r\n", std::set<int>{}, "bool.error", aedis::make_error_code(aedis::error::expects_resp3_set)};
auto const in03 = expect<std::unordered_set<int>>{"#t\r\n", std::unordered_set<int>{}, "bool.error", aedis::make_error_code(aedis::error::expects_resp3_set)};
auto const in04 = expect<std::map<int, int>>{"#t\r\n", std::map<int, int>{}, "bool.error", aedis::make_error_code(aedis::error::expects_resp3_map)};
auto const in05 = expect<std::unordered_map<int, int>>{"#t\r\n", std::unordered_map<int, int>{}, "bool.error", aedis::make_error_code(aedis::error::expects_resp3_map)};
// Success.
auto const in06 = expect<node_type>{"#f\r\n", node_type{resp3::type::boolean, 1UL, 0UL, {"f"}}, "bool.node (false)"};
auto const in07 = expect<node_type>{"#t\r\n", node_type{resp3::type::boolean, 1UL, 0UL, {"t"}}, "bool.node (true)"};
auto const in08 = expect<bool>{"#t\r\n", bool{true}, "bool.bool (true)"};
auto const in09 = expect<bool>{"#f\r\n", bool{false}, "bool.bool (true)"};
auto const in10 = expect<boost::optional<bool>>{"#t\r\n", ok, "optional.int"};
auto ex = ioc.get_executor();
test_sync(ex, in01);
test_sync(ex, in02);
test_sync(ex, in03);
test_sync(ex, in04);
test_sync(ex, in05);
test_sync(ex, in06);
test_sync(ex, in07);
test_sync(ex, in08);
test_sync(ex, in09);
test_sync(ex, in10);
test_sync(ex, in11);
test_async(ex, in01);
test_async(ex, in02);
test_async(ex, in03);
test_async(ex, in04);
test_async(ex, in05);
test_async(ex, in06);
test_async(ex, in07);
test_async(ex, in08);
test_async(ex, in09);
test_async(ex, in10);
test_async(ex, in11);
ioc.run();
}
@@ -208,8 +210,8 @@ BOOST_AUTO_TEST_CASE(test_streamed_string)
std::vector<node_type> e1b { {resp3::type::streamed_string_part, 1UL, 1UL, {}} };
auto const in01 = expect<std::vector<node_type>>{wire, e1a, "streamed_string.node"};
auto const in03 = expect<std::string>{wire, std::string{"Hello word"}, "streamed_string.string"};
auto const in02 = expect<std::vector<node_type>>{"$?\r\n;0\r\n", e1b, "streamed_string.node.empty"};
auto const in02 = expect<std::string>{wire, std::string{"Hello word"}, "streamed_string.string"};
auto const in03 = expect<std::vector<node_type>>{"$?\r\n;0\r\n", e1b, "streamed_string.node.empty"};
auto ex = ioc.get_executor();
@@ -347,10 +349,11 @@ BOOST_AUTO_TEST_CASE(test_map)
test_sync(ex, in03);
test_sync(ex, in04);
test_sync(ex, in05);
test_sync(ex, in06);
test_sync(ex, in07);
test_sync(ex, in08);
test_sync(ex, in09);
test_sync(ex, in00);
test_sync(ex, in10);
test_sync(ex, in11);
test_sync(ex, in12);
test_sync(ex, in13);
@@ -361,10 +364,11 @@ BOOST_AUTO_TEST_CASE(test_map)
test_async(ex, in03);
test_async(ex, in04);
test_async(ex, in05);
test_async(ex, in06);
test_async(ex, in07);
test_async(ex, in08);
test_async(ex, in09);
test_async(ex, in00);
test_async(ex, in10);
test_async(ex, in11);
test_async(ex, in12);
test_async(ex, in13);
@@ -401,8 +405,13 @@ void test_attribute(net::io_context& ioc)
BOOST_AUTO_TEST_CASE(test_array)
{
using tuple_type = std::tuple<int, int>;
using array_type = std::array<int, 3>;
using array_type2 = std::array<int, 1>;
net::io_context ioc;
char const* wire = "*3\r\n$2\r\n11\r\n$2\r\n22\r\n$1\r\n3\r\n";
char const* wire_nested = "*1\r\n*1\r\n$2\r\nab\r\n";
std::vector<node_type> e1a
{ {resp3::type::array, 3UL, 0UL, {}}
@@ -415,7 +424,7 @@ BOOST_AUTO_TEST_CASE(test_array)
std::vector<std::string> const e1c{"11", "22", "3"};
std::vector<std::string> const e1d{};
std::vector<node_type> const e1e{{resp3::type::array, 0UL, 0UL, {}}};
std::array<int, 3> const e1f{11, 22, 3};
array_type const e1f{11, 22, 3};
std::list<int> const e1g{11, 22, 3};
std::deque<int> const e1h{11, 22, 3};
@@ -424,11 +433,16 @@ BOOST_AUTO_TEST_CASE(test_array)
auto const in03 = expect<std::vector<node_type>>{"*0\r\n", e1e, "array.node.empty"};
auto const in04 = expect<std::vector<std::string>>{"*0\r\n", e1d, "array.string.empty"};
auto const in05 = expect<std::vector<std::string>>{wire, e1c, "array.string"};
auto const in06 = expect<std::array<int, 3>>{wire, e1f, "array.array"};
auto const in06 = expect<array_type>{wire, e1f, "array.array"};
auto const in07 = expect<std::list<int>>{wire, e1g, "array.list"};
auto const in08 = expect<std::deque<int>>{wire, e1h, "array.deque"};
auto const in09 = expect<std::vector<int>>{"_\r\n", std::vector<int>{}, "array.vector", aedis::make_error_code(aedis::error::null)};
auto const in10 = expect<std::list<int>>{"_\r\n", std::list<int>{}, "array.list", aedis::make_error_code(aedis::error::null)};
auto const in11 = expect<array_type>{"_\r\n", array_type{}, "array.null", aedis::make_error_code(aedis::error::null)};
auto const in12 = expect<tuple_type>{wire, tuple_type{}, "array.list", aedis::make_error_code(aedis::error::incompatible_size)};
auto const in13 = expect<array_type2>{wire_nested, array_type2{}, "array.nested", aedis::make_error_code(aedis::error::nested_aggregate_not_supported)};
auto const in14 = expect<array_type2>{wire, array_type2{}, "array.null", aedis::make_error_code(aedis::error::incompatible_size)};
auto const in15 = expect<array_type2>{":3\r\n", array_type2{}, "array.array", aedis::make_error_code(aedis::error::expects_resp3_aggregate)};
auto ex = ioc.get_executor();
@@ -441,6 +455,12 @@ BOOST_AUTO_TEST_CASE(test_array)
test_sync(ex, in07);
test_sync(ex, in08);
test_sync(ex, in09);
test_sync(ex, in10);
test_sync(ex, in11);
test_sync(ex, in12);
test_sync(ex, in13);
test_sync(ex, in14);
test_sync(ex, in15);
test_async(ex, in01);
test_async(ex, in02);
@@ -451,6 +471,13 @@ BOOST_AUTO_TEST_CASE(test_array)
test_async(ex, in07);
test_async(ex, in08);
test_async(ex, in09);
test_async(ex, in10);
test_async(ex, in11);
test_async(ex, in12);
test_async(ex, in13);
test_async(ex, in14);
test_async(ex, in15);
ioc.run();
}
@@ -671,12 +698,20 @@ BOOST_AUTO_TEST_CASE(test_simple_string)
BOOST_AUTO_TEST_CASE(test_resp3)
{
using map_type = std::map<std::string, std::string>;
std::string const wire_map = "%rt\r\n$4\r\nkey1\r\n$6\r\nvalue1\r\n$4\r\nkey2\r\n$6\r\nvalue2\r\n";
std::string const wire_ssp = "$?\r\n;d\r\nHell\r\n;5\r\no wor\r\n;1\r\nd\r\n;0\r\n";
net::io_context ioc;
auto const in01 = expect<int>{"s11\r\n", int{}, "number.error", aedis::make_error_code(aedis::error::invalid_data_type)};
auto const in02 = expect<int>{":adf\r\n", int{11}, "number.int", aedis::make_error_code(aedis::error::not_a_number)};
auto const in03 = expect<int>{":\r\n", int{}, "number.error (empty field)", aedis::make_error_code(aedis::error::empty_field)};
auto const in04 = expect<boost::optional<bool>>{"#\r\n", boost::optional<bool>{}, "bool.error", aedis::make_error_code(aedis::error::empty_field)};
auto const in05 = expect<std::string>{",\r\n", std::string{}, "double.error (empty field)", aedis::make_error_code(aedis::error::empty_field)};
auto const in03 = expect<map_type>{wire_map, map_type{}, "map.error", aedis::make_error_code(aedis::error::not_a_number)};
auto const in04 = expect<std::string>{wire_ssp, std::string{}, "streamed_string_part.error", aedis::make_error_code(aedis::error::not_a_number)};
auto const in05 = expect<std::string>{"$l\r\nhh\r\n", std::string{}, "blob_string.error", aedis::make_error_code(aedis::error::not_a_number)};
auto const in06 = expect<int>{":\r\n", int{}, "number.error (empty field)", aedis::make_error_code(aedis::error::empty_field)};
auto const in07 = expect<boost::optional<bool>>{"#\r\n", boost::optional<bool>{}, "bool.error", aedis::make_error_code(aedis::error::empty_field)};
auto const in08 = expect<std::string>{",\r\n", std::string{}, "double.error (empty field)", aedis::make_error_code(aedis::error::empty_field)};
auto ex = ioc.get_executor();
@@ -685,12 +720,18 @@ BOOST_AUTO_TEST_CASE(test_resp3)
test_sync(ex, in03);
test_sync(ex, in04);
test_sync(ex, in05);
test_sync(ex, in06);
test_sync(ex, in07);
test_sync(ex, in08);
test_async(ex, in01);
test_async(ex, in02);
test_async(ex, in03);
test_async(ex, in04);
test_async(ex, in05);
test_async(ex, in06);
test_async(ex, in07);
test_async(ex, in08);
ioc.run();
}
@@ -773,7 +814,7 @@ BOOST_AUTO_TEST_CASE(error)
check_error("aedis", aedis::error::expects_resp3_aggregate);
check_error("aedis", aedis::error::expects_resp3_map);
check_error("aedis", aedis::error::expects_resp3_set);
check_error("aedis", aedis::error::nested_aggregate_unsupported);
check_error("aedis", aedis::error::nested_aggregate_not_supported);
check_error("aedis", aedis::error::simple_error);
check_error("aedis", aedis::error::blob_error);
check_error("aedis", aedis::error::incompatible_size);
@@ -788,7 +829,7 @@ std::string get_type_as_str(aedis::resp3::type t)
return ss.str();
}
BOOST_AUTO_TEST_CASE(type)
BOOST_AUTO_TEST_CASE(type_string)
{
BOOST_TEST(!get_type_as_str(aedis::resp3::type::array).empty());
BOOST_TEST(!get_type_as_str(aedis::resp3::type::push).empty());
@@ -808,3 +849,29 @@ BOOST_AUTO_TEST_CASE(type)
BOOST_TEST(!get_type_as_str(aedis::resp3::type::streamed_string_part).empty());
BOOST_TEST(!get_type_as_str(aedis::resp3::type::invalid).empty());
}
BOOST_AUTO_TEST_CASE(type_convert)
{
using aedis::resp3::to_code;
using aedis::resp3::to_type;
using aedis::resp3::type;
#define CHECK_CASE(A) BOOST_CHECK_EQUAL(to_type(to_code(type::A)), type::A);
CHECK_CASE(array);
CHECK_CASE(push);
CHECK_CASE(set);
CHECK_CASE(map);
CHECK_CASE(attribute);
CHECK_CASE(simple_string);
CHECK_CASE(simple_error);
CHECK_CASE(number);
CHECK_CASE(doublean);
CHECK_CASE(boolean);
CHECK_CASE(big_number);
CHECK_CASE(null);
CHECK_CASE(blob_error);
CHECK_CASE(verbatim_string);
CHECK_CASE(blob_string);
CHECK_CASE(streamed_string_part);
#undef CHECK_CASE
}