File: test_conn_move.cpp

package info (click to toggle)
boost1.90 1.90.0-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 593,120 kB
  • sloc: cpp: 4,190,908; xml: 196,648; python: 34,618; ansic: 23,145; asm: 5,468; sh: 3,774; makefile: 1,161; perl: 1,020; sql: 728; ruby: 676; yacc: 478; java: 77; lisp: 24; csh: 6
file content (112 lines) | stat: -rw-r--r-- 2,871 bytes parent folder | download | duplicates (3)
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
//
// 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/request.hpp>
#include <boost/redis/response.hpp>

#include <boost/asio/bind_executor.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/post.hpp>
#include <boost/core/lightweight_test.hpp>

#include "common.hpp"

#include <cstddef>
#include <string>

using boost::system::error_code;
namespace net = boost::asio;
using namespace boost::redis;

namespace {

// Move constructing a connection doesn't leave dangling pointers
void test_conn_move_construct()
{
   // Setup
   net::io_context ioc;
   connection conn_prev(ioc);
   connection conn(std::move(conn_prev));
   request req;
   req.push("PING", "something");
   response<std::string> res;

   bool run_finished = false, exec_finished = false;

   // Run the connection
   conn.async_run(make_test_config(), [&](error_code ec) {
      run_finished = true;
      BOOST_TEST_EQ(ec, net::error::operation_aborted);
   });

   // Launch a PING
   conn.async_exec(req, res, [&](error_code ec, std::size_t) {
      exec_finished = true;
      BOOST_TEST_EQ(ec, error_code());
      conn.cancel();
   });

   ioc.run_for(test_timeout);

   // Check
   BOOST_TEST(run_finished);
   BOOST_TEST(exec_finished);
   BOOST_TEST_EQ(std::get<0>(res).value(), "something");
}

// Moving a connection is safe even when it's running,
// and it doesn't leave dangling pointers
void test_conn_move_assign_while_running()
{
   // Setup
   net::io_context ioc;
   connection conn(ioc);
   connection conn2(ioc);  // will be assigned to
   request req;
   req.push("PING", "something");
   response<std::string> res;

   bool run_finished = false, exec_finished = false;

   // Run the connection
   conn.async_run(make_test_config(), [&](error_code ec) {
      run_finished = true;
      BOOST_TEST_EQ(ec, net::error::operation_aborted);
   });

   // Launch a PING. When it finishes, conn will be moved-from, and conn2 will be valid
   conn.async_exec(req, res, [&](error_code ec, std::size_t) {
      exec_finished = true;
      BOOST_TEST_EQ(ec, error_code());
      conn2.cancel();
   });

   // While the operations are running, perform a move
   net::post(net::bind_executor(ioc.get_executor(), [&] {
      conn2 = std::move(conn);
   }));

   ioc.run_for(test_timeout);

   // Check
   BOOST_TEST(run_finished);
   BOOST_TEST(exec_finished);
   BOOST_TEST_EQ(std::get<0>(res).value(), "something");
}

}  // namespace

int main()
{
   test_conn_move_construct();
   test_conn_move_assign_while_running();

   return boost::report_errors();
}