Line data Source code
1 : // Copyright (c) 2006-2025 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/snaplogger
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 : // header being tested
20 : //
21 : #include <snaplogger/message.h>
22 :
23 :
24 : // self
25 : //
26 : #include "catch_main.h"
27 :
28 :
29 : // cppthread
30 : //
31 : #include <cppthread/log.h>
32 :
33 :
34 : // as2js
35 : //
36 : #include <as2js/message.h>
37 :
38 :
39 : // snaplogger
40 : //
41 : #include <snaplogger/buffer_appender.h>
42 : #include <snaplogger/exception.h>
43 : #include <snaplogger/format.h>
44 : #include <snaplogger/logger.h>
45 : #include <snaplogger/map_diagnostic.h>
46 : #include <snaplogger/severity.h>
47 : #include <snaplogger/version.h>
48 :
49 :
50 : // snapdev
51 : //
52 : #include <snapdev/enum_class_math.h>
53 :
54 :
55 : // advgetopt
56 : //
57 : #include <advgetopt/exception.h>
58 :
59 :
60 : // C
61 : //
62 : #include <math.h>
63 : #include <unistd.h>
64 :
65 :
66 : namespace
67 : {
68 :
69 :
70 1 : std::source_location get_other_loc()
71 : {
72 1 : return std::source_location::current();
73 : }
74 :
75 :
76 :
77 : } // no name namespace
78 :
79 :
80 1 : CATCH_TEST_CASE("message_is_final", "[message]")
81 : {
82 1 : CATCH_START_SECTION("message: make sure message is final")
83 : {
84 1 : CATCH_REQUIRE(std::is_final_v<snaplogger::message>);
85 : }
86 1 : CATCH_END_SECTION()
87 1 : }
88 :
89 :
90 2 : CATCH_TEST_CASE("not_a_message", "[message]")
91 : {
92 2 : CATCH_START_SECTION("message: Call send_message() with wrong ostream")
93 : {
94 3 : CATCH_REQUIRE_THROWS_MATCHES(
95 : snaplogger::send_message(std::cout)
96 : , snaplogger::not_a_message
97 : , Catch::Matchers::ExceptionMessage(
98 : "logger_error: the 'out' parameter to the send_message() function is expected to be a snaplogger::message object."));
99 : }
100 2 : CATCH_END_SECTION()
101 :
102 2 : CATCH_START_SECTION("message: Print snaplogger::secure to ostream")
103 : {
104 1 : std::stringstream buffer;
105 1 : std::streambuf * old(std::cout.rdbuf(buffer.rdbuf()));
106 1 : std::cout << snaplogger::secure << std::endl;
107 1 : CATCH_REQUIRE(buffer.str() == "(section:secure)\n");
108 1 : std::cout.rdbuf(old);
109 1 : }
110 2 : CATCH_END_SECTION()
111 2 : }
112 :
113 :
114 :
115 2 : CATCH_TEST_CASE("message_capture", "[message]")
116 : {
117 2 : CATCH_START_SECTION("message: Buffering")
118 : {
119 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-logging");
120 :
121 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
122 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
123 :
124 1 : CATCH_REQUIRE(buffer->get_type() == "buffer");
125 :
126 1 : char const * cargv[] =
127 : {
128 : "/usr/bin/daemon",
129 : nullptr
130 : };
131 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
132 1 : char ** argv = const_cast<char **>(cargv);
133 :
134 1 : advgetopt::options_environment environment_options;
135 1 : environment_options.f_project_name = "test-logger";
136 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
137 1 : advgetopt::getopt opts(environment_options);
138 1 : opts.parse_program_name(argv);
139 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
140 :
141 1 : buffer->set_config(opts);
142 :
143 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${severity}: ${message}"));
144 1 : buffer->set_format(f);
145 :
146 1 : l->add_appender(buffer);
147 :
148 2 : SNAP_LOG_ERROR << snaplogger::precise_time << "Logging this error" << SNAP_LOG_SEND;
149 1 : CATCH_REQUIRE(buffer->str() == "error: Logging this error\n");
150 :
151 : // test the other str() function too
152 : //
153 3 : buffer->str("Start: ");
154 :
155 : // show that the "\n" does not get duplicated
156 : //
157 2 : SNAP_LOG_ERROR << "Error with newline\n" << SNAP_LOG_SEND;
158 1 : CATCH_REQUIRE(buffer->str() == "Start: error: Error with newline\n");
159 1 : buffer->clear();
160 :
161 : // show that the "\r\n" gets replaced by "\n"
162 : //
163 2 : SNAP_LOG_ERROR << "Error with CRLF\r\n" << SNAP_LOG_SEND;
164 1 : CATCH_REQUIRE(buffer->str() == "error: Error with CRLF\n");
165 1 : buffer->clear();
166 :
167 : // severity too low, no change to buffer
168 : //
169 2 : SNAP_LOG_DEBUG << "Debug Message " << M_PI << " which does not make it at all...\n" << SNAP_LOG_SEND;
170 1 : CATCH_REQUIRE(buffer->empty());
171 :
172 1 : l->reset();
173 1 : }
174 2 : CATCH_END_SECTION()
175 :
176 2 : CATCH_START_SECTION("message: JSON Buffering")
177 : {
178 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "json-logging");
179 :
180 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
181 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("json-buffer"));
182 :
183 1 : CATCH_REQUIRE(buffer->get_type() == "buffer");
184 :
185 1 : char const * cargv[] =
186 : {
187 : "/usr/bin/daemon",
188 : nullptr
189 : };
190 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
191 1 : char ** argv = const_cast<char **>(cargv);
192 :
193 1 : advgetopt::options_environment environment_options;
194 1 : environment_options.f_project_name = "json-logger";
195 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
196 1 : advgetopt::getopt opts(environment_options);
197 1 : opts.parse_program_name(argv);
198 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
199 :
200 1 : buffer->set_config(opts);
201 :
202 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
203 : "{\"version\":1,"
204 1 : "\"message\":\"${message:escape='\\\r\n\t\"'}\"}"));
205 1 : buffer->set_format(f);
206 :
207 1 : l->add_appender(buffer);
208 :
209 4 : SNAP_LOG_ERROR
210 6 : << SNAP_LOG_FIELD(std::string("format"), std::string("json"))
211 : << "A JSON error message (format:${field:name=format})"
212 : << SNAP_LOG_SEND;
213 1 : CATCH_REQUIRE(buffer->str() == "{\"version\":1,\"message\":\"A JSON error message (format:json)\"}\n");
214 1 : buffer->clear();
215 :
216 : // show that the "\n" does not get duplicated
217 : //
218 5 : SNAP_LOG_ERROR
219 : << "See what happens with a \"quoted string\" within the message (${fields})\n"
220 6 : << SNAP_LOG_FIELD(std::string("format"), std::string("json"))
221 6 : << SNAP_LOG_FIELD(std::string("language"), std::string("js"))
222 : << SNAP_LOG_SEND;
223 1 : std::string const expected(std::regex_replace(buffer->str(), std::regex("\\\\\"id\\\\\":\\\\\"[0-9]+\\\\\","), ""));
224 1 : CATCH_REQUIRE(expected == "{\"version\":1,\"message\":\"See what happens with a \\\"quoted string\\\" within the message ({\\\"format\\\":\\\"json\\\",\\\"language\\\":\\\"js\\\"})\"}\n");
225 1 : buffer->clear();
226 :
227 1 : l->reset();
228 1 : }
229 2 : CATCH_END_SECTION()
230 2 : }
231 :
232 :
233 1 : CATCH_TEST_CASE("message_copy", "[message]")
234 : {
235 1 : CATCH_START_SECTION("message: Copy")
236 : {
237 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-copying");
238 :
239 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
240 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
241 :
242 1 : CATCH_REQUIRE(buffer->get_type() == "buffer");
243 :
244 1 : char const * cargv[] =
245 : {
246 : "/usr/bin/daemon",
247 : nullptr
248 : };
249 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
250 1 : char ** argv = const_cast<char **>(cargv);
251 :
252 1 : advgetopt::options_environment environment_options;
253 1 : environment_options.f_project_name = "test-logger";
254 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
255 1 : advgetopt::getopt opts(environment_options);
256 1 : opts.parse_program_name(argv);
257 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
258 :
259 1 : buffer->set_config(opts);
260 :
261 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
262 1 : buffer->set_format(f);
263 :
264 1 : l->add_appender(buffer);
265 :
266 1 : std::source_location const loc(std::source_location::current());
267 1 : snaplogger::message::pointer_t msg(std::make_shared<snaplogger::message>
268 1 : (::snaplogger::severity_t::SEVERITY_ERROR, loc));
269 :
270 1 : CATCH_REQUIRE(msg->get_filename() == loc.file_name());
271 1 : CATCH_REQUIRE(msg->get_function() == loc.function_name());
272 1 : CATCH_REQUIRE(msg->get_line() == loc.line());
273 1 : CATCH_REQUIRE(msg->get_column() == loc.column());
274 :
275 : // using a standard location
276 : //
277 1 : std::source_location const other_loc(get_other_loc());
278 :
279 1 : CATCH_REQUIRE(msg->get_filename() == loc.file_name());
280 1 : CATCH_REQUIRE(msg->get_function() == loc.function_name());
281 1 : CATCH_REQUIRE(msg->get_line() == loc.line());
282 1 : CATCH_REQUIRE(msg->get_column() == loc.column());
283 :
284 : // direct
285 : //
286 3 : msg->set_filename("we-are-under-control.cpp");
287 3 : msg->set_function("testing_set_function");
288 1 : msg->set_line(123);
289 1 : msg->set_column(64);
290 :
291 1 : CATCH_REQUIRE(msg->get_filename() == "we-are-under-control.cpp");
292 1 : CATCH_REQUIRE(msg->get_function() == "testing_set_function");
293 1 : CATCH_REQUIRE(msg->get_line() == 123);
294 1 : CATCH_REQUIRE(msg->get_column() == 64);
295 :
296 1 : *msg << "Logging an error.";
297 :
298 1 : CATCH_REQUIRE(msg->str() == "Logging an error.");
299 :
300 1 : snaplogger::message::pointer_t copy(std::make_shared<snaplogger::message>(*msg, *msg));
301 :
302 1 : CATCH_REQUIRE(msg->str() == "Logging an error.");
303 1 : CATCH_REQUIRE(copy->str() == "Logging an error.");
304 :
305 : // no destructor called, the output is still empty
306 : //
307 1 : CATCH_REQUIRE(buffer->empty());
308 :
309 1 : copy.reset();
310 :
311 : // msg not lost
312 : //
313 1 : CATCH_REQUIRE(msg->str() == "Logging an error.");
314 :
315 : // destructor against copy does not trigger send_message()
316 : //
317 1 : CATCH_REQUIRE(buffer->empty());
318 :
319 1 : snaplogger::send_message(*msg);
320 :
321 : // now we get the message as expected!
322 : //
323 : // (note that internally we can skip receiving the message on the
324 : // original, but not as a client... we may want to have the ability
325 : // to cancel a message, though.)
326 : //
327 1 : CATCH_REQUIRE(buffer->str() == "Logging an error.\n");
328 :
329 1 : msg.reset();
330 :
331 1 : CATCH_REQUIRE(buffer->str() == "Logging an error.\n");
332 :
333 1 : l->reset();
334 1 : }
335 1 : CATCH_END_SECTION()
336 1 : }
337 :
338 :
339 2 : CATCH_TEST_CASE("message_severity", "[message][severity]")
340 : {
341 2 : CATCH_START_SECTION("message: Appender vs Message severity")
342 : {
343 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-severity");
344 :
345 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
346 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
347 :
348 1 : char const * cargv[] =
349 : {
350 : "/usr/bin/daemon",
351 : nullptr
352 : };
353 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
354 1 : char ** argv = const_cast<char **>(cargv);
355 :
356 1 : advgetopt::options_environment environment_options;
357 1 : environment_options.f_project_name = "test-logger";
358 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
359 1 : advgetopt::getopt opts(environment_options);
360 1 : opts.parse_program_name(argv);
361 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
362 :
363 1 : buffer->set_config(opts);
364 :
365 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
366 1 : buffer->set_format(f);
367 :
368 1 : l->add_appender(buffer);
369 :
370 : // ++<enum> works here because of this header:
371 : // <snapdev/enum_class_math.h>
372 : //
373 257 : for(snaplogger::severity_t i(snaplogger::severity_t::SEVERITY_MIN); i <= snaplogger::severity_t::SEVERITY_MAX; ++i)
374 : {
375 256 : buffer->set_severity(i);
376 65792 : for(snaplogger::severity_t j(snaplogger::severity_t::SEVERITY_MIN); j <= snaplogger::severity_t::SEVERITY_MAX; ++j)
377 : {
378 131072 : snaplogger::send_message(*::snaplogger::create_message(j)
379 : << "The message itself");
380 :
381 65536 : if(j >= i
382 32896 : && i != snaplogger::severity_t::SEVERITY_OFF
383 32895 : && j != snaplogger::severity_t::SEVERITY_OFF)
384 : {
385 32640 : CATCH_REQUIRE(buffer->str() == "The message itself\n");
386 32640 : }
387 : else
388 : {
389 32896 : CATCH_REQUIRE(buffer->empty());
390 : }
391 65536 : buffer->clear();
392 : }
393 : }
394 :
395 1 : l->reset();
396 1 : }
397 2 : CATCH_END_SECTION()
398 :
399 2 : CATCH_START_SECTION("message: Changing message severity (takes about 3.5min)")
400 : {
401 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-copying");
402 :
403 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
404 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
405 :
406 1 : char const * cargv[] =
407 : {
408 : "/usr/bin/daemon",
409 : nullptr
410 : };
411 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
412 1 : char ** argv = const_cast<char **>(cargv);
413 :
414 1 : advgetopt::options_environment environment_options;
415 1 : environment_options.f_project_name = "test-logger";
416 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
417 1 : advgetopt::getopt opts(environment_options);
418 1 : opts.parse_program_name(argv);
419 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
420 :
421 1 : buffer->set_config(opts);
422 :
423 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
424 1 : buffer->set_format(f);
425 :
426 1 : l->add_appender(buffer);
427 :
428 : // <enum> += n works here because of this header:
429 : // <snapdev/enum_class_math.h>
430 : //
431 25 : for(snaplogger::severity_t i(snaplogger::severity_t::SEVERITY_MIN); i <= snaplogger::severity_t::SEVERITY_MAX; i += 1 + (rand() & 15))
432 : {
433 24 : buffer->set_severity(i);
434 780 : for(snaplogger::severity_t j(snaplogger::severity_t::SEVERITY_MIN); j <= snaplogger::severity_t::SEVERITY_MAX; j += 1 + (rand() & 15))
435 : {
436 23957 : for(snaplogger::severity_t k(snaplogger::severity_t::SEVERITY_MIN); k <= snaplogger::severity_t::SEVERITY_MAX; k += 1 + (rand() & 15))
437 : {
438 23201 : ::snaplogger::message::pointer_t msg(std::make_shared<::snaplogger::message>(j));
439 23201 : *msg << "Start of message";
440 23201 : msg->set_severity(k);
441 23201 : *msg << " -- end of message";
442 23201 : snaplogger::send_message(*msg);
443 : //std::cerr << "checking with " << i << ", " << j << ", " << k << "\n";
444 :
445 23201 : if(j >= i
446 12260 : && k >= i
447 8375 : && i != snaplogger::severity_t::SEVERITY_OFF
448 8375 : && j != snaplogger::severity_t::SEVERITY_OFF)
449 : //&& k != snaplogger::severity_t::SEVERITY_OFF)
450 : {
451 8344 : if(j >= i)
452 : {
453 8344 : CATCH_REQUIRE(buffer->str() == "Start of message -- end of message\n");
454 : }
455 : else
456 : {
457 0 : CATCH_REQUIRE(buffer->str() == "Start of message\n");
458 : }
459 8344 : }
460 : else
461 : {
462 14857 : CATCH_REQUIRE(buffer->empty());
463 : }
464 23201 : buffer->clear();
465 23201 : }
466 : }
467 : }
468 :
469 1 : l->reset();
470 1 : }
471 2 : CATCH_END_SECTION()
472 2 : }
473 :
474 :
475 4 : CATCH_TEST_CASE("message_format", "[message][format]")
476 : {
477 4 : CATCH_START_SECTION("message: Recursivity")
478 : {
479 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "basic-format");
480 :
481 : // these two are not called in this test
482 : //
483 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROJECT_NAME, "test-logger");
484 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_VERSION, "5.32.1024");
485 :
486 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
487 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
488 :
489 1 : char const * cargv[] =
490 : {
491 : "/usr/bin/daemon",
492 : nullptr
493 : };
494 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
495 1 : char ** argv = const_cast<char **>(cargv);
496 :
497 1 : advgetopt::options_environment environment_options;
498 1 : environment_options.f_project_name = "test-logger";
499 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
500 1 : environment_options.f_version = "5.32.1024";
501 1 : advgetopt::getopt opts(environment_options);
502 1 : opts.parse_program_name(argv);
503 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
504 :
505 1 : buffer->set_config(opts);
506 :
507 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${project_name} ${message} v${version}"));
508 1 : buffer->set_format(f);
509 :
510 1 : l->add_appender(buffer);
511 :
512 2 : SNAP_LOG_WARNING
513 : << "Message Project Name = ${project_name} and Version = ${version} -- uses \"recursive\""
514 : << SNAP_LOG_SEND;
515 :
516 1 : CATCH_REQUIRE(buffer->str() ==
517 : "test-logger Message Project Name = test-logger and"
518 : " Version = 5.32.1024 -- uses \"recursive\" v5.32.1024"
519 : "\n");
520 :
521 1 : l->reset();
522 1 : }
523 4 : CATCH_END_SECTION()
524 :
525 4 : CATCH_START_SECTION("message: ${message} itself is not recursive")
526 : {
527 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "prevent-infinite-loop");
528 :
529 : // these two are not called in this test
530 : //
531 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROJECT_NAME, "test-logger");
532 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_VERSION, "5.32.1024");
533 :
534 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
535 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
536 :
537 1 : char const * cargv[] =
538 : {
539 : "/usr/bin/daemon",
540 : nullptr
541 : };
542 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
543 1 : char ** argv = const_cast<char **>(cargv);
544 :
545 1 : advgetopt::options_environment environment_options;
546 1 : environment_options.f_project_name = "test-logger";
547 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
548 1 : environment_options.f_version = "5.32.1024";
549 1 : advgetopt::getopt opts(environment_options);
550 1 : opts.parse_program_name(argv);
551 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
552 :
553 1 : buffer->set_config(opts);
554 :
555 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${project_name} ${message} v${version}"));
556 1 : buffer->set_format(f);
557 :
558 1 : l->add_appender(buffer);
559 :
560 2 : SNAP_LOG_WARNING
561 : << "Message ${message} says: Project Name = ${project_name} and Version = ${version} -- uses \"recursive\""
562 : << SNAP_LOG_SEND;
563 :
564 1 : CATCH_REQUIRE(buffer->str() ==
565 : "test-logger Message says: Project Name = test-logger and"
566 : " Version = 5.32.1024 -- uses \"recursive\" v5.32.1024"
567 : "\n");
568 :
569 1 : buffer->clear();
570 :
571 3 : snaplogger::unset_diagnostic(snaplogger::DIAG_KEY_VERSION);
572 :
573 2 : SNAP_LOG_WARNING
574 : << "Removed the version: ${message} says: Project Name = ${project_name} and Version = ${version} -- uses \"recursive\""
575 : << SNAP_LOG_SEND;
576 :
577 1 : CATCH_REQUIRE(buffer->str() ==
578 : "test-logger Removed the version: says: Project Name = test-logger and"
579 : " Version = -- uses \"recursive\" v"
580 : "\n");
581 :
582 1 : l->reset();
583 1 : }
584 4 : CATCH_END_SECTION()
585 :
586 4 : CATCH_START_SECTION("message: ${pid} uses the get_environment() function")
587 : {
588 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "get-environment");
589 :
590 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
591 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
592 :
593 1 : char const * cargv[] =
594 : {
595 : "/usr/bin/daemon",
596 : nullptr
597 : };
598 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
599 1 : char ** argv = const_cast<char **>(cargv);
600 :
601 1 : advgetopt::options_environment environment_options;
602 1 : environment_options.f_project_name = "test-logger";
603 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
604 1 : advgetopt::getopt opts(environment_options);
605 1 : opts.parse_program_name(argv);
606 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
607 :
608 1 : buffer->set_config(opts);
609 :
610 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
611 1 : buffer->set_format(f);
612 :
613 1 : l->add_appender(buffer);
614 :
615 2 : SNAP_LOG_WARNING
616 : << "Test PID = ${pid} == ${pid:running}"
617 : << SNAP_LOG_SEND;
618 :
619 1 : CATCH_REQUIRE(buffer->str() ==
620 : "Test PID = " + std::to_string(getpid())
621 : + " == " + std::to_string(getpid())
622 : + "\n");
623 :
624 1 : l->reset();
625 1 : }
626 4 : CATCH_END_SECTION()
627 :
628 4 : CATCH_START_SECTION("message: Verify year")
629 : {
630 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "get-environment");
631 :
632 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
633 3 : CATCH_REQUIRE(l->get_appender("test-buffer") == nullptr);
634 :
635 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
636 :
637 1 : char const * cargv[] =
638 : {
639 : "/usr/bin/daemon",
640 : nullptr
641 : };
642 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
643 1 : char ** argv = const_cast<char **>(cargv);
644 :
645 1 : advgetopt::options_environment environment_options;
646 1 : environment_options.f_project_name = "test-logger";
647 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
648 1 : advgetopt::getopt opts(environment_options);
649 1 : opts.parse_program_name(argv);
650 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
651 :
652 1 : buffer->set_config(opts);
653 :
654 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
655 1 : buffer->set_format(f);
656 :
657 1 : l->add_appender(buffer);
658 :
659 3 : CATCH_REQUIRE(l->get_appender("test-buffer") == buffer);
660 :
661 : // we create a message so we can check the timestamp in our test
662 : //
663 1 : snaplogger::message::pointer_t msg(std::make_shared<snaplogger::message>
664 1 : (::snaplogger::severity_t::SEVERITY_ERROR));
665 1 : *msg << "Created message on YYYY = ${date:year}, MM = ${date:month}, DD = ${date:day}";
666 :
667 1 : timespec const stamp(msg->get_timestamp());
668 :
669 1 : snaplogger::send_message(*msg);
670 :
671 1 : tm t;
672 1 : gmtime_r(&stamp.tv_sec, &t);
673 1 : char year[16];
674 1 : char month[16];
675 1 : char day[16];
676 1 : strftime(year, 16, "%Y", &t);
677 1 : strftime(month, 16, "%m", &t);
678 1 : strftime(day, 16, "%d", &t);
679 :
680 3 : CATCH_REQUIRE(buffer->str() ==
681 : std::string("Created message on YYYY = ")
682 : + year
683 : + ", MM = "
684 : + std::to_string(std::atoi(month)) // remove the leading '0' if necessary
685 : + ", DD = "
686 : + std::to_string(std::atoi(day)) // remove the leading '0' if necessary
687 : + "\n");
688 :
689 1 : l->reset();
690 1 : }
691 4 : CATCH_END_SECTION()
692 4 : }
693 :
694 :
695 1 : CATCH_TEST_CASE("message_component_filter", "[message][component]")
696 : {
697 1 : CATCH_START_SECTION("message: Filter Message with Component")
698 : {
699 5 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "component-filter");
700 :
701 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
702 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
703 :
704 1 : char const * cargv[] =
705 : {
706 : "/usr/bin/daemon",
707 : nullptr
708 : };
709 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
710 1 : char ** argv = const_cast<char **>(cargv);
711 :
712 1 : advgetopt::options_environment environment_options;
713 1 : environment_options.f_project_name = "test-logger";
714 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
715 1 : advgetopt::getopt opts(environment_options);
716 1 : opts.parse_program_name(argv);
717 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
718 :
719 1 : buffer->set_config(opts);
720 :
721 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message} (${severity:format=number})"));
722 1 : buffer->set_format(f);
723 :
724 1 : l->add_appender(buffer);
725 :
726 3 : SNAP_LOG_WARNING
727 1 : << snaplogger::secure // mark as a secure message
728 : << "This message is secure but not the buffer"
729 : << SNAP_LOG_SEND;
730 :
731 1 : CATCH_REQUIRE(buffer->empty());
732 :
733 3 : SNAP_LOG_WARNING
734 1 : << "Test number: "
735 : << 2
736 1 : << " with buffer still unsecure..."
737 1 : << SNAP_LOG_SEND_SECURELY; // mark at the end
738 :
739 1 : CATCH_REQUIRE(buffer->empty());
740 :
741 : // mark the buffer as a secure buffer now
742 : //
743 1 : buffer->add_component(snaplogger::g_secure_component);
744 :
745 3 : SNAP_LOG_WARNING
746 1 : << snaplogger::secure // mark as a secure message
747 : << "This message is secure and so is the buffer"
748 : << SNAP_LOG_SEND;
749 :
750 : // TODO: get the WARNING severity level dynamically
751 1 : std::string const expected1("This message is secure and so is the buffer ("
752 2 : + std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING))
753 2 : + ")\n");
754 1 : CATCH_REQUIRE(buffer->str() == expected1);
755 :
756 1 : buffer->clear();
757 :
758 3 : SNAP_LOG_WARNING
759 1 : << "Test number: "
760 : << 4
761 1 : << " with secure buffer...\r\n"
762 1 : << SNAP_LOG_SEND_SECURELY; // mark at the end
763 :
764 : // TODO: get the WARNING severity level dynamically
765 1 : std::string const expected2("Test number: 4 with secure buffer... ("
766 2 : + std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING))
767 2 : + ")\n");
768 1 : CATCH_REQUIRE(buffer->str() == expected2);
769 :
770 1 : l->reset();
771 1 : }
772 1 : CATCH_END_SECTION()
773 1 : }
774 :
775 :
776 1 : CATCH_TEST_CASE("message_cppthread", "[message][cppthread]")
777 : {
778 1 : CATCH_START_SECTION("message: send log messages through cppthreadd with all levels")
779 : {
780 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
781 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("cppthread-buffer"));
782 :
783 1 : char const * cargv[] =
784 : {
785 : "/usr/bin/daemon",
786 : nullptr
787 : };
788 1 : int const argc(std::size(cargv) - 1);
789 1 : char ** argv = const_cast<char **>(cargv);
790 :
791 1 : advgetopt::options_environment environment_options;
792 1 : environment_options.f_project_name = "test-logger";
793 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
794 1 : advgetopt::getopt opts(environment_options);
795 1 : opts.parse_program_name(argv);
796 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
797 :
798 1 : buffer->set_config(opts);
799 :
800 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
801 1 : "${message} (${severity:format=number})"));
802 1 : buffer->set_format(f);
803 :
804 1 : l->add_appender(buffer);
805 1 : l->set_severity(snaplogger::severity_t::SEVERITY_ALL);
806 :
807 : cppthread::log
808 2 : << cppthread::log_level_t::debug
809 1 : << "a perfectly fine debug message here."
810 2 : << cppthread::end;
811 :
812 1 : std::string expected;
813 1 : expected = "a perfectly fine debug message here. (";
814 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_DEBUG));
815 1 : expected += ")\n";
816 1 : CATCH_REQUIRE(buffer->str() == expected);
817 1 : buffer->clear();
818 :
819 : cppthread::log
820 2 : << cppthread::log_level_t::info
821 1 : << "a good old info message there."
822 2 : << cppthread::end;
823 :
824 1 : expected = "a good old info message there. (";
825 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_INFORMATION));
826 1 : expected += ")\n";
827 1 : CATCH_REQUIRE(buffer->str() == expected);
828 1 : buffer->clear();
829 :
830 : cppthread::log
831 2 : << cppthread::log_level_t::warning
832 1 : << "a funny warning message here."
833 2 : << cppthread::end;
834 :
835 1 : expected = "a funny warning message here. (";
836 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING));
837 1 : expected += ")\n";
838 1 : CATCH_REQUIRE(buffer->str() == expected);
839 1 : buffer->clear();
840 :
841 : cppthread::log
842 2 : << cppthread::log_level_t::error
843 1 : << "a real error message here."
844 2 : << cppthread::end;
845 :
846 1 : expected = "a real error message here. (";
847 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_ERROR));
848 1 : expected += ")\n";
849 1 : CATCH_REQUIRE(buffer->str() == expected);
850 1 : buffer->clear();
851 :
852 : cppthread::log
853 2 : << cppthread::log_level_t::fatal
854 1 : << "an ending fatal message here."
855 2 : << cppthread::end;
856 :
857 1 : expected = "an ending fatal message here. (";
858 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_FATAL));
859 1 : expected += ")\n";
860 1 : CATCH_REQUIRE(buffer->str() == expected);
861 1 : buffer->clear();
862 :
863 : // try again when the CPPTHREAD component is turned off
864 : //
865 1 : l->add_component_to_ignore(snaplogger::g_cppthread_component);
866 :
867 : cppthread::log
868 2 : << cppthread::log_level_t::debug
869 1 : << "a perfectly fine debug message here."
870 2 : << cppthread::end;
871 :
872 1 : CATCH_REQUIRE(buffer->empty());
873 1 : buffer->clear();
874 :
875 : cppthread::log
876 2 : << cppthread::log_level_t::info
877 1 : << "a good old info message there."
878 2 : << cppthread::end;
879 :
880 1 : CATCH_REQUIRE(buffer->empty());
881 1 : buffer->clear();
882 :
883 : cppthread::log
884 2 : << cppthread::log_level_t::warning
885 1 : << "a funny warning message here."
886 2 : << cppthread::end;
887 :
888 1 : CATCH_REQUIRE(buffer->empty());
889 1 : buffer->clear();
890 :
891 : cppthread::log
892 2 : << cppthread::log_level_t::error
893 1 : << "a real error message here."
894 2 : << cppthread::end;
895 :
896 1 : CATCH_REQUIRE(buffer->empty());
897 1 : buffer->clear();
898 :
899 : cppthread::log
900 2 : << cppthread::log_level_t::fatal
901 1 : << "an ending fatal message here."
902 2 : << cppthread::end;
903 :
904 1 : CATCH_REQUIRE(buffer->empty());
905 1 : buffer->clear();
906 :
907 1 : l->remove_component_to_ignore(snaplogger::g_cppthread_component);
908 1 : l->reset();
909 1 : }
910 1 : CATCH_END_SECTION()
911 1 : }
912 :
913 :
914 1 : CATCH_TEST_CASE("message_as2js", "[message][as2js]")
915 : {
916 1 : CATCH_START_SECTION("message: send log messages through as2js with all levels")
917 : {
918 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
919 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("as2js-buffer"));
920 :
921 1 : char const * cargv[] =
922 : {
923 : "/usr/bin/daemon",
924 : nullptr
925 : };
926 1 : int const argc(std::size(cargv) - 1);
927 1 : char ** argv = const_cast<char **>(cargv);
928 :
929 1 : advgetopt::options_environment environment_options;
930 1 : environment_options.f_project_name = "test-logger";
931 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
932 1 : advgetopt::getopt opts(environment_options);
933 1 : opts.parse_program_name(argv);
934 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
935 :
936 1 : buffer->set_config(opts);
937 :
938 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
939 1 : "${message} (${severity:format=number})"));
940 1 : buffer->set_format(f);
941 :
942 1 : l->add_appender(buffer);
943 1 : l->set_severity(snaplogger::severity_t::SEVERITY_ALL);
944 :
945 1 : as2js::set_message_level(as2js::message_level_t::MESSAGE_LEVEL_TRACE);
946 :
947 : {
948 : {
949 1 : as2js::position pos;
950 3 : pos.set_filename("trace-me.as");
951 3 : pos.set_function("getUs");
952 1 : pos.reset_counters(15);
953 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_TRACE, as2js::err_code_t::AS_ERR_NONE, pos);
954 1 : msg << "as2js supports tracing too.";
955 1 : }
956 :
957 1 : std::string expected;
958 1 : expected = "trace-me.as:15: as2js supports tracing too. (";
959 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_TRACE));
960 1 : expected += ")\n";
961 1 : CATCH_REQUIRE(buffer->str() == expected);
962 1 : buffer->clear();
963 1 : }
964 :
965 : {
966 : {
967 1 : as2js::position pos;
968 3 : pos.set_filename("debug.as");
969 3 : pos.set_function("getFluff");
970 1 : pos.reset_counters(5);
971 1 : pos.new_column();
972 1 : pos.new_column();
973 1 : pos.new_column();
974 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_DEBUG, as2js::err_code_t::AS_ERR_INVALID_EXPRESSION, pos);
975 1 : msg << "This is the debug message.";
976 1 : }
977 :
978 1 : std::string expected;
979 1 : expected = "debug.as:5:4:err:";
980 1 : expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_INVALID_EXPRESSION));
981 1 : expected += ": This is the debug message. (";
982 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_DEBUG));
983 1 : expected += ")\n";
984 1 : CATCH_REQUIRE(buffer->str() == expected);
985 1 : buffer->clear();
986 1 : }
987 :
988 : {
989 : {
990 1 : as2js::position pos;
991 3 : pos.set_filename("info.as");
992 3 : pos.set_function("marvelous");
993 1 : pos.reset_counters(33);
994 1 : pos.new_column();
995 1 : pos.new_column();
996 1 : pos.new_column();
997 1 : pos.new_column();
998 1 : pos.new_column();
999 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_INFO, as2js::err_code_t::AS_ERR_ABSTRACT, pos);
1000 1 : msg << "This is the info message.";
1001 1 : }
1002 :
1003 1 : std::string expected;
1004 1 : expected = "info.as:33:6:err:";
1005 1 : expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_ABSTRACT));
1006 1 : expected += ": This is the info message. (";
1007 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_INFORMATION));
1008 1 : expected += ")\n";
1009 1 : CATCH_REQUIRE(buffer->str() == expected);
1010 1 : buffer->clear();
1011 1 : }
1012 :
1013 : {
1014 : {
1015 1 : as2js::position pos;
1016 3 : pos.set_filename("warning.as");
1017 3 : pos.set_function("getWarningSigns");
1018 1 : pos.reset_counters(3);
1019 1 : pos.new_column();
1020 1 : pos.new_column();
1021 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_WARNING, as2js::err_code_t::AS_ERR_FINAL, pos);
1022 1 : msg << "This is the warning message.";
1023 1 : }
1024 :
1025 1 : std::string expected;
1026 1 : expected = "warning.as:3:3:err:";
1027 1 : expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_FINAL));
1028 1 : expected += ": This is the warning message. (";
1029 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING));
1030 1 : expected += ")\n";
1031 1 : CATCH_REQUIRE(buffer->str() == expected);
1032 1 : buffer->clear();
1033 1 : }
1034 :
1035 : {
1036 : {
1037 1 : as2js::position pos;
1038 3 : pos.set_filename("error.as");
1039 3 : pos.set_function("gotMade");
1040 1 : pos.reset_counters(65);
1041 1 : pos.new_column();
1042 1 : pos.new_column();
1043 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_ERROR, as2js::err_code_t::AS_ERR_DIVIDE_BY_ZERO, pos);
1044 1 : msg << "we got a real error here.";
1045 1 : }
1046 :
1047 1 : std::string expected;
1048 1 : expected = "error.as:65:3:err:";
1049 1 : expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_DIVIDE_BY_ZERO));
1050 1 : expected += ": we got a real error here. (";
1051 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_ERROR));
1052 1 : expected += ")\n";
1053 1 : CATCH_REQUIRE(buffer->str() == expected);
1054 1 : buffer->clear();
1055 1 : }
1056 :
1057 : {
1058 : {
1059 1 : as2js::position pos;
1060 3 : pos.set_filename("fatal.as");
1061 3 : pos.set_function("done");
1062 1 : pos.reset_counters(789);
1063 1 : pos.new_column();
1064 1 : pos.new_column();
1065 1 : pos.new_column();
1066 1 : pos.new_column();
1067 1 : pos.new_column();
1068 1 : pos.new_column();
1069 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_FATAL, as2js::err_code_t::AS_ERR_NOT_SUPPORTED, pos);
1070 1 : msg << "this is not yet implemented.";
1071 1 : }
1072 :
1073 1 : std::string expected;
1074 1 : expected = "fatal.as:789:7:err:";
1075 1 : expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_NOT_SUPPORTED));
1076 1 : expected += ": this is not yet implemented. (";
1077 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_FATAL));
1078 1 : expected += ")\n";
1079 1 : CATCH_REQUIRE(buffer->str() == expected);
1080 1 : buffer->clear();
1081 1 : }
1082 :
1083 :
1084 : // try again when the AS2JS component is turned off
1085 : //
1086 1 : l->add_component_to_ignore(snaplogger::g_as2js_component);
1087 :
1088 : {
1089 : {
1090 1 : as2js::position pos;
1091 3 : pos.set_filename("trace-me.as");
1092 3 : pos.set_function("getUs");
1093 1 : pos.reset_counters(15);
1094 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_TRACE, as2js::err_code_t::AS_ERR_NOT_SUPPORTED, pos);
1095 1 : msg << "as2js supports tracing too.";
1096 1 : }
1097 :
1098 1 : CATCH_REQUIRE(buffer->empty());
1099 1 : buffer->clear();
1100 : }
1101 :
1102 : {
1103 : {
1104 1 : as2js::position pos;
1105 3 : pos.set_filename("debug.as");
1106 3 : pos.set_function("getFluff");
1107 1 : pos.reset_counters(5);
1108 1 : pos.new_column();
1109 1 : pos.new_column();
1110 1 : pos.new_column();
1111 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_DEBUG, as2js::err_code_t::AS_ERR_INVALID_EXPRESSION, pos);
1112 1 : msg << "This is the debug message.";
1113 1 : }
1114 :
1115 1 : CATCH_REQUIRE(buffer->empty());
1116 1 : buffer->clear();
1117 : }
1118 :
1119 : {
1120 : {
1121 1 : as2js::position pos;
1122 3 : pos.set_filename("info.as");
1123 3 : pos.set_function("marvelous");
1124 1 : pos.reset_counters(33);
1125 1 : pos.new_column();
1126 1 : pos.new_column();
1127 1 : pos.new_column();
1128 1 : pos.new_column();
1129 1 : pos.new_column();
1130 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_INFO, as2js::err_code_t::AS_ERR_ABSTRACT, pos);
1131 1 : msg << "This is the info message.";
1132 1 : }
1133 :
1134 1 : CATCH_REQUIRE(buffer->empty());
1135 1 : buffer->clear();
1136 : }
1137 :
1138 : {
1139 : {
1140 1 : as2js::position pos;
1141 3 : pos.set_filename("warning.as");
1142 3 : pos.set_function("getWarningSigns");
1143 1 : pos.reset_counters(3);
1144 1 : pos.new_column();
1145 1 : pos.new_column();
1146 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_WARNING, as2js::err_code_t::AS_ERR_FINAL, pos);
1147 1 : msg << "This is the warning message.";
1148 1 : }
1149 :
1150 1 : CATCH_REQUIRE(buffer->empty());
1151 1 : buffer->clear();
1152 : }
1153 :
1154 : {
1155 : {
1156 1 : as2js::position pos;
1157 3 : pos.set_filename("error.as");
1158 3 : pos.set_function("gotMade");
1159 1 : pos.reset_counters(65);
1160 1 : pos.new_column();
1161 1 : pos.new_column();
1162 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_ERROR, as2js::err_code_t::AS_ERR_DIVIDE_BY_ZERO, pos);
1163 1 : msg << "we got a real error here.";
1164 1 : }
1165 :
1166 1 : CATCH_REQUIRE(buffer->empty());
1167 1 : buffer->clear();
1168 : }
1169 :
1170 : {
1171 : {
1172 1 : as2js::position pos;
1173 3 : pos.set_filename("fatal.as");
1174 3 : pos.set_function("done");
1175 1 : pos.reset_counters(789);
1176 1 : pos.new_column();
1177 1 : pos.new_column();
1178 1 : pos.new_column();
1179 1 : pos.new_column();
1180 1 : pos.new_column();
1181 1 : pos.new_column();
1182 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_FATAL, as2js::err_code_t::AS_ERR_NOT_SUPPORTED, pos);
1183 1 : msg << "this is not yet implemented.";
1184 1 : }
1185 :
1186 1 : CATCH_REQUIRE(buffer->empty());
1187 1 : buffer->clear();
1188 : }
1189 :
1190 1 : l->remove_component_to_ignore(snaplogger::g_as2js_component);
1191 :
1192 :
1193 : {
1194 1 : snaplogger::format::pointer_t j(std::make_shared<snaplogger::format>(
1195 1 : "{\"message\":\"${message}\"${fields:format=json:json=start_comma}}"));
1196 1 : buffer->set_format(j);
1197 :
1198 : {
1199 1 : as2js::position pos;
1200 3 : pos.set_filename("json.as");
1201 3 : pos.set_function("convoluted");
1202 1 : pos.reset_counters(11);
1203 1 : pos.new_column();
1204 1 : pos.new_column();
1205 1 : pos.new_column();
1206 1 : pos.new_column();
1207 1 : as2js::message msg(as2js::message_level_t::MESSAGE_LEVEL_ERROR, as2js::err_code_t::AS_ERR_DYNAMIC, pos);
1208 1 : msg << "verify fields using JSON.";
1209 1 : }
1210 :
1211 1 : std::string expected;
1212 1 : expected = "{\"message\":\"json.as:11:5:err:15: verify fields using JSON.\",\"error_code\":\"";
1213 1 : expected += std::to_string(static_cast<int>(as2js::err_code_t::AS_ERR_DYNAMIC));
1214 1 : expected += "\",\"id\":\"";
1215 1 : expected += std::to_string(snaplogger::get_last_message_id());
1216 1 : expected += "\",\"position\":\"json.as:11:5:\"";
1217 1 : expected += "}\n";
1218 1 : CATCH_REQUIRE(buffer->str() == expected);
1219 1 : buffer->clear();
1220 1 : }
1221 :
1222 :
1223 1 : l->reset();
1224 1 : }
1225 1 : CATCH_END_SECTION()
1226 1 : }
1227 :
1228 :
1229 1 : CATCH_TEST_CASE("message_clog", "[message][clog]")
1230 : {
1231 1 : CATCH_START_SECTION("message: send log messages through std::clog with all supported levels")
1232 : {
1233 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
1234 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("clog-buffer"));
1235 :
1236 1 : char const * cargv[] =
1237 : {
1238 : "/usr/bin/daemon",
1239 : nullptr
1240 : };
1241 1 : int const argc(std::size(cargv) - 1);
1242 1 : char ** argv = const_cast<char **>(cargv);
1243 :
1244 1 : advgetopt::options_environment environment_options;
1245 1 : environment_options.f_project_name = "test-logger";
1246 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1247 1 : advgetopt::getopt opts(environment_options);
1248 1 : opts.parse_program_name(argv);
1249 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
1250 :
1251 1 : buffer->set_config(opts);
1252 :
1253 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
1254 1 : "${message} (${severity:format=number})"));
1255 1 : buffer->set_format(f);
1256 :
1257 1 : l->add_appender(buffer);
1258 1 : l->set_severity(snaplogger::severity_t::SEVERITY_ALL);
1259 :
1260 1 : as2js::set_message_level(as2js::message_level_t::MESSAGE_LEVEL_TRACE);
1261 :
1262 : // debug
1263 : //
1264 1 : std::clog << "debug: check with a debug message.\n";
1265 1 : std::string expected;
1266 1 : expected = "check with a debug message. (";
1267 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_DEBUG));
1268 1 : expected += ")\n";
1269 1 : CATCH_REQUIRE(buffer->str() == expected);
1270 1 : buffer->clear();
1271 :
1272 1 : std::clog << "Debug: nice upper to start word.\n";
1273 1 : expected = "nice upper to start word. (";
1274 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_DEBUG));
1275 1 : expected += ")\n";
1276 1 : CATCH_REQUIRE(buffer->str() == expected);
1277 1 : buffer->clear();
1278 :
1279 1 : std::clog << "DEBUG: check that case is ignored.\n";
1280 1 : expected = "check that case is ignored. (";
1281 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_DEBUG));
1282 1 : expected += ")\n";
1283 1 : CATCH_REQUIRE(buffer->str() == expected);
1284 1 : buffer->clear();
1285 :
1286 : // info
1287 : //
1288 1 : std::clog << "info: check with an informational message.\n";
1289 1 : expected = "check with an informational message. (";
1290 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_INFORMATION));
1291 1 : expected += ")\n";
1292 1 : CATCH_REQUIRE(buffer->str() == expected);
1293 1 : buffer->clear();
1294 :
1295 1 : std::clog << "advanced information: word just needs to appear.\n";
1296 1 : expected = "word just needs to appear. (";
1297 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_INFORMATION));
1298 1 : expected += ")\n";
1299 1 : CATCH_REQUIRE(buffer->str() == expected);
1300 1 : buffer->clear();
1301 :
1302 1 : std::clog << "INFO: like with debug, case does not matter.\n";
1303 1 : expected = "like with debug, case does not matter. (";
1304 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_INFORMATION));
1305 1 : expected += ")\n";
1306 1 : CATCH_REQUIRE(buffer->str() == expected);
1307 1 : buffer->clear();
1308 :
1309 : // warning
1310 : //
1311 1 : std::clog << "warning: verify warnings too.\n";
1312 1 : expected = "verify warnings too. (";
1313 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING));
1314 1 : expected += ")\n";
1315 1 : CATCH_REQUIRE(buffer->str() == expected);
1316 1 : buffer->clear();
1317 :
1318 1 : std::clog << "warn: word can be shorten.\n";
1319 1 : expected = "word can be shorten. (";
1320 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING));
1321 1 : expected += ")\n";
1322 1 : CATCH_REQUIRE(buffer->str() == expected);
1323 1 : buffer->clear();
1324 :
1325 : // error
1326 : //
1327 1 : std::clog << "error: this just doesn't work, does it?\n";
1328 1 : expected = "this just doesn't work, does it? (";
1329 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_ERROR));
1330 1 : expected += ")\n";
1331 1 : CATCH_REQUIRE(buffer->str() == expected);
1332 1 : buffer->clear();
1333 :
1334 : // fatal
1335 : //
1336 1 : std::clog << "fatal error: this one is tricky, we have to test fatal first.\n";
1337 1 : expected = "this one is tricky, we have to test fatal first. (";
1338 1 : expected += std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_FATAL));
1339 1 : expected += ")\n";
1340 1 : CATCH_REQUIRE(buffer->str() == expected);
1341 1 : buffer->clear();
1342 :
1343 : // empty line
1344 : //
1345 1 : std::clog << "\n";
1346 1 : CATCH_REQUIRE(buffer->empty());
1347 1 : buffer->clear();
1348 :
1349 :
1350 : // try again when the CLOG component is turned off
1351 : //
1352 1 : l->add_component_to_ignore(snaplogger::g_clog_component);
1353 :
1354 :
1355 : // error
1356 : //
1357 1 : std::clog << "error: clog can be filtered out.\n";
1358 1 : CATCH_REQUIRE(buffer->empty());
1359 1 : buffer->clear();
1360 :
1361 :
1362 1 : l->remove_component_to_ignore(snaplogger::g_clog_component);
1363 :
1364 1 : l->reset();
1365 1 : }
1366 1 : CATCH_END_SECTION()
1367 1 : }
1368 :
1369 :
1370 :
1371 2 : CATCH_TEST_CASE("message_exception", "[message][exception]")
1372 : {
1373 2 : CATCH_START_SECTION("message: Use '... << exception << ...'")
1374 : {
1375 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
1376 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
1377 :
1378 1 : char const * cargv[] =
1379 : {
1380 : "/usr/bin/daemon",
1381 : nullptr
1382 : };
1383 1 : int const argc(std::size(cargv) - 1);
1384 1 : char ** argv = const_cast<char **>(cargv);
1385 :
1386 1 : advgetopt::options_environment environment_options;
1387 1 : environment_options.f_project_name = "test-logger";
1388 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1389 1 : advgetopt::getopt opts(environment_options);
1390 1 : opts.parse_program_name(argv);
1391 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
1392 :
1393 1 : buffer->set_config(opts);
1394 :
1395 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
1396 1 : "${message} (${severity:format=number}) exit code: ${field:name=exception_exit_code}"));
1397 1 : buffer->set_format(f);
1398 :
1399 1 : l->add_appender(buffer);
1400 :
1401 3 : advgetopt::getopt_exit const error("testing an exception -> logging", 123);
1402 :
1403 2 : SNAP_LOG_WARNING
1404 : << "We got an exception! ["
1405 : << error
1406 : << "]"
1407 : << SNAP_LOG_SEND;
1408 :
1409 1 : CATCH_REQUIRE_FALSE(buffer->empty());
1410 :
1411 1 : std::string const expected("We got an exception! [getopt_exception: testing an exception -> logging] ("
1412 2 : + std::to_string(static_cast<int>(::snaplogger::severity_t::SEVERITY_WARNING))
1413 2 : + ") exit code: 123\n");
1414 1 : CATCH_REQUIRE(buffer->str() == expected);
1415 :
1416 1 : buffer->clear();
1417 :
1418 1 : l->reset();
1419 1 : }
1420 2 : CATCH_END_SECTION()
1421 :
1422 2 : CATCH_START_SECTION("message: Use '... << stringstream << ...'")
1423 : {
1424 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
1425 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
1426 :
1427 1 : char const * cargv[] =
1428 : {
1429 : "/usr/bin/daemon",
1430 : nullptr
1431 : };
1432 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
1433 1 : char ** argv = const_cast<char **>(cargv);
1434 :
1435 1 : advgetopt::options_environment environment_options;
1436 1 : environment_options.f_project_name = "test-logger";
1437 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
1438 1 : advgetopt::getopt opts(environment_options);
1439 1 : opts.parse_program_name(argv);
1440 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
1441 :
1442 1 : buffer->set_config(opts);
1443 :
1444 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message} (${severity:format=number})"));
1445 1 : buffer->set_format(f);
1446 :
1447 1 : l->add_appender(buffer);
1448 :
1449 1 : std::stringstream ss;
1450 1 : ss << "testing that we can also \"send\" the content of a string stream";
1451 :
1452 2 : SNAP_LOG_WARNING
1453 : << "We got an exception! ["
1454 : << ss
1455 : << "]"
1456 : << SNAP_LOG_SEND;
1457 :
1458 1 : CATCH_REQUIRE_FALSE(buffer->empty());
1459 :
1460 1 : std::string const expected("We got an exception! [testing that we can also \"send\" the content of a string stream] ("
1461 2 : + std::to_string(static_cast<int>(::snaplogger::severity_t::SEVERITY_WARNING))
1462 2 : + ")\n");
1463 1 : CATCH_REQUIRE(buffer->str() == expected);
1464 :
1465 1 : buffer->clear();
1466 :
1467 1 : l->reset();
1468 1 : }
1469 2 : CATCH_END_SECTION()
1470 2 : }
1471 :
1472 :
1473 :
1474 : // vim: ts=4 sw=4 et
|