Line data Source code
1 : // Copyright (c) 2018-2023 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snapdev
4 : // contact@m2osw.com
5 : //
6 : // This program is free software: you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation, either version 3 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program. If not, see <https://www.gnu.org/licenses/>.
18 :
19 : /** \file
20 : * \brief Verify that the callback_manager class works.
21 : *
22 : * This file implements tests for the callback_manager class.
23 : */
24 :
25 : // self
26 : //
27 : #include <snapdev/callback_manager.h>
28 :
29 : #include "catch_main.h"
30 :
31 :
32 : // snapdev include
33 : //
34 : #include <snapdev/not_used.h>
35 :
36 :
37 : // C++ include
38 : //
39 : #include <list>
40 : #include <set>
41 :
42 :
43 : // last include
44 : //
45 : #include <snapdev/poison.h>
46 :
47 :
48 : namespace
49 : {
50 :
51 :
52 : bool g_called = false;
53 : int g_expected_a = 33;
54 : int g_expected_b = 51;
55 : std::string g_expected_c = "expected value";
56 :
57 2 : bool the_static_callback(int v, int q, std::string z)
58 : {
59 2 : CATCH_REQUIRE(v == g_expected_a);
60 2 : CATCH_REQUIRE(q == g_expected_b);
61 2 : CATCH_REQUIRE(z == g_expected_c);
62 2 : g_called = true;
63 2 : return g_expected_a == 33;
64 : }
65 :
66 1 : bool void_static_callback()
67 : {
68 1 : g_called = true;
69 1 : return true;
70 : }
71 :
72 :
73 :
74 :
75 : }
76 : // no name namespace
77 :
78 :
79 :
80 4 : CATCH_TEST_CASE("callback_manager", "[callback]")
81 : {
82 4 : CATCH_START_SECTION("callback manager: member function callback")
83 : {
84 1 : int count(0);
85 :
86 : class foo
87 : {
88 : public:
89 : typedef std::shared_ptr<foo> pointer_t;
90 : typedef std::vector<pointer_t> vector_t;
91 :
92 3 : foo(int & cnt, int id)
93 3 : : f_id(id)
94 3 : , f_count(cnt)
95 : {
96 3 : }
97 :
98 6 : bool the_callback(int v, int q, int z)
99 : {
100 6 : CATCH_REQUIRE(v == f_expected_a);
101 6 : CATCH_REQUIRE(q == f_expected_b);
102 6 : CATCH_REQUIRE(z == f_expected_c);
103 6 : CATCH_REQUIRE(f_count == f_expected_count);
104 6 : ++f_count;
105 6 : return f_count < 9;
106 : }
107 :
108 3 : bool void_callback()
109 : {
110 3 : ++f_count;
111 3 : return true;
112 : }
113 :
114 : int f_id = 0;
115 : int & f_count;
116 : int f_expected_a = 0;
117 : int f_expected_b = 0;
118 : int f_expected_c = 0;
119 : int f_expected_count = 0;
120 : };
121 1 : snapdev::callback_manager<foo::pointer_t> m;
122 :
123 1 : foo::pointer_t f1(std::make_shared<foo>(count, 1));
124 1 : foo::pointer_t f2(std::make_shared<foo>(count, 2));
125 1 : foo::pointer_t f3(std::make_shared<foo>(count, 3));
126 :
127 1 : f1->f_expected_a = 5;
128 1 : f2->f_expected_a = 5;
129 1 : f3->f_expected_a = 5;
130 1 : f1->f_expected_b = 13;
131 1 : f2->f_expected_b = 13;
132 1 : f3->f_expected_b = 13;
133 1 : f1->f_expected_c = 7;
134 1 : f2->f_expected_c = 7;
135 1 : f3->f_expected_c = 7;
136 1 : f1->f_expected_count = 1;
137 1 : f2->f_expected_count = 0;
138 1 : f3->f_expected_count = 2;
139 :
140 1 : CATCH_REQUIRE(m.size() == 0);
141 1 : CATCH_REQUIRE(m.empty());
142 1 : auto const id1(m.add_callback(f1, 0));
143 1 : auto const id2(m.add_callback(f2, 1));
144 1 : auto const id3(m.add_callback(f3, -1));
145 1 : CATCH_REQUIRE_FALSE(m.empty());
146 1 : CATCH_REQUIRE(m.size() == 3);
147 :
148 1 : CATCH_REQUIRE(m.call(&foo::the_callback, 5, 13, 7));
149 :
150 1 : CATCH_REQUIRE(count == 3);
151 1 : CATCH_REQUIRE(f1->f_count == 3);
152 1 : CATCH_REQUIRE(f2->f_count == 3);
153 1 : CATCH_REQUIRE(f3->f_count == 3);
154 :
155 1 : CATCH_REQUIRE(m.call(&foo::void_callback));
156 :
157 1 : CATCH_REQUIRE(count == 6);
158 1 : CATCH_REQUIRE(f1->f_count == 6);
159 1 : CATCH_REQUIRE(f2->f_count == 6);
160 1 : CATCH_REQUIRE(f3->f_count == 6);
161 :
162 1 : CATCH_REQUIRE(m.remove_callback(id2));
163 1 : CATCH_REQUIRE_FALSE(m.empty());
164 1 : CATCH_REQUIRE(m.size() == 2);
165 :
166 1 : CATCH_REQUIRE_FALSE(m.remove_callback(id2));
167 1 : CATCH_REQUIRE_FALSE(m.empty());
168 1 : CATCH_REQUIRE(m.size() == 2);
169 :
170 1 : f1->f_expected_a = 12;
171 1 : f3->f_expected_a = 12;
172 1 : f1->f_expected_b = 37;
173 1 : f3->f_expected_b = 37;
174 1 : f1->f_expected_c = 17;
175 1 : f3->f_expected_c = 17;
176 :
177 1 : f1->f_expected_count = 6;
178 1 : f3->f_expected_count = 7;
179 :
180 1 : CATCH_REQUIRE(m.call(&foo::the_callback, 12, 37, 17));
181 :
182 1 : CATCH_REQUIRE(count == 8);
183 1 : CATCH_REQUIRE(f1->f_count == 8);
184 1 : CATCH_REQUIRE(f2->f_count == 8);
185 1 : CATCH_REQUIRE(f3->f_count == 8);
186 :
187 1 : f1->f_expected_a = 25;
188 1 : f1->f_expected_b = 31;
189 1 : f1->f_expected_c = 6;
190 :
191 1 : f1->f_expected_count = 8;
192 :
193 1 : CATCH_REQUIRE_FALSE(m.call(&foo::the_callback, 25, 31, 6));
194 :
195 1 : CATCH_REQUIRE(count == 9);
196 1 : CATCH_REQUIRE(f1->f_count == 9);
197 1 : CATCH_REQUIRE(f2->f_count == 9);
198 1 : CATCH_REQUIRE(f3->f_count == 9);
199 :
200 1 : CATCH_REQUIRE_FALSE(m.empty());
201 1 : CATCH_REQUIRE(m.clear());
202 1 : CATCH_REQUIRE(m.empty());
203 1 : CATCH_REQUIRE(m.size() == 0);
204 1 : CATCH_REQUIRE_FALSE(m.clear());
205 1 : CATCH_REQUIRE_FALSE(m.remove_callback(id1));
206 1 : CATCH_REQUIRE_FALSE(m.remove_callback(id3));
207 1 : }
208 4 : CATCH_END_SECTION()
209 :
210 4 : CATCH_START_SECTION("callback manager: direct function callback with 3 parameters")
211 : {
212 1 : g_called = false;
213 :
214 : typedef bool (*callback_t)(int, int, std::string);
215 :
216 1 : snapdev::callback_manager<callback_t> m;
217 :
218 1 : CATCH_REQUIRE(m.add_callback(the_static_callback));
219 1 : CATCH_REQUIRE_FALSE(m.empty());
220 1 : CATCH_REQUIRE(m.size() == 1);
221 :
222 1 : CATCH_REQUIRE_FALSE(g_called);
223 1 : CATCH_REQUIRE(m.call(33, 51, "expected value"));
224 1 : CATCH_REQUIRE(g_called);
225 :
226 1 : g_called = false;
227 1 : g_expected_a = 44;
228 1 : g_expected_b = 50;
229 1 : g_expected_c = "return false";
230 1 : CATCH_REQUIRE_FALSE(g_called);
231 1 : CATCH_REQUIRE_FALSE(m.call(44, 50, "return false"));
232 1 : CATCH_REQUIRE(g_called);
233 1 : }
234 4 : CATCH_END_SECTION()
235 :
236 4 : CATCH_START_SECTION("callback manager: direct function callback with no parameters")
237 : {
238 1 : g_called = false;
239 :
240 : typedef bool (*callback_t)();
241 : typedef std::list<callback_t> list_t;
242 :
243 1 : snapdev::callback_manager<callback_t> m;
244 :
245 1 : CATCH_REQUIRE(m.add_callback(void_static_callback));
246 :
247 1 : CATCH_REQUIRE_FALSE(g_called);
248 1 : CATCH_REQUIRE(m.call());
249 1 : CATCH_REQUIRE(g_called);
250 1 : }
251 4 : CATCH_END_SECTION()
252 :
253 4 : CATCH_START_SECTION("callback manager: std::bind() function")
254 : {
255 : class bind
256 : {
257 : public:
258 : typedef std::set<bind> set_t;
259 :
260 1 : bool my_callback(int param)
261 : {
262 1 : g_expected = param;
263 :
264 1 : return true;
265 : }
266 :
267 : int g_expected = -1;
268 : };
269 :
270 1 : bind b;
271 :
272 1 : auto f(std::bind(&bind::my_callback, &b, 111));
273 :
274 1 : snapdev::callback_manager<decltype(f)> m;
275 :
276 1 : auto const id(m.add_callback(f));
277 :
278 1 : CATCH_REQUIRE(m.call());
279 :
280 1 : CATCH_REQUIRE_FALSE(m.empty());
281 1 : CATCH_REQUIRE(m.remove_callback(id));
282 1 : CATCH_REQUIRE(m.empty());
283 1 : }
284 4 : CATCH_END_SECTION()
285 4 : }
286 :
287 :
288 :
289 : // vim: ts=4 sw=4 et
|