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