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