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 : // self
21 : //
22 : #include "catch_main.h"
23 :
24 :
25 : // snaplogger lib
26 : //
27 : #include <snaplogger/buffer_appender.h>
28 : #include <snaplogger/exception.h>
29 : #include <snaplogger/format.h>
30 : #include <snaplogger/logger.h>
31 : #include <snaplogger/map_diagnostic.h>
32 : #include <snaplogger/message.h>
33 : #include <snaplogger/severity.h>
34 : #include <snaplogger/version.h>
35 :
36 :
37 : // C lib
38 : //
39 : #include <unistd.h>
40 : #include <netdb.h>
41 : #include <sys/param.h>
42 :
43 :
44 :
45 :
46 :
47 1 : CATCH_TEST_CASE("variable_param", "[variable][param][error]")
48 : {
49 1 : CATCH_START_SECTION("variable: Param Name is Mandatory")
50 : {
51 4 : CATCH_REQUIRE_THROWS_MATCHES(
52 : new snaplogger::param(std::string())
53 : , snaplogger::invalid_parameter
54 : , Catch::Matchers::ExceptionMessage(
55 : "logger_error: a parameter must have a non-empty name."));
56 : }
57 1 : CATCH_END_SECTION()
58 1 : }
59 :
60 :
61 :
62 7 : CATCH_TEST_CASE("system_variable", "[variable][param]")
63 : {
64 7 : CATCH_START_SECTION("variable: get_type() to use padding as integer or string (hostname)")
65 : {
66 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-logging");
67 :
68 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
69 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
70 :
71 1 : char const * cargv[] =
72 : {
73 : "/usr/bin/daemon",
74 : nullptr
75 : };
76 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
77 1 : char ** argv = const_cast<char **>(cargv);
78 :
79 1 : advgetopt::options_environment environment_options;
80 1 : environment_options.f_project_name = "test-logger";
81 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
82 1 : advgetopt::getopt opts(environment_options);
83 1 : opts.parse_program_name(argv);
84 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
85 :
86 1 : buffer->set_config(opts);
87 :
88 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${hostname:padding=3:align=right:min_width=30} ${message}"));
89 1 : buffer->set_format(f);
90 :
91 1 : l->add_appender(buffer);
92 :
93 1 : char host[HOST_NAME_MAX + 2 + 30];
94 1 : CATCH_REQUIRE(gethostname(host, HOST_NAME_MAX + 1) == 0);
95 1 : host[HOST_NAME_MAX + 1] = '\0';
96 2 : std::string aligned(host);
97 24 : while(aligned.length() < 30)
98 : {
99 23 : aligned = "3" + aligned;
100 : }
101 :
102 1 : SNAP_LOG_ERROR << "Check the param::get_type()" << SNAP_LOG_SEND;
103 1 : CATCH_REQUIRE(buffer->str() == aligned + " Check the param::get_type()\n");
104 :
105 1 : buffer->clear();
106 :
107 1 : f = std::make_shared<snaplogger::format>("${hostname:padding=\"t\":align=center:min_width=30} ${message}");
108 1 : buffer->set_format(f);
109 :
110 1 : aligned = host;
111 1 : std::string::size_type const low((30 - aligned.length()) / 2 + aligned.length());
112 12 : while(aligned.length() < low)
113 : {
114 11 : aligned = "t" + aligned;
115 : }
116 13 : while(aligned.length() < 30)
117 : {
118 12 : aligned = aligned + "t";
119 : }
120 :
121 1 : SNAP_LOG_ERROR << "Try again with a string" << SNAP_LOG_SEND;
122 1 : CATCH_REQUIRE(buffer->str() == aligned + " Try again with a string\n");
123 :
124 1 : buffer->clear();
125 :
126 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"t\":align=center:max_width=30}");
127 1 : buffer->set_format(f);
128 :
129 1 : SNAP_LOG_ERROR << "This message will have a maximum width of 30 chars" << SNAP_LOG_SEND;
130 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " ge will have a maximum width o\n");
131 :
132 1 : buffer->clear();
133 :
134 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"t\":align=right:max_width=25}");
135 1 : buffer->set_format(f);
136 :
137 1 : SNAP_LOG_ERROR << "This message will have a maximum width of 25 chars" << SNAP_LOG_SEND;
138 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " maximum width of 25 chars\n");
139 :
140 1 : buffer->clear();
141 :
142 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"t\":align=center:min_width=25}");
143 1 : buffer->set_format(f);
144 :
145 1 : SNAP_LOG_ERROR << "minimum width 25" << SNAP_LOG_SEND;
146 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " ttttminimum width 25ttttt\n");
147 :
148 1 : buffer->clear();
149 :
150 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"t\":align=left:min_width=25}");
151 1 : buffer->set_format(f);
152 :
153 1 : SNAP_LOG_ERROR << "minimum width 25" << SNAP_LOG_SEND;
154 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " minimum width 25ttttttttt\n");
155 :
156 1 : buffer->clear();
157 :
158 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"t\":align=left:exact_width=25}");
159 1 : buffer->set_format(f);
160 :
161 1 : SNAP_LOG_ERROR << "First we get this message cut to the specified width." << SNAP_LOG_SEND;
162 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " First we get this message\n");
163 :
164 1 : buffer->clear();
165 :
166 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"t\":align=center:exact_width=25}");
167 1 : buffer->set_format(f);
168 :
169 1 : SNAP_LOG_ERROR << "First we get this message cut to the specified width." << SNAP_LOG_SEND;
170 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " his message cut to the sp\n");
171 :
172 1 : buffer->clear();
173 :
174 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"t\":align=right:exact_width=25}");
175 1 : buffer->set_format(f);
176 :
177 1 : SNAP_LOG_ERROR << "First we get this message cut to the specified width." << SNAP_LOG_SEND;
178 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " t to the specified width.\n");
179 :
180 1 : buffer->clear();
181 :
182 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"x\":align=left:exact_width=25}");
183 1 : buffer->set_format(f);
184 :
185 1 : SNAP_LOG_ERROR << "Small Message" << SNAP_LOG_SEND;
186 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " Small Messagexxxxxxxxxxxx\n");
187 :
188 1 : buffer->clear();
189 :
190 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"x\":align=center:exact_width=25}");
191 1 : buffer->set_format(f);
192 :
193 1 : SNAP_LOG_ERROR << "Small Message" << SNAP_LOG_SEND;
194 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " xxxxxxSmall Messagexxxxxx\n");
195 :
196 1 : buffer->clear();
197 :
198 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"x\":align=center:exact_width=25}");
199 1 : buffer->set_format(f);
200 :
201 1 : SNAP_LOG_ERROR << "Small Message (even)" << SNAP_LOG_SEND;
202 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " xxSmall Message (even)xxx\n");
203 :
204 1 : buffer->clear();
205 :
206 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:padding=\"x\":align=right:exact_width=25}");
207 1 : buffer->set_format(f);
208 :
209 1 : SNAP_LOG_ERROR << "Small Message" << SNAP_LOG_SEND;
210 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " xxxxxxxxxxxxSmall Message\n");
211 :
212 1 : buffer->clear();
213 :
214 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:prepend=\"(P) \":padding=\"z\":align=right:exact_width=25}");
215 1 : buffer->set_format(f);
216 :
217 1 : SNAP_LOG_ERROR << "Small Message" << SNAP_LOG_SEND;
218 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " zzzzzzzz(P) Small Message\n");
219 :
220 1 : buffer->clear();
221 :
222 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:append=\" (A)\":padding=\"z\":align=right:exact_width=25}");
223 1 : buffer->set_format(f);
224 :
225 1 : SNAP_LOG_ERROR << "Small Message" << SNAP_LOG_SEND;
226 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " zzzzzzzzSmall Message (A)\n");
227 :
228 1 : buffer->clear();
229 :
230 1 : f = std::make_shared<snaplogger::format>("${hostname:padding=\"q\":align=101:min_width=30} ${message}");
231 1 : buffer->set_format(f);
232 :
233 1 : snaplogger::message::pointer_t msg(std::make_shared<snaplogger::message>
234 1 : (::snaplogger::severity_t::SEVERITY_ERROR));
235 1 : *msg << "The align=101 parameter is the wrong type";
236 1 : CATCH_REQUIRE_THROWS_MATCHES(
237 : l->log_message(*msg)
238 : , snaplogger::invalid_parameter
239 : , Catch::Matchers::ExceptionMessage(
240 : "logger_error: the ${...:align=<value>} parameter must be a valid string (not an integer)."));
241 :
242 : // this is important here because we want to make sure that the
243 : // `message` destructor works as expected (i.e. it does not call
244 : // std::terminate() because of the throw as the align=101 is
245 : // invalid)
246 : //
247 1 : msg.reset();
248 :
249 1 : buffer->clear();
250 :
251 1 : f = std::make_shared<snaplogger::format>("${hostname:padding=\"t\":align=justify:min_width=30} ${message}");
252 1 : buffer->set_format(f);
253 :
254 1 : msg = std::make_shared<snaplogger::message>
255 1 : (::snaplogger::severity_t::SEVERITY_ERROR);
256 1 : *msg << "Try align=\"justify\" which has to fail.";
257 1 : CATCH_REQUIRE_THROWS_MATCHES(
258 : l->log_message(*msg)
259 : , snaplogger::invalid_parameter
260 : , Catch::Matchers::ExceptionMessage(
261 : "logger_error: the ${...:align=left|center|right} was expected, got \"justify\"."));
262 :
263 1 : buffer->clear();
264 :
265 1 : f = std::make_shared<snaplogger::format>("${hostname:padding=\"q\":align=left:min_width=wide} ${message}");
266 1 : buffer->set_format(f);
267 :
268 1 : msg = std::make_shared<snaplogger::message>
269 1 : (::snaplogger::severity_t::SEVERITY_ERROR);
270 1 : *msg << "The min_width=wide parameter is the wrong type";
271 1 : CATCH_REQUIRE_THROWS_MATCHES(
272 : l->log_message(*msg)
273 : , snaplogger::invalid_parameter
274 : , Catch::Matchers::ExceptionMessage(
275 : "logger_error: the ${...:min_width=<value>} parameter must be a valid integer."));
276 :
277 : // this is important here because we want to make sure that the
278 : // `message` destructor works as expected (i.e. it does not call
279 : // std::terminate() because of the throw as the align=101 is
280 : // invalid)
281 : //
282 1 : msg.reset();
283 :
284 1 : buffer->clear();
285 :
286 1 : f = std::make_shared<snaplogger::format>("${hostname:padding=99:align=left:min_width=wide} ${message}");
287 1 : buffer->set_format(f);
288 :
289 1 : msg = std::make_shared<snaplogger::message>
290 1 : (::snaplogger::severity_t::SEVERITY_ERROR);
291 1 : *msg << "The padding=... accepts a number between 0 and 9 inclusive";
292 1 : CATCH_REQUIRE_THROWS_MATCHES(
293 : l->log_message(*msg)
294 : , snaplogger::invalid_parameter
295 : , Catch::Matchers::ExceptionMessage(
296 : "logger_error: the ${...:padding=<value>} when set to a number must be one digit ('0' to '9'), not \"99\"."));
297 :
298 : // this is important here because we want to make sure that the
299 : // `message` destructor works as expected (i.e. it does not call
300 : // std::terminate() because of the throw as the align=101 is
301 : // invalid)
302 : //
303 1 : msg.reset();
304 :
305 1 : buffer->clear();
306 :
307 1 : f = std::make_shared<snaplogger::format>("${hostname:padding='abc':align=left:min_width=wide} ${message}");
308 1 : buffer->set_format(f);
309 :
310 1 : msg = std::make_shared<snaplogger::message>
311 1 : (::snaplogger::severity_t::SEVERITY_ERROR);
312 1 : *msg << "The padding=... accepts one character";
313 1 : CATCH_REQUIRE_THROWS_MATCHES(
314 : l->log_message(*msg)
315 : , snaplogger::invalid_parameter
316 : , Catch::Matchers::ExceptionMessage(
317 : "logger_error: the ${...:padding=' '} must be exactly one character, not \"abc\"."));
318 :
319 : // this is important here because we want to make sure that the
320 : // `message` destructor works as expected (i.e. it does not call
321 : // std::terminate() because of the throw as the align=101 is
322 : // invalid)
323 : //
324 1 : msg.reset();
325 :
326 1 : l->reset();
327 1 : }
328 7 : CATCH_END_SECTION()
329 :
330 7 : CATCH_START_SECTION("variable: escape")
331 : {
332 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "escape");
333 :
334 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
335 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
336 :
337 1 : char const * cargv[] =
338 : {
339 : "/usr/bin/daemon",
340 : nullptr
341 : };
342 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
343 1 : char ** argv = const_cast<char **>(cargv);
344 :
345 1 : advgetopt::options_environment environment_options;
346 1 : environment_options.f_project_name = "test-logger";
347 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
348 1 : advgetopt::getopt opts(environment_options);
349 1 : opts.parse_program_name(argv);
350 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
351 :
352 1 : buffer->set_config(opts);
353 :
354 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${hostname} ${message:escape}"));
355 1 : buffer->set_format(f);
356 :
357 1 : l->add_appender(buffer);
358 :
359 1 : char host[HOST_NAME_MAX + 2 + 30];
360 1 : CATCH_REQUIRE(gethostname(host, HOST_NAME_MAX + 1) == 0);
361 1 : host[HOST_NAME_MAX + 1] = '\0';
362 :
363 1 : SNAP_LOG_ERROR << "Default escape for newline (\n), carriage return (\r), and tab (\t)" << SNAP_LOG_SEND;
364 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " Default escape for newline (\\n), carriage return (\\r), and tab (\\t)\n");
365 :
366 1 : buffer->clear();
367 :
368 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:escape=\"[]\"}");
369 1 : buffer->set_format(f);
370 :
371 1 : SNAP_LOG_ERROR << "Try again [with a string]" << SNAP_LOG_SEND;
372 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " Try again \\[with a string\\]\n");
373 :
374 1 : buffer->clear();
375 :
376 1 : f = std::make_shared<snaplogger::format>("${hostname} ${message:escape=\"\a\b\f\n\r\t\v\x1f\xC2\x88\xC2\x97\"}");
377 1 : buffer->set_format(f);
378 :
379 1 : SNAP_LOG_ERROR << "Escape all \a\b\f\n\r\t\v\x1f\xC2\x88\xC2\x97 types" << SNAP_LOG_SEND;
380 1 : CATCH_REQUIRE(buffer->str() == std::string(host) + " Escape all \\a\\b\\f\\n\\r\\t\\v^_@H@W types\n");
381 1 : }
382 7 : CATCH_END_SECTION()
383 :
384 7 : CATCH_START_SECTION("variable: caps")
385 : {
386 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "caps");
387 :
388 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
389 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
390 :
391 1 : char const * cargv[] =
392 : {
393 : "/usr/bin/daemon",
394 : nullptr
395 : };
396 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
397 1 : char ** argv = const_cast<char **>(cargv);
398 :
399 1 : advgetopt::options_environment environment_options;
400 1 : environment_options.f_project_name = "test-logger";
401 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
402 1 : advgetopt::getopt opts(environment_options);
403 1 : opts.parse_program_name(argv);
404 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
405 :
406 1 : buffer->set_config(opts);
407 :
408 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message:caps}"));
409 1 : buffer->set_format(f);
410 :
411 1 : l->add_appender(buffer);
412 :
413 1 : SNAP_LOG_ERROR << "this message words will get their FIRST-LETTER capitalized." << SNAP_LOG_SEND;
414 1 : CATCH_REQUIRE(buffer->str() == "This Message Words Will Get Their First-Letter Capitalized.\n");
415 1 : }
416 7 : CATCH_END_SECTION()
417 :
418 7 : CATCH_START_SECTION("variable: lower/upper")
419 : {
420 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "case");
421 :
422 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
423 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
424 :
425 1 : char const * cargv[] =
426 : {
427 : "/usr/bin/daemon",
428 : nullptr
429 : };
430 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
431 1 : char ** argv = const_cast<char **>(cargv);
432 :
433 1 : advgetopt::options_environment environment_options;
434 1 : environment_options.f_project_name = "test-logger";
435 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
436 1 : advgetopt::getopt opts(environment_options);
437 1 : opts.parse_program_name(argv);
438 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
439 :
440 1 : buffer->set_config(opts);
441 :
442 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${message:lower}"));
443 1 : buffer->set_format(f);
444 :
445 1 : l->add_appender(buffer);
446 :
447 1 : SNAP_LOG_ERROR << "This message words will get their FIRST-LETTER capitalized." << SNAP_LOG_SEND;
448 1 : CATCH_REQUIRE(buffer->str() == "this message words will get their first-letter capitalized.\n");
449 :
450 1 : buffer->clear();
451 :
452 1 : f = std::make_shared<snaplogger::format>("${message:upper}");
453 1 : buffer->set_format(f);
454 :
455 1 : SNAP_LOG_ERROR << "This message words will get their FIRST-LETTER capitalized." << SNAP_LOG_SEND;
456 1 : CATCH_REQUIRE(buffer->str() == "THIS MESSAGE WORDS WILL GET THEIR FIRST-LETTER CAPITALIZED.\n");
457 1 : }
458 7 : CATCH_END_SECTION()
459 :
460 7 : CATCH_START_SECTION("variable: default align value")
461 : {
462 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-variable-default-param");
463 :
464 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
465 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
466 :
467 1 : char const * cargv[] =
468 : {
469 : "/usr/bin/daemon",
470 : nullptr
471 : };
472 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
473 1 : char ** argv = const_cast<char **>(cargv);
474 :
475 1 : advgetopt::options_environment environment_options;
476 1 : environment_options.f_project_name = "test-logger";
477 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
478 1 : advgetopt::getopt opts(environment_options);
479 1 : opts.parse_program_name(argv);
480 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
481 :
482 1 : buffer->set_config(opts);
483 :
484 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${hostname:max_width=3} ${message}"));
485 1 : buffer->set_format(f);
486 :
487 1 : l->add_appender(buffer);
488 :
489 1 : char host[HOST_NAME_MAX + 2 + 30];
490 1 : CATCH_REQUIRE(gethostname(host, HOST_NAME_MAX + 1) == 0);
491 1 : host[HOST_NAME_MAX + 1] = '\0';
492 2 : std::string aligned(host);
493 1 : aligned = aligned.substr(0, 3);
494 1 : while(aligned.length() < 3)
495 : {
496 0 : aligned = " " + aligned;
497 : }
498 :
499 1 : SNAP_LOG_ERROR << "<- first three letters of hostname" << SNAP_LOG_SEND;
500 1 : CATCH_REQUIRE(buffer->str() == aligned + " <- first three letters of hostname\n");
501 1 : }
502 7 : CATCH_END_SECTION()
503 :
504 7 : CATCH_START_SECTION("variable: systemd severity")
505 : {
506 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-variable-systemd-severity");
507 :
508 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
509 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
510 :
511 1 : char const * cargv[] =
512 : {
513 : "/usr/bin/daemon",
514 : nullptr
515 : };
516 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
517 1 : char ** argv = const_cast<char **>(cargv);
518 :
519 1 : advgetopt::options_environment environment_options;
520 1 : environment_options.f_project_name = "test-logger";
521 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
522 1 : advgetopt::getopt opts(environment_options);
523 1 : opts.parse_program_name(argv);
524 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
525 :
526 1 : buffer->set_config(opts);
527 :
528 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${severity:format=systemd} ${message} (${severity:format=alpha})"));
529 1 : buffer->set_format(f);
530 :
531 1 : l->add_appender(buffer);
532 :
533 1 : SNAP_LOG_EMERGENCY << "<- severity tag for systemd/syslog" << SNAP_LOG_SEND;
534 1 : SNAP_LOG_ALERT << "<- severity tag for systemd/syslog" << SNAP_LOG_SEND;
535 1 : SNAP_LOG_CRIT << "<- severity tag for systemd/syslog" << SNAP_LOG_SEND;
536 1 : SNAP_LOG_ERROR << "<- severity tag for systemd/syslog" << SNAP_LOG_SEND;
537 1 : SNAP_LOG_WARNING << "<- severity tag for systemd/syslog" << SNAP_LOG_SEND;
538 1 : SNAP_LOG_MINOR << "<- severity tag for systemd/syslog" << SNAP_LOG_SEND; // a.k.a. a NOTICE for syslog
539 1 : SNAP_LOG_INFO << "<- severity tag for systemd/syslog" << SNAP_LOG_SEND;
540 1 : SNAP_LOG_DEBUG << "<- severity tag for systemd/syslog" << SNAP_LOG_SEND;
541 :
542 1 : CATCH_REQUIRE(buffer->str() == "<0> <- severity tag for systemd/syslog (emergency)\n"
543 : "<1> <- severity tag for systemd/syslog (alert)\n"
544 : "<2> <- severity tag for systemd/syslog (critical)\n"
545 : "<3> <- severity tag for systemd/syslog (error)\n"
546 : "<4> <- severity tag for systemd/syslog (warning)\n"
547 : "<5> <- severity tag for systemd/syslog (minor)\n"
548 : "<6> <- severity tag for systemd/syslog (information)\n");
549 :
550 1 : l->set_severity(::snaplogger::severity_t::SEVERITY_ALL);
551 1 : SNAP_LOG_DEBUG << "<- severity tag for systemd/syslog" << SNAP_LOG_SEND;
552 :
553 1 : CATCH_REQUIRE(buffer->str() == "<0> <- severity tag for systemd/syslog (emergency)\n"
554 : "<1> <- severity tag for systemd/syslog (alert)\n"
555 : "<2> <- severity tag for systemd/syslog (critical)\n"
556 : "<3> <- severity tag for systemd/syslog (error)\n"
557 : "<4> <- severity tag for systemd/syslog (warning)\n"
558 : "<5> <- severity tag for systemd/syslog (minor)\n"
559 : "<6> <- severity tag for systemd/syslog (information)\n"
560 : "<7> <- severity tag for systemd/syslog (debug)\n");
561 1 : }
562 7 : CATCH_END_SECTION()
563 :
564 7 : CATCH_START_SECTION("variable: systemd severity with an invalid format")
565 : {
566 1 : snaplogger::set_diagnostic(snaplogger::DIAG_KEY_PROGNAME, "message-variable-systemd-severity-invalid-format");
567 :
568 1 : snaplogger::logger::pointer_t l(snaplogger::logger::get_instance());
569 1 : snaplogger::buffer_appender::pointer_t buffer(std::make_shared<snaplogger::buffer_appender>("test-buffer"));
570 :
571 1 : char const * cargv[] =
572 : {
573 : "/usr/bin/daemon",
574 : nullptr
575 : };
576 1 : int const argc(sizeof(cargv) / sizeof(cargv[0]) - 1);
577 1 : char ** argv = const_cast<char **>(cargv);
578 :
579 1 : advgetopt::options_environment environment_options;
580 1 : environment_options.f_project_name = "test-logger";
581 1 : environment_options.f_environment_flags = advgetopt::GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS;
582 1 : advgetopt::getopt opts(environment_options);
583 1 : opts.parse_program_name(argv);
584 1 : opts.parse_arguments(argc, argv, advgetopt::option_source_t::SOURCE_COMMAND_LINE);
585 :
586 1 : buffer->set_config(opts);
587 :
588 1 : snaplogger::format::pointer_t f(std::make_shared<snaplogger::format>("${severity:format=invalid} ${message} (${severity:format=alpha})"));
589 1 : buffer->set_format(f);
590 :
591 1 : l->add_appender(buffer);
592 :
593 3 : CATCH_REQUIRE_THROWS_MATCHES(
594 : SNAP_LOG_MAJOR << "<- severity tag for systemd/syslog" << SNAP_LOG_SEND
595 : , snaplogger::invalid_variable
596 : , Catch::Matchers::ExceptionMessage(
597 : "logger_error: the ${severity:format=alpha|number|systemd}"
598 : " variable cannot be set to \"invalid\"."));
599 :
600 1 : CATCH_REQUIRE(buffer->str() == "");
601 1 : }
602 7 : CATCH_END_SECTION()
603 7 : }
604 :
605 :
606 :
607 3 : CATCH_TEST_CASE("duplicate_factory", "[variable][factory]")
608 : {
609 3 : CATCH_START_SECTION("variable: attempt dynamically creating a factory which already exists")
610 : {
611 : class fake_variable_factory final
612 : : public snaplogger::variable_factory
613 : {
614 : public:
615 1 : fake_variable_factory()
616 1 : : variable_factory("version")
617 : {
618 1 : }
619 :
620 0 : virtual snaplogger::variable::pointer_t create_variable() override final
621 : {
622 : // we can't even register this one so returning an empty
623 : // pointer is perfectly safe here
624 : //
625 0 : return snaplogger::variable::pointer_t();
626 : }
627 : };
628 :
629 5 : CATCH_REQUIRE_THROWS_MATCHES(
630 : snaplogger::register_variable_factory(std::make_shared<fake_variable_factory>())
631 : , snaplogger::duplicate_error
632 : , Catch::Matchers::ExceptionMessage("logger_error: trying to add two variable factories of type \"version\"."));
633 : }
634 3 : CATCH_END_SECTION()
635 :
636 3 : CATCH_START_SECTION("variable: attempt creating a variable with a non-existant type")
637 : {
638 1 : CATCH_REQUIRE(snaplogger::get_variable("fake") == nullptr);
639 : }
640 3 : CATCH_END_SECTION()
641 :
642 3 : CATCH_START_SECTION("variable: attempt creating a function factory with an existing name")
643 : {
644 : class fake_function final
645 : : public snaplogger::function
646 : {
647 : public:
648 1 : fake_function()
649 1 : : function("padding")
650 : {
651 1 : }
652 :
653 0 : virtual void apply(
654 : ::snaplogger::message const & msg
655 : , ::snaplogger::function_data & d
656 : , ::snaplogger::param::pointer_t const & p) override
657 : {
658 0 : snapdev::NOT_USED(msg, d, p);
659 0 : }
660 : };
661 :
662 5 : CATCH_REQUIRE_THROWS_MATCHES(
663 : snaplogger::register_function(std::make_shared<fake_function>())
664 : , snaplogger::duplicate_error
665 : , Catch::Matchers::ExceptionMessage("logger_error: trying to add two functions named \"padding\"."));
666 : }
667 3 : CATCH_END_SECTION()
668 3 : }
669 :
670 :
671 : // vim: ts=4 sw=4 et
|