Line data Source code
1 : // Copyright (c) 2006-2023 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 : // snaplogger
31 : //
32 : #include <snaplogger/buffer_appender.h>
33 : #include <snaplogger/exception.h>
34 : #include <snaplogger/format.h>
35 : #include <snaplogger/logger.h>
36 : #include <snaplogger/map_diagnostic.h>
37 : #include <snaplogger/severity.h>
38 : #include <snaplogger/version.h>
39 :
40 :
41 : // snapdev
42 : //
43 : #include <snapdev/enum_class_math.h>
44 :
45 :
46 : // advgetopt
47 : //
48 : #include <advgetopt/exception.h>
49 :
50 :
51 : // C
52 : //
53 : #include <math.h>
54 : #include <unistd.h>
55 :
56 :
57 : namespace
58 : {
59 :
60 :
61 1 : std::source_location get_other_loc()
62 : {
63 1 : return std::source_location::current();
64 : }
65 :
66 :
67 :
68 : } // no name namespace
69 :
70 :
71 2 : CATCH_TEST_CASE("not_a_message", "[message]")
72 : {
73 2 : CATCH_START_SECTION("message: Call send_message() with wrong ostream")
74 : {
75 1 : CATCH_REQUIRE_THROWS_MATCHES(
76 : snaplogger::send_message(std::cout)
77 : , snaplogger::not_a_message
78 : , Catch::Matchers::ExceptionMessage(
79 : "logger_error: the 'out' parameter to the send_message() function is expected to be a snaplogger::message object."));
80 : }
81 2 : CATCH_END_SECTION()
82 :
83 2 : CATCH_START_SECTION("message: Print snaplogger::secure to wrong ostream")
84 : {
85 1 : std::stringstream buffer;
86 1 : std::streambuf * old(std::cout.rdbuf(buffer.rdbuf()));
87 1 : std::cout << snaplogger::secure << std::endl;
88 1 : CATCH_REQUIRE(buffer.str() == "(section:secure)\n");
89 1 : std::cout.rdbuf(old);
90 1 : }
91 2 : CATCH_END_SECTION()
92 2 : }
93 :
94 :
95 :
96 2 : CATCH_TEST_CASE("message_capture", "[message]")
97 : {
98 2 : CATCH_START_SECTION("message: Buffering")
99 : {
100 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-logging");
101 :
102 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
103 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
104 :
105 1 : CATCH_REQUIRE(buffer->get_type() == "buffer");
106 :
107 1 : char const * cargv[] =
108 : {
109 : "/usr/bin/daemon",
110 : nullptr
111 : };
112 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
113 1 : char ** argv = const_cast<char **>(cargv);
114 :
115 1 : advgetopt::options_environment environment_options;
116 1 : environment_options.f_project_name = "test-logger";
117 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
118 1 : advgetopt::getopt opts(environment_options);
119 1 : opts.parse_program_name(argv);
120 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
121 :
122 1 : buffer->set_config(opts);
123 :
124 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${severity}: ${message}"));
125 1 : buffer->set_format(f);
126 :
127 1 : l->add_appender(buffer);
128 :
129 1 : SNAP_LOG_ERROR << snaplogger::precise_time << "Logging this error" << SNAP_LOG_SEND;
130 1 : CATCH_REQUIRE(buffer->str() == "error: Logging this error\n");
131 :
132 : // test the other str() function too
133 : //
134 1 : buffer->str("Start: ");
135 :
136 : // show that the "\n" does not get duplicated
137 : //
138 1 : SNAP_LOG_ERROR << "Error with newline\n" << SNAP_LOG_SEND;
139 1 : CATCH_REQUIRE(buffer->str() == "Start: error: Error with newline\n");
140 1 : buffer->clear();
141 :
142 : // show that the "\r\n" gets replaced by "\n"
143 : //
144 1 : SNAP_LOG_ERROR << "Error with CRLF\r\n" << SNAP_LOG_SEND;
145 1 : CATCH_REQUIRE(buffer->str() == "error: Error with CRLF\n");
146 1 : buffer->clear();
147 :
148 : // severity too low, no change to buffer
149 : //
150 1 : SNAP_LOG_DEBUG << "Debug Message " << M_PI << " which does not make it at all...\n" << SNAP_LOG_SEND;
151 1 : CATCH_REQUIRE(buffer->empty());
152 :
153 1 : l->reset();
154 1 : }
155 2 : CATCH_END_SECTION()
156 :
157 2 : CATCH_START_SECTION("message: JSON Buffering")
158 : {
159 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "json-logging");
160 :
161 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
162 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("json-buffer"));
163 :
164 1 : CATCH_REQUIRE(buffer->get_type() == "buffer");
165 :
166 1 : char const * cargv[] =
167 : {
168 : "/usr/bin/daemon",
169 : nullptr
170 : };
171 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
172 1 : char ** argv = const_cast<char **>(cargv);
173 :
174 1 : advgetopt::options_environment environment_options;
175 1 : environment_options.f_project_name = "json-logger";
176 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
177 1 : advgetopt::getopt opts(environment_options);
178 1 : opts.parse_program_name(argv);
179 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
180 :
181 1 : buffer->set_config(opts);
182 :
183 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
184 : "{\"version\":1,"
185 1 : "\"message\":\"${message:escape='\\\r\n\t\"'}\"}"));
186 1 : buffer->set_format(f);
187 :
188 1 : l->add_appender(buffer);
189 :
190 3 : SNAP_LOG_ERROR
191 2 : << SNAP_LOG_FIELD(std::string("format"), std::string("json"))
192 : << "A JSON error message (format:${field:name=format})"
193 : << SNAP_LOG_SEND;
194 1 : CATCH_REQUIRE(buffer->str() == "{\"version\":1,\"message\":\"A JSON error message (format:json)\"}\n");
195 1 : buffer->clear();
196 :
197 : // show that the "\n" does not get duplicated
198 : //
199 4 : SNAP_LOG_ERROR
200 : << "See what happens with a \"quoted string\" within the message (${fields})\n"
201 2 : << SNAP_LOG_FIELD(std::string("format"), std::string("json"))
202 2 : << SNAP_LOG_FIELD(std::string("language"), std::string("js"))
203 : << SNAP_LOG_SEND;
204 3 : std::string const expected(std::regex_replace(buffer->str(), std::regex("\\\\\"id\\\\\":\\\\\"[0-9]+\\\\\","), ""));
205 1 : CATCH_REQUIRE(expected == "{\"version\":1,\"message\":\"See what happens with a \\\"quoted string\\\" within the message ({\\\"format\\\":\\\"json\\\",\\\"language\\\":\\\"js\\\"})\"}\n");
206 1 : buffer->clear();
207 :
208 1 : l->reset();
209 1 : }
210 2 : CATCH_END_SECTION()
211 2 : }
212 :
213 :
214 1 : CATCH_TEST_CASE("message_copy", "[message]")
215 : {
216 1 : CATCH_START_SECTION("message: Copy")
217 : {
218 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-copying");
219 :
220 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
221 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
222 :
223 1 : CATCH_REQUIRE(buffer->get_type() == "buffer");
224 :
225 1 : char const * cargv[] =
226 : {
227 : "/usr/bin/daemon",
228 : nullptr
229 : };
230 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
231 1 : char ** argv = const_cast<char **>(cargv);
232 :
233 1 : advgetopt::options_environment environment_options;
234 1 : environment_options.f_project_name = "test-logger";
235 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
236 1 : advgetopt::getopt opts(environment_options);
237 1 : opts.parse_program_name(argv);
238 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
239 :
240 1 : buffer->set_config(opts);
241 :
242 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
243 1 : buffer->set_format(f);
244 :
245 1 : l->add_appender(buffer);
246 :
247 1 : std::source_location const loc(std::source_location::current());
248 1 : snaplogger::message::pointer_t msg(std::make_shared<snaplogger::message>
249 1 : (::snaplogger::severity_t::SEVERITY_ERROR, loc));
250 :
251 1 : CATCH_REQUIRE(msg->get_filename() == loc.file_name());
252 1 : CATCH_REQUIRE(msg->get_function() == loc.function_name());
253 1 : CATCH_REQUIRE(msg->get_line() == loc.line());
254 1 : CATCH_REQUIRE(msg->get_column() == loc.column());
255 :
256 : // using a standard location
257 : //
258 1 : std::source_location const other_loc(get_other_loc());
259 :
260 1 : CATCH_REQUIRE(msg->get_filename() == loc.file_name());
261 1 : CATCH_REQUIRE(msg->get_function() == loc.function_name());
262 1 : CATCH_REQUIRE(msg->get_line() == loc.line());
263 1 : CATCH_REQUIRE(msg->get_column() == loc.column());
264 :
265 : // direct
266 : //
267 1 : msg->set_filename("we-are-under-control.cpp");
268 1 : msg->set_function("testing_set_function");
269 1 : msg->set_line(123);
270 1 : msg->set_column(64);
271 :
272 1 : CATCH_REQUIRE(msg->get_filename() == "we-are-under-control.cpp");
273 1 : CATCH_REQUIRE(msg->get_function() == "testing_set_function");
274 1 : CATCH_REQUIRE(msg->get_line() == 123);
275 1 : CATCH_REQUIRE(msg->get_column() == 64);
276 :
277 1 : *msg << "Logging an error.";
278 :
279 1 : CATCH_REQUIRE(msg->str() == "Logging an error.");
280 :
281 1 : snaplogger::message::pointer_t copy(std::make_shared<snaplogger::message>(*msg, *msg));
282 :
283 1 : CATCH_REQUIRE(msg->str() == "Logging an error.");
284 1 : CATCH_REQUIRE(copy->str() == "Logging an error.");
285 :
286 : // no destructor called, the output is still empty
287 : //
288 1 : CATCH_REQUIRE(buffer->empty());
289 :
290 1 : copy.reset();
291 :
292 : // msg not lost
293 : //
294 1 : CATCH_REQUIRE(msg->str() == "Logging an error.");
295 :
296 : // destructor against copy does not trigger send_message()
297 : //
298 1 : CATCH_REQUIRE(buffer->empty());
299 :
300 1 : snaplogger::send_message(*msg);
301 :
302 : // now we get the message as expected!
303 : //
304 : // (note that internally we can skip receiving the message on the
305 : // original, but not as a client... we may want to have the ability
306 : // to cancel a message, though.)
307 : //
308 1 : CATCH_REQUIRE(buffer->str() == "Logging an error.\n");
309 :
310 1 : msg.reset();
311 :
312 1 : CATCH_REQUIRE(buffer->str() == "Logging an error.\n");
313 :
314 1 : l->reset();
315 1 : }
316 1 : CATCH_END_SECTION()
317 1 : }
318 :
319 :
320 2 : CATCH_TEST_CASE("message_severity", "[message][severity]")
321 : {
322 2 : CATCH_START_SECTION("message: Appender vs Message severity")
323 : {
324 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-severity");
325 :
326 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
327 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
328 :
329 1 : char const * cargv[] =
330 : {
331 : "/usr/bin/daemon",
332 : nullptr
333 : };
334 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
335 1 : char ** argv = const_cast<char **>(cargv);
336 :
337 1 : advgetopt::options_environment environment_options;
338 1 : environment_options.f_project_name = "test-logger";
339 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
340 1 : advgetopt::getopt opts(environment_options);
341 1 : opts.parse_program_name(argv);
342 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
343 :
344 1 : buffer->set_config(opts);
345 :
346 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
347 1 : buffer->set_format(f);
348 :
349 1 : l->add_appender(buffer);
350 :
351 : // ++<enum> works here because of this header:
352 : // <snapdev/enum_class_math.h>
353 : //
354 257 : for(snaplogger::severity_t i(snaplogger::severity_t::SEVERITY_MIN); i <= snaplogger::severity_t::SEVERITY_MAX; ++i)
355 : {
356 256 : buffer->set_severity(i);
357 65792 : for(snaplogger::severity_t j(snaplogger::severity_t::SEVERITY_MIN); j <= snaplogger::severity_t::SEVERITY_MAX; ++j)
358 : {
359 65536 : snaplogger::send_message(*::snaplogger::create_message(j)
360 : << "The message itself");
361 :
362 65536 : if(j >= i
363 32896 : && i != snaplogger::severity_t::SEVERITY_OFF
364 32895 : && j != snaplogger::severity_t::SEVERITY_OFF)
365 : {
366 32640 : CATCH_REQUIRE(buffer->str() == "The message itself\n");
367 32640 : }
368 : else
369 : {
370 32896 : CATCH_REQUIRE(buffer->empty());
371 : }
372 65536 : buffer->clear();
373 : }
374 : }
375 :
376 1 : l->reset();
377 1 : }
378 2 : CATCH_END_SECTION()
379 :
380 2 : CATCH_START_SECTION("message: Changing message severity (takes about 3.5min)")
381 : {
382 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-copying");
383 :
384 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
385 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
386 :
387 1 : char const * cargv[] =
388 : {
389 : "/usr/bin/daemon",
390 : nullptr
391 : };
392 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
393 1 : char ** argv = const_cast<char **>(cargv);
394 :
395 1 : advgetopt::options_environment environment_options;
396 1 : environment_options.f_project_name = "test-logger";
397 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
398 1 : advgetopt::getopt opts(environment_options);
399 1 : opts.parse_program_name(argv);
400 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
401 :
402 1 : buffer->set_config(opts);
403 :
404 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
405 1 : buffer->set_format(f);
406 :
407 1 : l->add_appender(buffer);
408 :
409 : // <enum> += n works here because of this header:
410 : // <snapdev/enum_class_math.h>
411 : //
412 30 : for(snaplogger::severity_t i(snaplogger::severity_t::SEVERITY_MIN); i <= snaplogger::severity_t::SEVERITY_MAX; i += 1 + (rand() & 15))
413 : {
414 29 : buffer->set_severity(i);
415 956 : for(snaplogger::severity_t j(snaplogger::severity_t::SEVERITY_MIN); j <= snaplogger::severity_t::SEVERITY_MAX; j += 1 + (rand() & 15))
416 : {
417 29388 : for(snaplogger::severity_t k(snaplogger::severity_t::SEVERITY_MIN); k <= snaplogger::severity_t::SEVERITY_MAX; k += 1 + (rand() & 15))
418 : {
419 28461 : ::snaplogger::message::pointer_t msg(std::make_shared<::snaplogger::message>(j));
420 28461 : *msg << "Start of message";
421 28461 : msg->set_severity(k);
422 28461 : *msg << " -- end of message";
423 28461 : snaplogger::send_message(*msg);
424 : //std::cerr << "checking with " << i << ", " << j << ", " << k << "\n";
425 :
426 28461 : if(j >= i
427 13669 : && k >= i
428 9130 : && i != snaplogger::severity_t::SEVERITY_OFF
429 9130 : && j != snaplogger::severity_t::SEVERITY_OFF)
430 : //&& k != snaplogger::severity_t::SEVERITY_OFF)
431 : {
432 9099 : if(j >= i)
433 : {
434 9099 : CATCH_REQUIRE(buffer->str() == "Start of message -- end of message\n");
435 : }
436 : else
437 : {
438 0 : CATCH_REQUIRE(buffer->str() == "Start of message\n");
439 : }
440 9099 : }
441 : else
442 : {
443 19362 : CATCH_REQUIRE(buffer->empty());
444 : }
445 28461 : buffer->clear();
446 28461 : }
447 : }
448 : }
449 :
450 1 : l->reset();
451 1 : }
452 2 : CATCH_END_SECTION()
453 2 : }
454 :
455 :
456 4 : CATCH_TEST_CASE("message_format", "[message][format]")
457 : {
458 4 : CATCH_START_SECTION("message: Recursivity")
459 : {
460 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "basic-format");
461 :
462 : // these two are not called in this test
463 : //
464 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROJECT_NAME, "test-logger");
465 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_VERSION, "5.32.1024");
466 :
467 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
468 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
469 :
470 1 : char const * cargv[] =
471 : {
472 : "/usr/bin/daemon",
473 : nullptr
474 : };
475 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
476 1 : char ** argv = const_cast<char **>(cargv);
477 :
478 1 : advgetopt::options_environment environment_options;
479 1 : environment_options.f_project_name = "test-logger";
480 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
481 1 : environment_options.f_version = "5.32.1024";
482 1 : advgetopt::getopt opts(environment_options);
483 1 : opts.parse_program_name(argv);
484 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
485 :
486 1 : buffer->set_config(opts);
487 :
488 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${project_name} ${message} v${version}"));
489 1 : buffer->set_format(f);
490 :
491 1 : l->add_appender(buffer);
492 :
493 1 : SNAP_LOG_WARNING
494 : << "Message Project Name = ${project_name} and Version = ${version} -- uses \"recursive\""
495 : << SNAP_LOG_SEND;
496 :
497 1 : CATCH_REQUIRE(buffer->str() ==
498 : "test-logger Message Project Name = test-logger and"
499 : " Version = 5.32.1024 -- uses \"recursive\" v5.32.1024"
500 : "\n");
501 :
502 1 : l->reset();
503 1 : }
504 4 : CATCH_END_SECTION()
505 :
506 4 : CATCH_START_SECTION("message: ${message} itself is not recursive")
507 : {
508 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "prevent-infinite-loop");
509 :
510 : // these two are not called in this test
511 : //
512 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROJECT_NAME, "test-logger");
513 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_VERSION, "5.32.1024");
514 :
515 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
516 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
517 :
518 1 : char const * cargv[] =
519 : {
520 : "/usr/bin/daemon",
521 : nullptr
522 : };
523 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
524 1 : char ** argv = const_cast<char **>(cargv);
525 :
526 1 : advgetopt::options_environment environment_options;
527 1 : environment_options.f_project_name = "test-logger";
528 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
529 1 : environment_options.f_version = "5.32.1024";
530 1 : advgetopt::getopt opts(environment_options);
531 1 : opts.parse_program_name(argv);
532 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
533 :
534 1 : buffer->set_config(opts);
535 :
536 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${project_name} ${message} v${version}"));
537 1 : buffer->set_format(f);
538 :
539 1 : l->add_appender(buffer);
540 :
541 1 : SNAP_LOG_WARNING
542 : << "Message ${message} says: Project Name = ${project_name} and Version = ${version} -- uses \"recursive\""
543 : << SNAP_LOG_SEND;
544 :
545 1 : CATCH_REQUIRE(buffer->str() ==
546 : "test-logger Message says: Project Name = test-logger and"
547 : " Version = 5.32.1024 -- uses \"recursive\" v5.32.1024"
548 : "\n");
549 :
550 1 : buffer->clear();
551 :
552 1 : snaplogger::unset_diagnostic(snaplogger::DIAG_KEY_VERSION);
553 :
554 1 : SNAP_LOG_WARNING
555 : << "Removed the version: ${message} says: Project Name = ${project_name} and Version = ${version} -- uses \"recursive\""
556 : << SNAP_LOG_SEND;
557 :
558 1 : CATCH_REQUIRE(buffer->str() ==
559 : "test-logger Removed the version: says: Project Name = test-logger and"
560 : " Version = -- uses \"recursive\" v"
561 : "\n");
562 :
563 1 : l->reset();
564 1 : }
565 4 : CATCH_END_SECTION()
566 :
567 4 : CATCH_START_SECTION("message: ${pid} uses the get_environment() function")
568 : {
569 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "get-environment");
570 :
571 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
572 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
573 :
574 1 : char const * cargv[] =
575 : {
576 : "/usr/bin/daemon",
577 : nullptr
578 : };
579 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
580 1 : char ** argv = const_cast<char **>(cargv);
581 :
582 1 : advgetopt::options_environment environment_options;
583 1 : environment_options.f_project_name = "test-logger";
584 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
585 1 : advgetopt::getopt opts(environment_options);
586 1 : opts.parse_program_name(argv);
587 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
588 :
589 1 : buffer->set_config(opts);
590 :
591 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
592 1 : buffer->set_format(f);
593 :
594 1 : l->add_appender(buffer);
595 :
596 1 : SNAP_LOG_WARNING
597 : << "Test PID = ${pid} == ${pid:running}"
598 : << SNAP_LOG_SEND;
599 :
600 1 : CATCH_REQUIRE(buffer->str() ==
601 : "Test PID = " + std::to_string(getpid())
602 : + " == " + std::to_string(getpid())
603 : + "\n");
604 :
605 1 : l->reset();
606 1 : }
607 4 : CATCH_END_SECTION()
608 :
609 4 : CATCH_START_SECTION("message: Verify year")
610 : {
611 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "get-environment");
612 :
613 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
614 1 : CATCH_REQUIRE(l->get_appender("test-buffer") == nullptr);
615 :
616 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
617 :
618 1 : char const * cargv[] =
619 : {
620 : "/usr/bin/daemon",
621 : nullptr
622 : };
623 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
624 1 : char ** argv = const_cast<char **>(cargv);
625 :
626 1 : advgetopt::options_environment environment_options;
627 1 : environment_options.f_project_name = "test-logger";
628 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
629 1 : advgetopt::getopt opts(environment_options);
630 1 : opts.parse_program_name(argv);
631 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
632 :
633 1 : buffer->set_config(opts);
634 :
635 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message}"));
636 1 : buffer->set_format(f);
637 :
638 1 : l->add_appender(buffer);
639 :
640 1 : CATCH_REQUIRE(l->get_appender("test-buffer") == buffer);
641 :
642 : // we create a message so we can check the timestamp in our test
643 : //
644 1 : snaplogger::message::pointer_t msg(std::make_shared<snaplogger::message>
645 1 : (::snaplogger::severity_t::SEVERITY_ERROR));
646 1 : *msg << "Created message on YYYY = ${date:year}, MM = ${date:month}, DD = ${date:day}";
647 :
648 1 : timespec const stamp(msg->get_timestamp());
649 :
650 1 : snaplogger::send_message(*msg);
651 :
652 1 : tm t;
653 1 : gmtime_r(&stamp.tv_sec, &t);
654 1 : char year[16];
655 1 : char month[16];
656 1 : char day[16];
657 1 : strftime(year, 16, "%Y", &t);
658 1 : strftime(month, 16, "%m", &t);
659 1 : strftime(day, 16, "%d", &t);
660 :
661 1 : CATCH_REQUIRE(buffer->str() ==
662 : std::string("Created message on YYYY = ")
663 : + year
664 : + ", MM = "
665 : + std::to_string(std::atoi(month)) // remove the leading '0' if necessary
666 : + ", DD = "
667 : + std::to_string(std::atoi(day)) // remove the leading '0' if necessary
668 : + "\n");
669 :
670 1 : l->reset();
671 1 : }
672 4 : CATCH_END_SECTION()
673 4 : }
674 :
675 :
676 1 : CATCH_TEST_CASE("message_component_filter", "[message][component]")
677 : {
678 1 : CATCH_START_SECTION("message: Filter Message with Component")
679 : {
680 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "component-filter");
681 :
682 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
683 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
684 :
685 1 : char const * cargv[] =
686 : {
687 : "/usr/bin/daemon",
688 : nullptr
689 : };
690 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
691 1 : char ** argv = const_cast<char **>(cargv);
692 :
693 1 : advgetopt::options_environment environment_options;
694 1 : environment_options.f_project_name = "test-logger";
695 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
696 1 : advgetopt::getopt opts(environment_options);
697 1 : opts.parse_program_name(argv);
698 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
699 :
700 1 : buffer->set_config(opts);
701 :
702 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message} (${severity:format=number})"));
703 1 : buffer->set_format(f);
704 :
705 1 : l->add_appender(buffer);
706 :
707 2 : SNAP_LOG_WARNING
708 1 : << snaplogger::secure // mark as a secure message
709 : << "This message is secure but not the buffer"
710 : << SNAP_LOG_SEND;
711 :
712 1 : CATCH_REQUIRE(buffer->empty());
713 :
714 2 : SNAP_LOG_WARNING
715 1 : << "Test number: "
716 : << 2
717 1 : << " with buffer still unsecure..."
718 1 : << SNAP_LOG_SEND_SECURELY; // mark at the end
719 :
720 1 : CATCH_REQUIRE(buffer->empty());
721 :
722 : // mark the buffer as a secure buffer now
723 : //
724 1 : buffer->add_component(snaplogger::g_secure_component);
725 :
726 2 : SNAP_LOG_WARNING
727 1 : << snaplogger::secure // mark as a secure message
728 : << "This message is secure and so is the buffer"
729 : << SNAP_LOG_SEND;
730 :
731 : // TODO: get the WARNING severity level dynamically
732 1 : std::string const expected1("This message is secure and so is the buffer ("
733 3 : + std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING))
734 2 : + ")\n");
735 1 : CATCH_REQUIRE(buffer->str() == expected1);
736 :
737 1 : buffer->clear();
738 :
739 2 : SNAP_LOG_WARNING
740 1 : << "Test number: "
741 : << 4
742 1 : << " with secure buffer...\r\n"
743 1 : << SNAP_LOG_SEND_SECURELY; // mark at the end
744 :
745 : // TODO: get the WARNING severity level dynamically
746 1 : std::string const expected2("Test number: 4 with secure buffer... ("
747 3 : + std::to_string(static_cast<int>(snaplogger::severity_t::SEVERITY_WARNING))
748 2 : + ")\n");
749 1 : CATCH_REQUIRE(buffer->str() == expected2);
750 :
751 1 : l->reset();
752 1 : }
753 1 : CATCH_END_SECTION()
754 1 : }
755 :
756 :
757 :
758 2 : CATCH_TEST_CASE("message_exception", "[message][exception]")
759 : {
760 2 : CATCH_START_SECTION("message: Use '... << exception << ...'")
761 : {
762 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
763 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
764 :
765 1 : char const * cargv[] =
766 : {
767 : "/usr/bin/daemon",
768 : nullptr
769 : };
770 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
771 1 : char ** argv = const_cast<char **>(cargv);
772 :
773 1 : advgetopt::options_environment environment_options;
774 1 : environment_options.f_project_name = "test-logger";
775 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
776 1 : advgetopt::getopt opts(environment_options);
777 1 : opts.parse_program_name(argv);
778 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
779 :
780 1 : buffer->set_config(opts);
781 :
782 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>(
783 1 : "${message} (${severity:format=number}) exit code: ${field:name=exception_exit_code}"));
784 1 : buffer->set_format(f);
785 :
786 1 : l->add_appender(buffer);
787 :
788 3 : advgetopt::getopt_exit const error("testing an exception -> logging", 123);
789 :
790 1 : SNAP_LOG_WARNING
791 : << "We got an exception! ["
792 : << error
793 : << "]"
794 : << SNAP_LOG_SEND;
795 :
796 1 : CATCH_REQUIRE_FALSE(buffer->empty());
797 :
798 1 : std::string const expected("We got an exception! [getopt_exception: testing an exception -> logging] ("
799 3 : + std::to_string(static_cast<int>(::snaplogger::severity_t::SEVERITY_WARNING))
800 2 : + ") exit code: 123\n");
801 1 : CATCH_REQUIRE(buffer->str() == expected);
802 :
803 1 : buffer->clear();
804 :
805 1 : l->reset();
806 1 : }
807 2 : CATCH_END_SECTION()
808 :
809 2 : CATCH_START_SECTION("message: Use '... << stringstream << ...'")
810 : {
811 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
812 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
813 :
814 1 : char const * cargv[] =
815 : {
816 : "/usr/bin/daemon",
817 : nullptr
818 : };
819 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
820 1 : char ** argv = const_cast<char **>(cargv);
821 :
822 1 : advgetopt::options_environment environment_options;
823 1 : environment_options.f_project_name = "test-logger";
824 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
825 1 : advgetopt::getopt opts(environment_options);
826 1 : opts.parse_program_name(argv);
827 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
828 :
829 1 : buffer->set_config(opts);
830 :
831 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message} (${severity:format=number})"));
832 1 : buffer->set_format(f);
833 :
834 1 : l->add_appender(buffer);
835 :
836 1 : std::stringstream ss;
837 1 : ss << "testing that we can also \"send\" the content of a string stream";
838 :
839 1 : SNAP_LOG_WARNING
840 : << "We got an exception! ["
841 : << ss
842 : << "]"
843 : << SNAP_LOG_SEND;
844 :
845 1 : CATCH_REQUIRE_FALSE(buffer->empty());
846 :
847 1 : std::string const expected("We got an exception! [testing that we can also \"send\" the content of a string stream] ("
848 3 : + std::to_string(static_cast<int>(::snaplogger::severity_t::SEVERITY_WARNING))
849 2 : + ")\n");
850 1 : CATCH_REQUIRE(buffer->str() == expected);
851 :
852 1 : buffer->clear();
853 :
854 1 : l->reset();
855 1 : }
856 2 : CATCH_END_SECTION()
857 2 : }
858 :
859 :
860 :
861 : // vim: ts=4 sw=4 et
|