1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
|
/* Copyright (c) 2018-2022 Marcelo Zimbres Silva (mzimbres@gmail.com)
*
* Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE.txt)
*/
#include <boost/redis/adapter/any_adapter.hpp>
#include <boost/redis/connection.hpp>
#include <boost/asio/detached.hpp>
#include <cstddef>
#include <string>
#define BOOST_TEST_MODULE conn_exec
#include <boost/test/included/unit_test.hpp>
#include "common.hpp"
#include <iostream>
// TODO: Test whether HELLO won't be inserted past commands that have
// been already written.
// TODO: Test async_exec with empty request e.g. hgetall with an empty
// container.
namespace net = boost::asio;
using boost::redis::config;
using boost::redis::connection;
using boost::redis::generic_response;
using boost::redis::ignore;
using boost::redis::operation;
using boost::redis::request;
using boost::redis::response;
using boost::redis::any_adapter;
using boost::system::error_code;
using namespace std::chrono_literals;
namespace {
// Sends three requests where one of them has a hello with a priority
// set, which means it should be executed first.
BOOST_AUTO_TEST_CASE(hello_priority)
{
request req1;
req1.push("PING", "req1");
request req2;
req2.get_config().hello_with_priority = false;
req2.push("HELLO", 3);
req2.push("PING", "req2");
request req3;
req3.get_config().hello_with_priority = true;
req3.push("HELLO", 3);
req3.push("PING", "req3");
net::io_context ioc;
auto conn = std::make_shared<connection>(ioc);
bool seen1 = false;
bool seen2 = false;
bool seen3 = false;
conn->async_exec(req1, ignore, [&](error_code ec, std::size_t) {
// Second callback to the called.
std::cout << "req1" << std::endl;
BOOST_TEST(ec == error_code());
BOOST_TEST(!seen2);
BOOST_TEST(seen3);
seen1 = true;
});
conn->async_exec(req2, ignore, [&](error_code ec, std::size_t) {
// Last callback to the called.
std::cout << "req2" << std::endl;
BOOST_TEST(ec == error_code());
BOOST_TEST(seen1);
BOOST_TEST(seen3);
seen2 = true;
conn->cancel(operation::run);
conn->cancel(operation::reconnection);
});
conn->async_exec(req3, ignore, [&](error_code ec, std::size_t) {
// Callback that will be called first.
std::cout << "req3" << std::endl;
BOOST_TEST(ec == error_code());
BOOST_TEST(!seen1);
BOOST_TEST(!seen2);
seen3 = true;
});
run(conn);
ioc.run_for(test_timeout);
BOOST_TEST(seen1);
BOOST_TEST(seen2);
BOOST_TEST(seen3);
}
// Tries to receive a string in an int and gets an error.
BOOST_AUTO_TEST_CASE(wrong_response_data_type)
{
request req;
req.push("PING");
// Wrong data type.
response<int> resp;
net::io_context ioc;
auto conn = std::make_shared<connection>(ioc);
bool finished = false;
conn->async_exec(req, resp, [conn, &finished](error_code ec, std::size_t) {
BOOST_TEST(ec == boost::redis::error::not_a_number);
conn->cancel(operation::reconnection);
finished = true;
});
run(conn);
ioc.run_for(test_timeout);
BOOST_TEST(finished);
}
BOOST_AUTO_TEST_CASE(large_number_of_concurrent_requests_issue_170)
{
// See https://github.com/boostorg/redis/issues/170
std::string payload;
payload.resize(1024);
std::fill(std::begin(payload), std::end(payload), 'A');
net::io_context ioc;
auto conn = std::make_shared<connection>(ioc);
auto cfg = make_test_config();
conn->async_run(cfg, net::detached);
constexpr int repeat = 8000;
int remaining = repeat;
for (int i = 0; i < repeat; ++i) {
auto req = std::make_shared<request>();
req->push("PING", payload);
conn->async_exec(*req, ignore, [req, &remaining, conn](error_code ec, std::size_t) {
BOOST_TEST(ec == error_code());
if (--remaining == 0)
conn->cancel();
});
}
ioc.run_for(test_timeout);
BOOST_TEST(remaining == 0);
}
BOOST_AUTO_TEST_CASE(exec_any_adapter)
{
// Executing an any_adapter object works
request req;
req.push("PING", "PONG");
response<std::string> res;
net::io_context ioc;
auto conn = std::make_shared<connection>(ioc);
bool finished = false;
conn->async_exec(req, res, [&](error_code ec, std::size_t) {
BOOST_TEST(ec == error_code());
conn->cancel();
finished = true;
});
run(conn);
ioc.run_for(test_timeout);
BOOST_TEST_REQUIRE(finished);
BOOST_TEST(std::get<0>(res).value() == "PONG");
}
} // namespace
|