1//
2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// Official repository: https://github.com/boostorg/beast
8//
9
10// Test that header file is self-contained.
11#include <boost/beast/core/saved_handler.hpp>
12#include <boost/asio/bind_cancellation_slot.hpp>
13#include <boost/beast/_experimental/unit_test/suite.hpp>
14#include <stdexcept>
15
16namespace boost {
17namespace beast {
18
19//------------------------------------------------------------------------------
20
21class saved_handler_test : public unit_test::suite
22{
23public:
24 class handler
25 {
26 bool failed_ = true;
27 bool throw_on_move_ = false;
28
29 public:
30 handler() = default;
31 handler(handler const&) = delete;
32 handler& operator=(handler&&) = delete;
33 handler& operator=(handler const&) = delete;
34
35 ~handler()
36 {
37 BEAST_EXPECT(! failed_);
38 }
39
40 handler(handler&& other)
41 : failed_(boost::exchange(
42 t&: other.failed_, u: false))
43 {
44 if(throw_on_move_)
45 throw std::bad_alloc{};
46 }
47
48 void
49 operator()(system::error_code = {})
50 {
51 failed_ = false;
52 }
53 };
54
55 class unhandler
56 {
57 bool invoked_ = false;
58
59 public:
60 unhandler() = default;
61 unhandler(unhandler const&) = delete;
62 unhandler& operator=(unhandler&&) = delete;
63 unhandler& operator=(unhandler const&) = delete;
64
65 ~unhandler()
66 {
67 BEAST_EXPECT(! invoked_);
68 }
69
70 unhandler(unhandler&& other)
71 : invoked_(boost::exchange(
72 t&: other.invoked_, u: false))
73 {
74 }
75
76 void
77 operator()(system::error_code = {})
78 {
79 invoked_ = true;
80 }
81 };
82
83 struct throwing_handler
84 {
85 throwing_handler() = default;
86
87 throwing_handler(throwing_handler&&)
88 {
89 BOOST_THROW_EXCEPTION(std::exception{});
90 }
91
92 void
93 operator()(system::error_code = {})
94 {
95 }
96 };
97
98 void
99 testSavedHandler()
100 {
101 {
102 saved_handler sh;
103 BEAST_EXPECT(! sh.has_value());
104
105 sh.emplace(handler: handler{});
106 BEAST_EXPECT(sh.has_value());
107 sh.invoke();
108 BEAST_EXPECT(! sh.has_value());
109
110 sh.emplace(handler: handler{}, alloc: std::allocator<char>{});
111 BEAST_EXPECT(sh.has_value());
112 sh.invoke();
113 BEAST_EXPECT(! sh.has_value());
114
115 sh.emplace(handler: unhandler{});
116 BEAST_EXPECT(sh.has_value());
117 }
118
119 {
120 saved_handler sh;
121 try
122 {
123 sh.emplace(handler: throwing_handler{});
124 fail();
125 }
126 catch(std::exception const&)
127 {
128 pass();
129 }
130 BEAST_EXPECT(! sh.has_value());
131 }
132 }
133
134 void
135 testSavedHandlerCancellation()
136 {
137 {
138 net::cancellation_signal sig;
139
140 saved_handler sh;
141 BEAST_EXPECT(! sh.has_value());
142
143 sh.emplace(
144 handler: net::bind_cancellation_slot(
145 s: sig.slot(), t: handler{}));
146 BEAST_EXPECT(sh.has_value());
147 BEAST_EXPECT(sig.slot().has_handler());
148 sig.emit(type: net::cancellation_type::all);
149 BEAST_EXPECT(! sh.has_value());
150 BEAST_EXPECT(!sig.slot().has_handler());
151
152
153 sh.emplace(
154 handler: net::bind_cancellation_slot(
155 s: sig.slot(), t: handler{}));
156 BEAST_EXPECT(sh.has_value());
157 BEAST_EXPECT(sig.slot().has_handler());
158 sig.emit(type: net::cancellation_type::total);
159 BEAST_EXPECT(sh.has_value());
160 BEAST_EXPECT(sig.slot().has_handler());
161 sig.emit(type: net::cancellation_type::terminal);
162 BEAST_EXPECT(! sh.has_value());
163 BEAST_EXPECT(!sig.slot().has_handler());
164
165 sh.emplace(
166 handler: net::bind_cancellation_slot(
167 s: sig.slot(), t: handler{}),
168 cancel_type: net::cancellation_type::total);
169 BEAST_EXPECT(sh.has_value());
170 BEAST_EXPECT(sig.slot().has_handler());
171 sig.emit(type: net::cancellation_type::total);
172 BEAST_EXPECT(! sh.has_value());
173 BEAST_EXPECT(!sig.slot().has_handler());
174
175 {
176 saved_handler sh_inner;
177 sh_inner.emplace(
178 handler: net::bind_cancellation_slot(
179 s: sig.slot(), t: handler{}));
180
181 sh = std::move(sh_inner);
182 }
183 BEAST_EXPECT(sh.has_value());
184 BEAST_EXPECT(sig.slot().has_handler());
185 sig.emit(type: net::cancellation_type::all);
186 BEAST_EXPECT(! sh.has_value());
187 BEAST_EXPECT(!sig.slot().has_handler());
188
189 }
190 {
191 saved_handler sh;
192 net::cancellation_signal sig;
193
194 try
195 {
196 sh.emplace(
197 handler: net::bind_cancellation_slot(
198 s: sig.slot(),
199 t: throwing_handler{}));
200 fail();
201 }
202 catch(std::exception const&)
203 {
204 pass();
205 }
206 BEAST_EXPECT(!sig.slot().has_handler());
207 BEAST_EXPECT(! sh.has_value());
208 }
209 }
210
211 void
212 run() override
213 {
214 testSavedHandler();
215 testSavedHandlerCancellation();
216 }
217};
218
219BEAST_DEFINE_TESTSUITE(beast,core,saved_handler);
220
221} // beast
222} // boost
223

source code of boost/libs/beast/test/beast/core/saved_handler.cpp