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 
13 #include <boost/beast/_experimental/unit_test/suite.hpp>
14 #include <stdexcept>
15 
16 namespace boost {
17 namespace beast {
18 
19 //------------------------------------------------------------------------------
20 
21 class saved_handler_test : public unit_test::suite
22 {
23 public:
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 
~handler()35         ~handler()
36         {
37             BEAST_EXPECT(! failed_);
38         }
39 
handler(handler && other)40         handler(handler&& other)
41             : failed_(boost::exchange(
42                 other.failed_, false))
43         {
44             if(throw_on_move_)
45                 throw std::bad_alloc{};
46         }
47 
48         void
operator ()()49         operator()()
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 
~unhandler()65         ~unhandler()
66         {
67             BEAST_EXPECT(! invoked_);
68         }
69 
unhandler(unhandler && other)70         unhandler(unhandler&& other)
71             : invoked_(boost::exchange(
72                 other.invoked_, false))
73         {
74         }
75 
76         void
operator ()()77         operator()()
78         {
79             invoked_ = true;
80         }
81     };
82 
83     struct throwing_handler
84     {
85         throwing_handler() = default;
86 
throwing_handlerboost::beast::saved_handler_test::throwing_handler87         throwing_handler(throwing_handler&&)
88         {
89             BOOST_THROW_EXCEPTION(std::exception{});
90         }
91 
92         void
operator ()boost::beast::saved_handler_test::throwing_handler93         operator()()
94         {
95         }
96     };
97 
98     void
testSavedHandler()99     testSavedHandler()
100     {
101         {
102             saved_handler sh;
103             BEAST_EXPECT(! sh.has_value());
104 
105             sh.emplace(handler{});
106             BEAST_EXPECT(sh.has_value());
107             sh.invoke();
108             BEAST_EXPECT(! sh.has_value());
109 
110             sh.emplace(handler{}, std::allocator<char>{});
111             BEAST_EXPECT(sh.has_value());
112             sh.invoke();
113             BEAST_EXPECT(! sh.has_value());
114 
115             sh.emplace(unhandler{});
116             BEAST_EXPECT(sh.has_value());
117         }
118 
119         {
120             saved_handler sh;
121             try
122             {
123                 sh.emplace(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
run()135     run() override
136     {
137         testSavedHandler();
138     }
139 };
140 
141 BEAST_DEFINE_TESTSUITE(beast,core,saved_handler);
142 
143 } // beast
144 } // boost
145