Line data Source code
1 : // Copyright (c) 2016-2024 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/cluck
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 : // self
20 : //
21 : #include "catch_main.h"
22 :
23 :
24 :
25 : // cluckd
26 : //
27 : #include <daemon/cluckd.h>
28 :
29 :
30 : // cluck
31 : //
32 : #include <cluck/exception.h>
33 :
34 :
35 : // eventdispatcher
36 : //
37 : #include <eventdispatcher/reporter/executor.h>
38 : #include <eventdispatcher/reporter/parser.h>
39 : #include <eventdispatcher/reporter/variable_integer.h>
40 :
41 :
42 : // snapdev
43 : //
44 : #include <snapdev/gethostname.h>
45 :
46 :
47 : // advgetopt
48 : //
49 : #include <advgetopt/exception.h>
50 :
51 :
52 : // last include
53 : //
54 : #include <snapdev/poison.h>
55 :
56 :
57 :
58 : namespace
59 : {
60 :
61 :
62 :
63 16 : addr::addr get_address()
64 : {
65 16 : addr::addr a;
66 16 : sockaddr_in ip = {
67 : .sin_family = AF_INET,
68 16 : .sin_port = htons(20002),
69 : .sin_addr = {
70 16 : .s_addr = htonl(0x7f000001),
71 : },
72 : .sin_zero = {},
73 16 : };
74 16 : a.set_ipv4(ip);
75 32 : return a;
76 0 : }
77 :
78 :
79 :
80 : } // no name namespace
81 :
82 :
83 :
84 1 : CATCH_TEST_CASE("cluck_daemon_one_computer", "[cluckd][daemon]")
85 : {
86 3 : CATCH_START_SECTION("cluck_daemon_one_computer: verify cluckd")
87 : {
88 1 : addr::addr a(get_address());
89 :
90 1 : std::vector<std::string> const args = {
91 : "cluckd", // name of command
92 : "--communicatord-listen",
93 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
94 : "--path-to-message-definitions",
95 :
96 : // WARNING: the order matters, we want to test with our source
97 : // (i.e. original) files first
98 : //
99 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
100 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
101 13 : };
102 :
103 : // convert arguments
104 : //
105 1 : std::vector<char const *> args_strings;
106 1 : args_strings.reserve(args.size() + 1);
107 6 : for(auto const & arg : args)
108 : {
109 5 : args_strings.push_back(arg.c_str());
110 : }
111 1 : args_strings.push_back(nullptr); // NULL terminated
112 :
113 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
114 1 : lock->add_connections();
115 :
116 : // no elections happened, 'lock' is not a leader
117 : //
118 1 : CATCH_REQUIRE(lock->is_leader() == nullptr);
119 1 : CATCH_REQUIRE_THROWS_MATCHES(
120 : lock->get_leader_a()
121 : , cluck::logic_error
122 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
123 1 : CATCH_REQUIRE_THROWS_MATCHES(
124 : lock->get_leader_b()
125 : , cluck::logic_error
126 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
127 :
128 : // messenger is not yet connected, it's not ready
129 : //
130 1 : CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
131 :
132 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
133 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_one_computer.rprtr");
134 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
135 1 : CATCH_REQUIRE(l != nullptr);
136 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
137 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
138 1 : p->parse_program();
139 :
140 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
141 1 : e->start();
142 :
143 1 : e->set_thread_done_callback([lock]()
144 : {
145 1 : lock->stop(true);
146 1 : });
147 :
148 : try
149 : {
150 1 : lock->run();
151 : }
152 0 : catch(std::exception const & ex)
153 : {
154 0 : SNAP_LOG_FATAL
155 : << "an exception occurred while running cluckd (1 cluckd): "
156 : << ex
157 : << SNAP_LOG_SEND;
158 :
159 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
160 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
161 : {
162 0 : SNAP_LOG_FATAL
163 : << " "
164 : << line
165 : << SNAP_LOG_SEND;
166 : }
167 :
168 0 : throw;
169 0 : }
170 :
171 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
172 1 : }
173 2 : CATCH_END_SECTION()
174 1 : }
175 :
176 :
177 1 : CATCH_TEST_CASE("cluck_daemon_two_computers", "[cluckd][daemon]")
178 : {
179 3 : CATCH_START_SECTION("cluck_daemon_two_computers: verify cluckd")
180 : {
181 1 : addr::addr a(get_address());
182 :
183 1 : std::vector<std::string> const args = {
184 : "cluckd", // name of command
185 : "--communicatord-listen",
186 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
187 : "--path-to-message-definitions",
188 :
189 : // WARNING: the order matters, we want to test with our source
190 : // (i.e. original) files first
191 : //
192 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
193 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
194 :
195 : "--server-name",
196 : snapdev::gethostname(),
197 : "--candidate-priority",
198 : "10",
199 20 : };
200 :
201 : // convert arguments
202 : //
203 1 : std::vector<char const *> args_strings;
204 1 : args_strings.reserve(args.size() + 1);
205 10 : for(auto const & arg : args)
206 : {
207 9 : args_strings.push_back(arg.c_str());
208 : }
209 1 : args_strings.push_back(nullptr); // NULL terminated
210 :
211 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
212 1 : lock->add_connections();
213 :
214 : // no elections happened, 'lock' is not a leader
215 : //
216 1 : CATCH_REQUIRE(lock->is_leader() == nullptr);
217 1 : CATCH_REQUIRE_THROWS_MATCHES(
218 : lock->get_leader_a()
219 : , cluck::logic_error
220 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
221 1 : CATCH_REQUIRE_THROWS_MATCHES(
222 : lock->get_leader_b()
223 : , cluck::logic_error
224 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
225 :
226 : // messenger is not yet connected, it's not ready
227 : //
228 1 : CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
229 :
230 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
231 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_two_computers.rprtr");
232 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
233 1 : CATCH_REQUIRE(l != nullptr);
234 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
235 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
236 1 : p->parse_program();
237 :
238 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
239 1 : e->start();
240 :
241 1 : e->set_thread_done_callback([lock]()
242 : {
243 1 : lock->stop(true);
244 1 : });
245 :
246 : try
247 : {
248 1 : lock->run();
249 : }
250 0 : catch(std::exception const & ex)
251 : {
252 0 : SNAP_LOG_FATAL
253 : << "an exception occurred while running cluckd (2 cluckd): "
254 : << ex
255 : << SNAP_LOG_SEND;
256 :
257 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
258 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
259 : {
260 0 : SNAP_LOG_FATAL
261 : << " "
262 : << line
263 : << SNAP_LOG_SEND;
264 : }
265 :
266 0 : throw;
267 0 : }
268 :
269 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
270 1 : }
271 2 : CATCH_END_SECTION()
272 1 : }
273 :
274 :
275 1 : CATCH_TEST_CASE("cluck_daemon_three_computers", "[cluckd][daemon]")
276 : {
277 3 : CATCH_START_SECTION("cluck_daemon_three_computers: verify cluckd")
278 : {
279 1 : addr::addr a(get_address());
280 :
281 1 : std::vector<std::string> const args = {
282 : "cluckd", // name of command
283 : "--communicatord-listen",
284 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
285 : "--path-to-message-definitions",
286 :
287 : // WARNING: the order matters, we want to test with our source
288 : // (i.e. original) files first
289 : //
290 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
291 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
292 13 : };
293 :
294 : // convert arguments
295 : //
296 1 : std::vector<char const *> args_strings;
297 1 : args_strings.reserve(args.size() + 1);
298 6 : for(auto const & arg : args)
299 : {
300 5 : args_strings.push_back(arg.c_str());
301 : }
302 1 : args_strings.push_back(nullptr); // NULL terminated
303 :
304 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
305 1 : lock->add_connections();
306 :
307 : // no elections happened, 'lock' is not a leader
308 : //
309 1 : CATCH_REQUIRE(lock->is_leader() == nullptr);
310 1 : CATCH_REQUIRE_THROWS_MATCHES(
311 : lock->get_leader_a()
312 : , cluck::logic_error
313 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
314 1 : CATCH_REQUIRE_THROWS_MATCHES(
315 : lock->get_leader_b()
316 : , cluck::logic_error
317 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
318 :
319 : // messenger is not yet connected, it's not ready
320 : //
321 1 : CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
322 :
323 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
324 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_three_computers.rprtr");
325 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
326 1 : CATCH_REQUIRE(l != nullptr);
327 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
328 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
329 1 : p->parse_program();
330 :
331 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
332 1 : e->start();
333 :
334 1 : e->set_thread_done_callback([lock]()
335 : {
336 1 : lock->stop(true);
337 1 : });
338 :
339 : try
340 : {
341 1 : lock->run();
342 : }
343 0 : catch(std::exception const & ex)
344 : {
345 0 : SNAP_LOG_FATAL
346 : << "an exception occurred while running cluckd (3 cluckd): "
347 : << ex
348 : << SNAP_LOG_SEND;
349 :
350 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
351 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
352 : {
353 0 : SNAP_LOG_FATAL
354 : << " "
355 : << line
356 : << SNAP_LOG_SEND;
357 : }
358 :
359 0 : throw;
360 0 : }
361 :
362 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
363 1 : }
364 2 : CATCH_END_SECTION()
365 1 : }
366 :
367 :
368 1 : CATCH_TEST_CASE("cluck_daemon_four_computers", "[cluckd][daemon]")
369 : {
370 3 : CATCH_START_SECTION("cluck_daemon_four_computers: verify cluckd")
371 : {
372 1 : addr::addr a(get_address());
373 :
374 1 : std::vector<std::string> const args = {
375 : "cluckd", // name of command
376 : "--communicatord-listen",
377 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
378 : "--path-to-message-definitions",
379 :
380 : // WARNING: the order matters, we want to test with our source
381 : // (i.e. original) files first
382 : //
383 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
384 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
385 13 : };
386 :
387 : // convert arguments
388 : //
389 1 : std::vector<char const *> args_strings;
390 1 : args_strings.reserve(args.size() + 1);
391 6 : for(auto const & arg : args)
392 : {
393 5 : args_strings.push_back(arg.c_str());
394 : }
395 1 : args_strings.push_back(nullptr); // NULL terminated
396 :
397 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
398 1 : lock->add_connections();
399 :
400 : // no elections happened, 'lock' is not a leader
401 : //
402 1 : CATCH_REQUIRE(lock->is_leader() == nullptr);
403 1 : CATCH_REQUIRE_THROWS_MATCHES(
404 : lock->get_leader_a()
405 : , cluck::logic_error
406 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
407 1 : CATCH_REQUIRE_THROWS_MATCHES(
408 : lock->get_leader_b()
409 : , cluck::logic_error
410 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
411 :
412 : // messenger is not yet connected, it's not ready
413 : //
414 1 : CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
415 :
416 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
417 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_four_computers.rprtr");
418 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
419 1 : CATCH_REQUIRE(l != nullptr);
420 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
421 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
422 1 : p->parse_program();
423 :
424 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
425 1 : e->start();
426 :
427 1 : e->set_thread_done_callback([lock]()
428 : {
429 1 : lock->stop(true);
430 1 : });
431 :
432 : try
433 : {
434 1 : lock->run();
435 : }
436 0 : catch(std::exception const & ex)
437 : {
438 0 : SNAP_LOG_FATAL
439 : << "an exception occurred while running cluckd (4 cluckd): "
440 : << ex
441 : << SNAP_LOG_SEND;
442 :
443 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
444 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
445 : {
446 0 : SNAP_LOG_FATAL
447 : << " "
448 : << line
449 : << SNAP_LOG_SEND;
450 : }
451 :
452 0 : throw;
453 0 : }
454 :
455 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
456 1 : }
457 2 : CATCH_END_SECTION()
458 1 : }
459 :
460 :
461 1 : CATCH_TEST_CASE("cluck_daemon_ten_computers", "[cluckd][daemon]")
462 : {
463 3 : CATCH_START_SECTION("cluck_daemon_ten_computers: verify cluckd")
464 : {
465 1 : addr::addr a(get_address());
466 :
467 1 : std::vector<std::string> const args = {
468 : "cluckd", // name of command
469 : "--communicatord-listen",
470 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
471 : "--candidate-priority",
472 : "5",
473 : "--path-to-message-definitions",
474 :
475 : // WARNING: the order matters, we want to test with our source
476 : // (i.e. original) files first
477 : //
478 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
479 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
480 17 : };
481 :
482 : // convert arguments
483 : //
484 1 : std::vector<char const *> args_strings;
485 1 : args_strings.reserve(args.size() + 1);
486 8 : for(auto const & arg : args)
487 : {
488 7 : args_strings.push_back(arg.c_str());
489 : }
490 1 : args_strings.push_back(nullptr); // NULL terminated
491 :
492 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
493 1 : lock->add_connections();
494 :
495 : // no elections happened, 'lock' is not a leader
496 : //
497 1 : CATCH_REQUIRE(lock->is_leader() == nullptr);
498 1 : CATCH_REQUIRE_THROWS_MATCHES(
499 : lock->get_leader_a()
500 : , cluck::logic_error
501 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
502 1 : CATCH_REQUIRE_THROWS_MATCHES(
503 : lock->get_leader_b()
504 : , cluck::logic_error
505 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
506 :
507 : // messenger is not yet connected, it's not ready
508 : //
509 1 : CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
510 :
511 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
512 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_ten_computers.rprtr");
513 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
514 1 : CATCH_REQUIRE(l != nullptr);
515 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
516 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
517 1 : p->parse_program();
518 :
519 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
520 1 : e->start();
521 :
522 1 : e->set_thread_done_callback([lock]()
523 : {
524 1 : lock->stop(true);
525 1 : });
526 :
527 : try
528 : {
529 1 : lock->run();
530 : }
531 0 : catch(std::exception const & ex)
532 : {
533 0 : SNAP_LOG_FATAL
534 : << "an exception occurred while running cluckd (10 cluckd): "
535 : << ex
536 : << SNAP_LOG_SEND;
537 :
538 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
539 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
540 : {
541 0 : SNAP_LOG_FATAL
542 : << " "
543 : << line
544 : << SNAP_LOG_SEND;
545 : }
546 :
547 0 : throw;
548 0 : }
549 :
550 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
551 1 : }
552 2 : CATCH_END_SECTION()
553 1 : }
554 :
555 :
556 1 : CATCH_TEST_CASE("cluck_daemon_lock_tickets", "[cluckd][daemon]")
557 : {
558 3 : CATCH_START_SECTION("cluck_daemon_lock_tickets: verify cluckd")
559 : {
560 1 : addr::addr a(get_address());
561 :
562 1 : std::vector<std::string> const args = {
563 : "cluckd", // name of command
564 : "--communicatord-listen",
565 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
566 : "--candidate-priority",
567 : "2",
568 : "--path-to-message-definitions",
569 :
570 : // WARNING: the order matters, we want to test with our source
571 : // (i.e. original) files first
572 : //
573 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
574 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
575 17 : };
576 :
577 : // convert arguments
578 : //
579 1 : std::vector<char const *> args_strings;
580 1 : args_strings.reserve(args.size() + 1);
581 8 : for(auto const & arg : args)
582 : {
583 7 : args_strings.push_back(arg.c_str());
584 : }
585 1 : args_strings.push_back(nullptr); // NULL terminated
586 :
587 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
588 1 : lock->add_connections();
589 :
590 : // no elections happened, 'lock' is not a leader
591 : //
592 1 : CATCH_REQUIRE(lock->is_leader() == nullptr);
593 1 : CATCH_REQUIRE_THROWS_MATCHES(
594 : lock->get_leader_a()
595 : , cluck::logic_error
596 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
597 1 : CATCH_REQUIRE_THROWS_MATCHES(
598 : lock->get_leader_b()
599 : , cluck::logic_error
600 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
601 :
602 : // messenger is not yet connected, it's not ready
603 : //
604 1 : CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
605 :
606 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
607 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_lock_tickets.rprtr");
608 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
609 1 : CATCH_REQUIRE(l != nullptr);
610 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
611 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
612 1 : p->parse_program();
613 :
614 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
615 1 : e->start();
616 :
617 1 : e->set_thread_done_callback([lock]()
618 : {
619 1 : lock->stop(true);
620 1 : });
621 :
622 : try
623 : {
624 1 : lock->run();
625 : }
626 0 : catch(std::exception const & ex)
627 : {
628 0 : SNAP_LOG_FATAL
629 : << "an exception occurred while running cluckd (10 cluckd): "
630 : << ex
631 : << SNAP_LOG_SEND;
632 :
633 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
634 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
635 : {
636 0 : SNAP_LOG_FATAL
637 : << " "
638 : << line
639 : << SNAP_LOG_SEND;
640 : }
641 :
642 0 : throw;
643 0 : }
644 :
645 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
646 1 : }
647 2 : CATCH_END_SECTION()
648 1 : }
649 :
650 :
651 3 : CATCH_TEST_CASE("cluck_daemon_specialized_tests", "[cluckd][daemon]")
652 : {
653 5 : CATCH_START_SECTION("cluck_daemon_specialized_tests: verify early LOCK_LEADERS")
654 : {
655 1 : addr::addr a(get_address());
656 :
657 1 : std::vector<std::string> const args = {
658 : "cluckd", // name of command
659 : "--communicatord-listen",
660 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
661 : "--path-to-message-definitions",
662 :
663 : // WARNING: the order matters, we want to test with our source
664 : // (i.e. original) files first
665 : //
666 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
667 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
668 13 : };
669 :
670 : // convert arguments
671 : //
672 1 : std::vector<char const *> args_strings;
673 1 : args_strings.reserve(args.size() + 1);
674 6 : for(auto const & arg : args)
675 : {
676 5 : args_strings.push_back(arg.c_str());
677 : }
678 1 : args_strings.push_back(nullptr); // NULL terminated
679 :
680 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
681 1 : lock->add_connections();
682 :
683 : // no elections happened, 'lock' is not a leader
684 : //
685 1 : CATCH_REQUIRE(lock->is_leader() == nullptr);
686 1 : CATCH_REQUIRE_THROWS_MATCHES(
687 : lock->get_leader_a()
688 : , cluck::logic_error
689 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
690 1 : CATCH_REQUIRE_THROWS_MATCHES(
691 : lock->get_leader_b()
692 : , cluck::logic_error
693 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
694 :
695 : // messenger is not yet connected, it's not ready
696 : //
697 1 : CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
698 :
699 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
700 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_early_lock_leaders.rprtr");
701 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
702 1 : CATCH_REQUIRE(l != nullptr);
703 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
704 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
705 1 : p->parse_program();
706 :
707 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
708 1 : e->start();
709 :
710 1 : e->set_thread_done_callback([lock]()
711 : {
712 1 : lock->stop(true);
713 1 : });
714 :
715 : try
716 : {
717 1 : lock->run();
718 : }
719 0 : catch(std::exception const & ex)
720 : {
721 0 : SNAP_LOG_FATAL
722 : << "an exception occurred while running cluckd (3 cluckd): "
723 : << ex
724 : << SNAP_LOG_SEND;
725 :
726 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
727 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
728 : {
729 0 : SNAP_LOG_FATAL
730 : << " "
731 : << line
732 : << SNAP_LOG_SEND;
733 : }
734 :
735 0 : throw;
736 0 : }
737 :
738 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
739 1 : }
740 4 : CATCH_END_SECTION()
741 :
742 5 : CATCH_START_SECTION("cluck_daemon_specialized_tests: verify forwarded (off)")
743 : {
744 1 : addr::addr a(get_address());
745 :
746 1 : std::vector<std::string> const args = {
747 : "cluckd", // name of command
748 : "--communicatord-listen",
749 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
750 : "--candidate-priority",
751 : "off",
752 : "--path-to-message-definitions",
753 :
754 : // WARNING: the order matters, we want to test with our source
755 : // (i.e. original) files first
756 : //
757 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
758 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
759 17 : };
760 :
761 : // convert arguments
762 : //
763 1 : std::vector<char const *> args_strings;
764 1 : args_strings.reserve(args.size() + 1);
765 8 : for(auto const & arg : args)
766 : {
767 7 : args_strings.push_back(arg.c_str());
768 : }
769 1 : args_strings.push_back(nullptr); // NULL terminated
770 :
771 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
772 1 : lock->add_connections();
773 :
774 : // no elections happened, 'lock' is not a leader
775 : //
776 1 : CATCH_REQUIRE(lock->is_leader() == nullptr);
777 1 : CATCH_REQUIRE_THROWS_MATCHES(
778 : lock->get_leader_a()
779 : , cluck::logic_error
780 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
781 1 : CATCH_REQUIRE_THROWS_MATCHES(
782 : lock->get_leader_b()
783 : , cluck::logic_error
784 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
785 :
786 : // messenger is not yet connected, it's not ready
787 : //
788 1 : CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
789 :
790 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
791 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_forwarder.rprtr");
792 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
793 1 : CATCH_REQUIRE(l != nullptr);
794 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
795 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
796 1 : p->parse_program();
797 :
798 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
799 1 : e->start();
800 :
801 1 : e->set_thread_done_callback([lock]()
802 : {
803 1 : lock->stop(true);
804 1 : });
805 :
806 : try
807 : {
808 1 : lock->run();
809 : }
810 0 : catch(std::exception const & ex)
811 : {
812 0 : SNAP_LOG_FATAL
813 : << "an exception occurred while running cluckd (3 cluckd): "
814 : << ex
815 : << SNAP_LOG_SEND;
816 :
817 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
818 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
819 : {
820 0 : SNAP_LOG_FATAL
821 : << " "
822 : << line
823 : << SNAP_LOG_SEND;
824 : }
825 :
826 0 : throw;
827 0 : }
828 :
829 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
830 1 : }
831 4 : CATCH_END_SECTION()
832 :
833 5 : CATCH_START_SECTION("cluck_daemon_specialized_tests: try an interrupt to stop the cluck daemon")
834 : {
835 1 : addr::addr a(get_address());
836 :
837 1 : std::vector<std::string> const args = {
838 : "cluckd", // name of command
839 : "--communicatord-listen",
840 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
841 : "--path-to-message-definitions",
842 :
843 : // WARNING: the order matters, we want to test with our source
844 : // (i.e. original) files first
845 : //
846 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
847 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
848 13 : };
849 :
850 : // convert arguments
851 : //
852 1 : std::vector<char const *> args_strings;
853 1 : args_strings.reserve(args.size() + 1);
854 6 : for(auto const & arg : args)
855 : {
856 5 : args_strings.push_back(arg.c_str());
857 : }
858 1 : args_strings.push_back(nullptr); // NULL terminated
859 :
860 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
861 1 : lock->add_connections();
862 :
863 : // no elections happened, 'lock' is not a leader
864 : //
865 1 : CATCH_REQUIRE(lock->is_leader() == nullptr);
866 1 : CATCH_REQUIRE_THROWS_MATCHES(
867 : lock->get_leader_a()
868 : , cluck::logic_error
869 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_a(): only a leader can call this function."));
870 1 : CATCH_REQUIRE_THROWS_MATCHES(
871 : lock->get_leader_b()
872 : , cluck::logic_error
873 : , Catch::Matchers::ExceptionMessage("logic_error: cluckd::get_leader_b(): only a leader can call this function."));
874 :
875 : // messenger is not yet connected, it's not ready
876 : //
877 1 : CATCH_REQUIRE_FALSE(lock->is_daemon_ready());
878 :
879 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
880 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_interrupt_signal.rprtr");
881 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
882 1 : CATCH_REQUIRE(l != nullptr);
883 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
884 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
885 1 : p->parse_program();
886 :
887 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
888 1 : e->start();
889 :
890 1 : e->set_thread_done_callback([lock]()
891 : {
892 1 : lock->stop(true);
893 1 : });
894 :
895 : try
896 : {
897 1 : lock->run();
898 : }
899 0 : catch(std::exception const & ex)
900 : {
901 0 : SNAP_LOG_FATAL
902 : << "an exception occurred while running cluckd (interrupt signal): "
903 : << ex
904 : << SNAP_LOG_SEND;
905 :
906 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
907 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
908 : {
909 0 : SNAP_LOG_FATAL
910 : << " "
911 : << line
912 : << SNAP_LOG_SEND;
913 : }
914 :
915 0 : throw;
916 0 : }
917 :
918 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
919 1 : }
920 4 : CATCH_END_SECTION()
921 3 : }
922 :
923 :
924 4 : CATCH_TEST_CASE("cluck_daemon_failures", "[cluckd][daemon][fail]")
925 : {
926 6 : CATCH_START_SECTION("cluck_daemon_failures: entering too slowly")
927 : {
928 1 : addr::addr a(get_address());
929 :
930 1 : std::vector<std::string> const args = {
931 : "cluckd", // name of command
932 : "--communicatord-listen",
933 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
934 : "--path-to-message-definitions",
935 :
936 : // WARNING: the order matters, we want to test with our source
937 : // (i.e. original) files first
938 : //
939 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
940 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
941 13 : };
942 :
943 : // convert arguments
944 : //
945 1 : std::vector<char const *> args_strings;
946 1 : args_strings.reserve(args.size() + 1);
947 6 : for(auto const & arg : args)
948 : {
949 5 : args_strings.push_back(arg.c_str());
950 : }
951 1 : args_strings.push_back(nullptr); // NULL terminated
952 :
953 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
954 1 : lock->add_connections();
955 :
956 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
957 1 : std::string const filename(source_dir + "/tests/rprtr/failed_with_timing_out_entering.rprtr");
958 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
959 1 : CATCH_REQUIRE(l != nullptr);
960 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
961 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
962 1 : p->parse_program();
963 :
964 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
965 1 : e->start();
966 :
967 1 : e->set_thread_done_callback([lock]()
968 : {
969 1 : lock->stop(true);
970 1 : });
971 :
972 : try
973 : {
974 1 : lock->run();
975 : }
976 0 : catch(std::exception const & ex)
977 : {
978 0 : SNAP_LOG_FATAL
979 : << "an exception occurred while running cluckd (entering timing out): "
980 : << ex
981 : << SNAP_LOG_SEND;
982 :
983 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
984 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
985 : {
986 0 : SNAP_LOG_FATAL
987 : << " "
988 : << line
989 : << SNAP_LOG_SEND;
990 : }
991 :
992 0 : throw;
993 0 : }
994 :
995 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
996 1 : }
997 5 : CATCH_END_SECTION()
998 :
999 6 : CATCH_START_SECTION("cluck_daemon_failures: cache timeout")
1000 : {
1001 1 : addr::addr a(get_address());
1002 :
1003 1 : std::vector<std::string> const args = {
1004 : "cluckd", // name of command
1005 : "--communicatord-listen",
1006 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
1007 : "--path-to-message-definitions",
1008 :
1009 : // WARNING: the order matters, we want to test with our source
1010 : // (i.e. original) files first
1011 : //
1012 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
1013 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
1014 13 : };
1015 :
1016 : // convert arguments
1017 : //
1018 1 : std::vector<char const *> args_strings;
1019 1 : args_strings.reserve(args.size() + 1);
1020 6 : for(auto const & arg : args)
1021 : {
1022 5 : args_strings.push_back(arg.c_str());
1023 : }
1024 1 : args_strings.push_back(nullptr); // NULL terminated
1025 :
1026 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
1027 1 : lock->add_connections();
1028 :
1029 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
1030 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_cache_timeout.rprtr");
1031 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
1032 1 : CATCH_REQUIRE(l != nullptr);
1033 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1034 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1035 1 : p->parse_program();
1036 :
1037 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1038 1 : e->start();
1039 :
1040 1 : e->set_thread_done_callback([lock]()
1041 : {
1042 1 : lock->stop(true);
1043 1 : });
1044 :
1045 : try
1046 : {
1047 1 : lock->run();
1048 : }
1049 0 : catch(std::exception const & ex)
1050 : {
1051 0 : SNAP_LOG_FATAL
1052 : << "an exception occurred while running cluckd (entering timing out): "
1053 : << ex
1054 : << SNAP_LOG_SEND;
1055 :
1056 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
1057 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
1058 : {
1059 0 : SNAP_LOG_FATAL
1060 : << " "
1061 : << line
1062 : << SNAP_LOG_SEND;
1063 : }
1064 :
1065 0 : throw;
1066 0 : }
1067 :
1068 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
1069 1 : }
1070 5 : CATCH_END_SECTION()
1071 :
1072 6 : CATCH_START_SECTION("cluck_daemon_failures: too many locks")
1073 : {
1074 1 : addr::addr a(get_address());
1075 :
1076 1 : cluck::timeout_t const default_obtention_timeout(cluck::get_lock_obtention_timeout());
1077 1 : cluck::set_lock_obtention_timeout(cluck::timeout_t(120, 0));
1078 :
1079 1 : std::vector<std::string> const args = {
1080 : "cluckd", // name of command
1081 : "--communicatord-listen",
1082 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
1083 : "--candidate-priority",
1084 : "10",
1085 : "--path-to-message-definitions",
1086 :
1087 : // WARNING: the order matters, we want to test with our source
1088 : // (i.e. original) files first
1089 : //
1090 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
1091 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
1092 17 : };
1093 :
1094 : // convert arguments
1095 : //
1096 1 : std::vector<char const *> args_strings;
1097 1 : args_strings.reserve(args.size() + 1);
1098 8 : for(auto const & arg : args)
1099 : {
1100 7 : args_strings.push_back(arg.c_str());
1101 : }
1102 1 : args_strings.push_back(nullptr); // NULL terminated
1103 :
1104 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
1105 1 : lock->add_connections();
1106 :
1107 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
1108 1 : std::string const filename(source_dir + "/tests/rprtr/failed_with_too_many_locks.rprtr");
1109 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
1110 1 : CATCH_REQUIRE(l != nullptr);
1111 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1112 1 : SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t var(
1113 : std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(
1114 1 : "cluck_maximum_entering_locks"));
1115 1 : var->set_integer(cluck::CLUCK_MAXIMUM_ENTERING_LOCKS);
1116 1 : s->set_variable(var);
1117 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1118 1 : p->parse_program();
1119 :
1120 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1121 1 : e->start();
1122 :
1123 1 : e->set_thread_done_callback([lock]()
1124 : {
1125 1 : lock->stop(true);
1126 1 : });
1127 :
1128 : try
1129 : {
1130 1 : lock->run();
1131 : }
1132 0 : catch(std::exception const & ex)
1133 : {
1134 0 : SNAP_LOG_FATAL
1135 : << "an exception occurred while running cluckd (entering timing out): "
1136 : << ex
1137 : << SNAP_LOG_SEND;
1138 :
1139 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
1140 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
1141 : {
1142 0 : SNAP_LOG_FATAL
1143 : << " "
1144 : << line
1145 : << SNAP_LOG_SEND;
1146 : }
1147 :
1148 0 : throw;
1149 0 : }
1150 :
1151 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
1152 :
1153 1 : cluck::set_lock_obtention_timeout(default_obtention_timeout);
1154 1 : }
1155 5 : CATCH_END_SECTION()
1156 :
1157 6 : CATCH_START_SECTION("cluck_daemon_failures: send a DROP_TICKET to cancel an entering LOCK")
1158 : {
1159 1 : addr::addr a(get_address());
1160 :
1161 1 : std::vector<std::string> const args = {
1162 : "cluckd", // name of command
1163 : "--candidate-priority",
1164 : "10",
1165 : "--communicatord-listen",
1166 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
1167 : "--path-to-message-definitions",
1168 :
1169 : // WARNING: the order matters, we want to test with our source
1170 : // (i.e. original) files first
1171 : //
1172 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
1173 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
1174 :
1175 : "--server-name",
1176 : snapdev::gethostname(),
1177 20 : };
1178 :
1179 : // convert arguments
1180 : //
1181 1 : std::vector<char const *> args_strings;
1182 1 : args_strings.reserve(args.size() + 1);
1183 10 : for(auto const & arg : args)
1184 : {
1185 9 : args_strings.push_back(arg.c_str());
1186 : }
1187 1 : args_strings.push_back(nullptr); // NULL terminated
1188 :
1189 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
1190 1 : lock->add_connections();
1191 :
1192 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
1193 1 : std::string const filename(source_dir + "/tests/rprtr/drop_entering_ticket.rprtr");
1194 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
1195 1 : CATCH_REQUIRE(l != nullptr);
1196 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1197 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1198 1 : p->parse_program();
1199 :
1200 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1201 1 : e->start();
1202 :
1203 1 : e->set_thread_done_callback([lock]()
1204 : {
1205 1 : lock->stop(true);
1206 1 : });
1207 :
1208 : try
1209 : {
1210 1 : lock->run();
1211 : }
1212 0 : catch(std::exception const & ex)
1213 : {
1214 0 : SNAP_LOG_FATAL
1215 : << "an exception occurred while running cluckd (get max ticket overflow): "
1216 : << ex
1217 : << SNAP_LOG_SEND;
1218 :
1219 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
1220 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
1221 : {
1222 0 : SNAP_LOG_FATAL
1223 : << " "
1224 : << line
1225 : << SNAP_LOG_SEND;
1226 : }
1227 :
1228 0 : throw;
1229 0 : }
1230 :
1231 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
1232 1 : }
1233 5 : CATCH_END_SECTION()
1234 4 : }
1235 :
1236 :
1237 6 : CATCH_TEST_CASE("cluck_daemon_errors", "[cluckd][daemon][error]")
1238 : {
1239 8 : CATCH_START_SECTION("cluck_daemon_errors: invalid logger parameter")
1240 : {
1241 1 : SNAP_CATCH2_NAMESPACE::reset_log_errors safe_counters;
1242 1 : char const * const args[] = {
1243 : "cluckd", // name of command
1244 : "--log-severity",
1245 : "unknown-severity-name",
1246 : nullptr
1247 : };
1248 :
1249 3 : CATCH_REQUIRE_THROWS_MATCHES(
1250 : std::make_shared<cluck_daemon::cluckd>(3, const_cast<char **>(args))
1251 : , advgetopt::getopt_exit
1252 : , Catch::Matchers::ExceptionMessage("getopt_exception: logger options generated an error."));
1253 1 : }
1254 7 : CATCH_END_SECTION()
1255 :
1256 8 : CATCH_START_SECTION("cluck_daemon_errors: standalone command line options are not allowed")
1257 : {
1258 1 : SNAP_CATCH2_NAMESPACE::reset_log_errors safe_counters;
1259 1 : char const * const args[] = {
1260 : "cluckd", // name of command
1261 : "filename",
1262 : nullptr
1263 : };
1264 :
1265 3 : CATCH_REQUIRE_THROWS_MATCHES(
1266 : std::make_shared<cluck_daemon::cluckd>(2, const_cast<char **>(args))
1267 : , advgetopt::getopt_exit
1268 : , Catch::Matchers::ExceptionMessage("getopt_exception: errors were found on your command line, environment variable, or configuration file."));
1269 1 : }
1270 7 : CATCH_END_SECTION()
1271 :
1272 8 : CATCH_START_SECTION("cluck_daemon_errors: double severity")
1273 : {
1274 1 : SNAP_CATCH2_NAMESPACE::reset_log_errors safe_counters;
1275 1 : char const * const args[] = {
1276 : "cluckd", // name of command
1277 : "--log-severity",
1278 : "INFO",
1279 : "ERROR", // oops, the log severity level "leaked"
1280 : nullptr
1281 : };
1282 :
1283 3 : CATCH_REQUIRE_THROWS_MATCHES(
1284 : std::make_shared<cluck_daemon::cluckd>(4, const_cast<char **>(args))
1285 : , advgetopt::getopt_exit
1286 : , Catch::Matchers::ExceptionMessage("getopt_exception: errors were found on your command line, environment variable, or configuration file."));
1287 1 : }
1288 7 : CATCH_END_SECTION()
1289 :
1290 8 : CATCH_START_SECTION("cluck_daemon_errors: get max ticket overflow")
1291 : {
1292 1 : addr::addr a(get_address());
1293 :
1294 1 : std::vector<std::string> const args = {
1295 : "cluckd", // name of command
1296 : "--candidate-priority",
1297 : "10",
1298 : "--communicatord-listen",
1299 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
1300 : "--path-to-message-definitions",
1301 :
1302 : // WARNING: the order matters, we want to test with our source
1303 : // (i.e. original) files first
1304 : //
1305 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
1306 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
1307 17 : };
1308 :
1309 : // convert arguments
1310 : //
1311 1 : std::vector<char const *> args_strings;
1312 1 : args_strings.reserve(args.size() + 1);
1313 8 : for(auto const & arg : args)
1314 : {
1315 7 : args_strings.push_back(arg.c_str());
1316 : }
1317 1 : args_strings.push_back(nullptr); // NULL terminated
1318 :
1319 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
1320 1 : lock->add_connections();
1321 :
1322 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
1323 1 : std::string const filename(source_dir + "/tests/rprtr/failed_with_max_ticket_too_large.rprtr");
1324 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
1325 1 : CATCH_REQUIRE(l != nullptr);
1326 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1327 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1328 1 : p->parse_program();
1329 :
1330 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1331 1 : e->start();
1332 :
1333 1 : e->set_thread_done_callback([lock]()
1334 : {
1335 1 : lock->stop(true);
1336 1 : });
1337 :
1338 : try
1339 : {
1340 1 : lock->run();
1341 : }
1342 1 : catch(cluck::out_of_range const & ex)
1343 : {
1344 1 : SNAP_LOG_INFO
1345 : << "got the expected exception: "
1346 : << ex
1347 : << SNAP_LOG_SEND;
1348 :
1349 2 : std::string const expected("out_of_range: ticket::max_ticket() tried to generate the next ticket and got a wrapping around number.");
1350 1 : CATCH_REQUIRE(ex.what() == expected);
1351 :
1352 : // the communicator daemon may still have connections because of
1353 : // the exception
1354 : //
1355 2 : ed::connection::vector_t connections(ed::communicator::instance()->get_connections());
1356 1 : for(auto c : connections)
1357 : {
1358 0 : ed::communicator::instance()->remove_connection(c);
1359 0 : }
1360 2 : }
1361 0 : catch(std::exception const & ex)
1362 : {
1363 0 : SNAP_LOG_FATAL
1364 : << "an exception occurred while running cluckd (get max ticket overflow): "
1365 : << ex
1366 : << SNAP_LOG_SEND;
1367 :
1368 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
1369 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
1370 : {
1371 0 : SNAP_LOG_FATAL
1372 : << " "
1373 : << line
1374 : << SNAP_LOG_SEND;
1375 : }
1376 :
1377 0 : throw;
1378 0 : }
1379 :
1380 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
1381 1 : }
1382 7 : CATCH_END_SECTION()
1383 :
1384 8 : CATCH_START_SECTION("cluck_daemon_errors: too many computers are off")
1385 : {
1386 1 : addr::addr a(get_address());
1387 :
1388 5 : for(int version(1); version <= 4; ++version)
1389 : {
1390 14 : for(int off_mask(1); off_mask < (version == 4 ? 8 : 2); ++off_mask)
1391 : {
1392 20 : std::string diagnostic_msg("version: " + std::to_string(version));
1393 10 : if(version == 4)
1394 : {
1395 7 : diagnostic_msg += '/';
1396 7 : diagnostic_msg += std::to_string(off_mask);
1397 : }
1398 10 : ::snaplogger::nested_diagnostic version_diagnostic(diagnostic_msg, true);
1399 :
1400 10 : std::vector<std::string> const args = {
1401 : "cluckd", // name of command
1402 : "--candidate-priority",
1403 9 : (version == 2 || (version == 4 && (off_mask & 0x04) != 0) ? "15" : "10"),
1404 : "--communicatord-listen",
1405 20 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
1406 : "--path-to-message-definitions",
1407 :
1408 : // WARNING: the order matters, we want to test with our source
1409 : // (i.e. original) files first
1410 : //
1411 20 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
1412 30 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
1413 179 : };
1414 :
1415 : // convert arguments
1416 : //
1417 10 : std::vector<char const *> args_strings;
1418 10 : args_strings.reserve(args.size() + 1);
1419 80 : for(auto const & arg : args)
1420 : {
1421 70 : args_strings.push_back(arg.c_str());
1422 : }
1423 10 : args_strings.push_back(nullptr); // NULL terminated
1424 :
1425 10 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
1426 10 : lock->add_connections();
1427 :
1428 10 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
1429 40 : std::string const filename(source_dir + "/tests/rprtr/failed_with_too_many_off_v" + std::to_string(version) + ".rprtr");
1430 10 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
1431 10 : CATCH_REQUIRE(l != nullptr);
1432 10 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1433 10 : if(version == 4)
1434 : {
1435 7 : SNAP_CATCH2_NAMESPACE::reporter::variable_integer::pointer_t var(
1436 : std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::variable_integer>(
1437 7 : "off_mask"));
1438 7 : var->set_integer(off_mask);
1439 7 : s->set_variable(var);
1440 7 : }
1441 10 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1442 10 : p->parse_program();
1443 :
1444 10 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1445 10 : e->start();
1446 :
1447 10 : e->set_thread_done_callback([lock]()
1448 : {
1449 10 : lock->stop(true);
1450 10 : });
1451 :
1452 : try
1453 : {
1454 10 : lock->run();
1455 : }
1456 0 : catch(std::exception const & ex)
1457 : {
1458 0 : SNAP_LOG_FATAL
1459 : << "an exception occurred while running cluckd (get max ticket overflow): "
1460 : << ex
1461 : << SNAP_LOG_SEND;
1462 :
1463 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
1464 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
1465 : {
1466 0 : SNAP_LOG_FATAL
1467 : << " "
1468 : << line
1469 : << SNAP_LOG_SEND;
1470 : }
1471 :
1472 0 : throw;
1473 0 : }
1474 :
1475 10 : CATCH_REQUIRE(s->get_exit_code() == 0);
1476 10 : }
1477 : }
1478 1 : }
1479 7 : CATCH_END_SECTION()
1480 :
1481 8 : CATCH_START_SECTION("cluck_daemon_errors: 100% time out")
1482 : {
1483 1 : addr::addr a(get_address());
1484 :
1485 1 : std::vector<std::string> const args = {
1486 : "cluckd", // name of command
1487 : "--candidate-priority",
1488 : "10",
1489 : "--communicatord-listen",
1490 2 : "cd://" + a.to_ipv4or6_string(addr::STRING_IP_ADDRESS_PORT),
1491 : "--path-to-message-definitions",
1492 :
1493 : // WARNING: the order matters, we want to test with our source
1494 : // (i.e. original) files first
1495 : //
1496 2 : SNAP_CATCH2_NAMESPACE::g_source_dir() + "/daemon/message-definitions:"
1497 3 : + SNAP_CATCH2_NAMESPACE::g_dist_dir() + "/share/eventdispatcher/messages",
1498 17 : };
1499 :
1500 : // convert arguments
1501 : //
1502 1 : std::vector<char const *> args_strings;
1503 1 : args_strings.reserve(args.size() + 1);
1504 8 : for(auto const & arg : args)
1505 : {
1506 7 : args_strings.push_back(arg.c_str());
1507 : }
1508 1 : args_strings.push_back(nullptr); // NULL terminated
1509 :
1510 1 : cluck_daemon::cluckd::pointer_t lock(std::make_shared<cluck_daemon::cluckd>(args.size(), const_cast<char **>(args_strings.data())));
1511 1 : lock->add_connections();
1512 :
1513 1 : std::string const source_dir(SNAP_CATCH2_NAMESPACE::g_source_dir());
1514 1 : std::string const filename(source_dir + "/tests/rprtr/cluck_daemon_test_timeout.rprtr");
1515 1 : SNAP_CATCH2_NAMESPACE::reporter::lexer::pointer_t l(SNAP_CATCH2_NAMESPACE::reporter::create_lexer(filename));
1516 1 : CATCH_REQUIRE(l != nullptr);
1517 1 : SNAP_CATCH2_NAMESPACE::reporter::state::pointer_t s(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::state>());
1518 1 : SNAP_CATCH2_NAMESPACE::reporter::parser::pointer_t p(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::parser>(l, s));
1519 1 : p->parse_program();
1520 :
1521 1 : SNAP_CATCH2_NAMESPACE::reporter::executor::pointer_t e(std::make_shared<SNAP_CATCH2_NAMESPACE::reporter::executor>(s));
1522 1 : e->start();
1523 :
1524 1 : e->set_thread_done_callback([lock]()
1525 : {
1526 1 : lock->stop(true);
1527 1 : });
1528 :
1529 : try
1530 : {
1531 1 : lock->run();
1532 : }
1533 0 : catch(std::exception const & ex)
1534 : {
1535 0 : SNAP_LOG_FATAL
1536 : << "an exception occurred while running cluckd (get max ticket overflow): "
1537 : << ex
1538 : << SNAP_LOG_SEND;
1539 :
1540 0 : libexcept::exception_base_t const * b(dynamic_cast<libexcept::exception_base_t const *>(&ex));
1541 0 : if(b != nullptr) for(auto const & line : b->get_stack_trace())
1542 : {
1543 0 : SNAP_LOG_FATAL
1544 : << " "
1545 : << line
1546 : << SNAP_LOG_SEND;
1547 : }
1548 :
1549 0 : throw;
1550 0 : }
1551 :
1552 1 : CATCH_REQUIRE(s->get_exit_code() == 0);
1553 1 : }
1554 7 : CATCH_END_SECTION()
1555 6 : }
1556 :
1557 :
1558 :
1559 : // vim: ts=4 sw=4 et
|