1 /*
2  * Copyright (c) 2011-2015 Red Hat, Inc.
3  *
4  * All rights reserved.
5  *
6  * Author: Angus Salkeld <asalkeld@redhat.com>
7  *
8  * This file is part of libqb.
9  *
10  * libqb is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation, either version 2.1 of the License, or
13  * (at your option) any later version.
14  *
15  * libqb is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with libqb.  If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include "os_base.h"
25 #include <pthread.h>
26 
27 #include "check_common.h"
28 
29 #include <qb/qbdefs.h>
30 #include <qb/qbutil.h>
31 #include <qb/qblog.h>
32 
33 #ifdef USE_JOURNAL
34 #include <systemd/sd-journal.h>
35 #endif
36 
37 #include "_syslog_override.h"
38 
39 extern size_t qb_vsnprintf_serialize(char *serialize, size_t max_len, const char *fmt, va_list ap);
40 extern size_t qb_vsnprintf_deserialize(char *string, size_t strlen, const char *buf);
41 
42 
43 static void
format_this(char * out,const char * fmt,...)44 format_this(char *out, const char *fmt, ...)
45 {
46 	char buf[QB_LOG_MAX_LEN];
47 	va_list ap;
48 
49 	va_start(ap, fmt);
50 	qb_vsnprintf_serialize(buf, QB_LOG_MAX_LEN, fmt, ap);
51 	qb_vsnprintf_deserialize(out, QB_LOG_MAX_LEN, buf);
52 	va_end(ap);
53 }
54 
55 static void
format_this_up_to(char * out,size_t max_len,const char * fmt,...)56 format_this_up_to(char *out, size_t max_len, const char *fmt, ...)
57 {
58 	char buf[QB_LOG_MAX_LEN];
59 	va_list ap;
60 
61 	va_start(ap, fmt);
62 	qb_vsnprintf_serialize(buf, max_len, fmt, ap);
63 	qb_vsnprintf_deserialize(out, QB_LOG_MAX_LEN, buf);
64 	va_end(ap);
65 }
66 
START_TEST(test_va_serialize)67 START_TEST(test_va_serialize)
68 {
69 	char buf[QB_LOG_MAX_LEN];
70 	char cmp_buf[QB_LOG_MAX_LEN];
71 
72 	format_this(buf, "one line");
73 	ck_assert_str_eq(buf, "one line");
74 
75 	format_this(buf, "p1:%p, p2:%p", format_this, buf);
76 	snprintf(cmp_buf, QB_LOG_MAX_LEN, "p1:%p, p2:%p", format_this, buf);
77 	ck_assert_str_eq(buf, cmp_buf);
78 
79 	format_this(buf, "s1:%s, s2:%s", "Yes", "Never");
80 	ck_assert_str_eq(buf, "s1:Yes, s2:Never");
81 
82 	format_this(buf, "s1:%s, s2:%s", "Yes", "Never");
83 	ck_assert_str_eq(buf, "s1:Yes, s2:Never");
84 
85 	format_this(buf, "d1:%d, d2:%5i, d3:%04i", 23, 37, 84);
86 	ck_assert_str_eq(buf, "d1:23, d2:   37, d3:0084");
87 
88 	format_this(buf, "f1:%.5f, f2:%.2f", 23.34109, 23.34109);
89 	ck_assert_str_eq(buf, "f1:23.34109, f2:23.34");
90 
91 	format_this(buf, "%zd", (size_t)13140964);
92 	ck_assert_str_eq(buf, "13140964");
93 	format_this(buf, "%jd", (intmax_t)30627823);
94 	ck_assert_str_eq(buf, "30627823");
95 	format_this(buf, "%td", buf-cmp_buf);
96 	snprintf(cmp_buf, QB_LOG_MAX_LEN, "%td", buf-cmp_buf);
97 	ck_assert_str_eq(buf, cmp_buf);
98 
99 	format_this(buf, ":%s:", "Hello, world!");
100 	ck_assert_str_eq(buf, ":Hello, world!:");
101 	format_this(buf, ":%15s:", "Hello, world!");
102 	ck_assert_str_eq(buf, ":  Hello, world!:");
103 	format_this(buf, ":%.10s:", "Hello, world!");
104 	ck_assert_str_eq(buf, ":Hello, wor:");
105 	format_this(buf, ":%-10s:", "Hello, world!");
106 	ck_assert_str_eq(buf, ":Hello, world!:");
107 	format_this(buf, ":%-15s:", "Hello, world!");
108 	ck_assert_str_eq(buf, ":Hello, world!  :");
109 	format_this(buf, ":%.15s:", "Hello, world!");
110 	ck_assert_str_eq(buf, ":Hello, world!:");
111 	format_this(buf, ":%15.10s:", "Hello, world!");
112 	ck_assert_str_eq(buf, ":     Hello, wor:");
113 	format_this(buf, ":%-15.10s:", "Hello, world!");
114 	ck_assert_str_eq(buf, ":Hello, wor     :");
115 
116 	format_this(buf, ":%*d:", 8, 96);
117 	ck_assert_str_eq(buf, ":      96:");
118 
119 	format_this_up_to(buf, 11, "123456789____");
120 	ck_assert_str_eq(buf, "123456789_");
121 
122 	format_this(buf, "Client %s.%.9s wants to fence (%s) '%s' with device '%s'",
123 		    "bla", "foooooooooooooooooo",
124 		    "action", "target", "hoop");
125 
126 	ck_assert_str_eq(buf,
127 			 "Client bla.foooooooo wants to fence (action) 'target' with device 'hoop'");
128 
129 	format_this(buf, "Node %s now has process list: %.32x (was %.32x)",
130 		    "18builder", 2, 0);
131 	ck_assert_str_eq(buf, "Node 18builder now has process list: 00000000000000000000000000000002 (was 00000000000000000000000000000000)");
132 
133 
134 }
135 END_TEST
136 
START_TEST(test_log_stupid_inputs)137 START_TEST(test_log_stupid_inputs)
138 {
139 	int32_t rc;
140 
141 	/* shouldn't crash with out an init() */
142 	qb_log_fini();
143 
144 	/* not init'ed */
145 	rc = qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
146 			       QB_LOG_FILTER_FILE, "bla", LOG_TRACE);
147 	ck_assert_int_eq(rc, -EINVAL);
148 
149 	rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 2000);
150 	ck_assert_int_eq(rc, -EINVAL);
151 
152 	qb_log(LOG_INFO, "not init'd");
153 
154 	qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
155 				    __LINE__, 0, "also not init'd");
156 
157 	qb_log_init("test", LOG_USER, LOG_DEBUG);
158 
159 	/* non-opened log file */
160 	rc = qb_log_filter_ctl(21, QB_LOG_FILTER_ADD,
161 			       QB_LOG_FILTER_FILE, "bla", LOG_TRACE);
162 	ck_assert_int_eq(rc, -EBADF);
163 
164 	rc = qb_log_ctl(21, QB_LOG_CONF_PRIORITY_BUMP, -1);
165 	ck_assert_int_eq(rc, -EBADF);
166 
167 	/* target < 0 or >= 32 */
168 	rc = qb_log_filter_ctl(41, QB_LOG_FILTER_ADD,
169 			       QB_LOG_FILTER_FILE, "bla", LOG_TRACE);
170 	ck_assert_int_eq(rc, -EBADF);
171 
172 	rc = qb_log_ctl(-1, QB_LOG_CONF_PRIORITY_BUMP, -1);
173 	ck_assert_int_eq(rc, -EBADF);
174 
175 	/* crap values to filter_ctl() */
176 	rc = qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
177 			       QB_LOG_FILTER_FILE, NULL, LOG_INFO);
178 	ck_assert_int_eq(rc, -EINVAL);
179 	rc = qb_log_filter_ctl(QB_LOG_SYSLOG, 56,
180 			       QB_LOG_FILTER_FILE, "boja", LOG_INFO);
181 	ck_assert_int_eq(rc, -EINVAL);
182 
183 	/* crap values to ctl() */
184 	rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, -2000);
185 	ck_assert_int_eq(rc, -EINVAL);
186 	rc = qb_log_ctl(QB_LOG_BLACKBOX, 67, 2000);
187 	ck_assert_int_eq(rc, -EINVAL);
188 	rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_SIZE, 2000);
189 	ck_assert_int_eq(rc, -ENOSYS);
190 
191 }
192 END_TEST
193 
194 static char test_buf[4097];
195 static uint8_t test_priority;
196 static int32_t num_msgs;
197 static size_t last_length;
198 
199 /*
200  * to test that we get what we expect.
201  */
202 static void
_test_logger(int32_t t,struct qb_log_callsite * cs,struct timespec * timestamp,const char * msg)203 _test_logger(int32_t t,
204 	     struct qb_log_callsite *cs,
205 	     struct timespec *timestamp, const char *msg)
206 {
207 	test_buf[0] = '\0';
208 	qb_log_target_format(t, cs, timestamp, msg, test_buf);
209 	test_priority = cs->priority;
210 
211 	num_msgs++;
212 }
213 
214 static void
_test_length_logger(int32_t t,struct qb_log_callsite * cs,struct timespec * timestamp,const char * msg)215 _test_length_logger(int32_t t,
216 	     struct qb_log_callsite *cs,
217 	     struct timespec *timestamp, const char *msg)
218 {
219 	strcpy(test_buf, msg);
220 	qb_log_target_format(t, cs, timestamp, msg, test_buf);
221 	test_priority = cs->priority;
222 
223 	num_msgs++;
224 	last_length = strlen(msg);
225 }
226 
log_also(void)227 static void log_also(void)
228 {
229 	qb_log(LOG_INFO, "yes please");
230 }
231 
log_and_this_too(void)232 static void log_and_this_too(void)
233 {
234 	qb_log(LOG_INFO, "this too please");
235 }
236 
log_it_please(void)237 static void log_it_please(void)
238 {
239 	qb_enter();
240 	qb_log(LOG_TRACE, "A:%d B:%d C:%d", 1, 2, 3);
241 	qb_log(LOG_DEBUG, "A:%d B:%d C:%d", 1, 2, 3);
242 	errno = EEXIST;
243 	qb_perror(LOG_WARNING, "bogus error");
244 	errno = 0;
245 	qb_log(LOG_INFO, "A:%d B:%d C:%d", 1, 2, 3);
246 	qb_log(LOG_NOTICE, "A:%d B:%d C:%d", 1, 2, 3);
247 	qb_log(LOG_WARNING, "A:%d B:%d C:%d", 1, 2, 3);
248 	qb_log(LOG_ERR, "A:%d B:%d C:%d", 1, 2, 3);
249 	qb_leave();
250 }
251 
252 
253 static int32_t _cust_t = -1;
254 static void
m_filter(struct qb_log_callsite * cs)255 m_filter(struct qb_log_callsite *cs)
256 {
257 	if ((cs->priority >= LOG_ALERT &&
258 	     cs->priority <= LOG_INFO) ||
259 	    cs->tags > 0) {
260 		qb_bit_set(cs->targets, _cust_t);
261 	} else {
262 		qb_bit_clear(cs->targets, _cust_t);
263 	}
264 }
265 
266 
START_TEST(test_log_filter_fn)267 START_TEST(test_log_filter_fn)
268 {
269 	int32_t rc;
270 
271 	qb_log_init("test", LOG_USER, LOG_EMERG);
272 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
273 
274 	_cust_t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
275 	_ck_assert_int(_cust_t, >, QB_LOG_BLACKBOX);
276 	rc = qb_log_ctl(_cust_t, QB_LOG_CONF_ENABLED, QB_TRUE);
277 	ck_assert_int_eq(rc, 0);
278 
279 	/*
280 	 * test the custom filter function.
281 	 * make sure qb_log, and qb_log_from_external_source are filtered.
282 	 */
283 	qb_log_filter_fn_set(m_filter);
284 	num_msgs = 0;
285 
286 	qb_log(LOG_NOTICE, "qb_log_filter_fn_set good");
287 	qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
288 				    __LINE__, 0, "qb_log_filter_fn_set good");
289 	qb_log(LOG_TRACE, "qb_log_filter_fn_set bad");
290 	qb_log_from_external_source(__func__, __FILE__, "%s", LOG_DEBUG,
291 				    __LINE__, 44, "qb_log_filter_fn_set woot");
292 	qb_log_from_external_source(__func__, __FILE__, "%s", LOG_DEBUG,
293 				    __LINE__, 0, "qb_log_filter_fn_set bad");
294 
295 	ck_assert_int_eq(num_msgs, 3);
296 }
297 END_TEST
298 
START_TEST(test_file_logging)299 START_TEST(test_file_logging)
300 {
301 	struct stat st;
302 	int rc, lf;
303 
304 	unlink("test1.log");
305 	unlink("test2.log");
306 
307 	qb_log_init("test", LOG_USER, LOG_DEBUG);
308 	lf = qb_log_file_open("test1.log");
309 	rc = qb_log_filter_ctl(lf, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE,
310 			       __FILE__, LOG_DEBUG);
311 	ck_assert_int_eq(rc, 0);
312 	rc = qb_log_ctl(lf, QB_LOG_CONF_ENABLED, QB_TRUE);
313 	ck_assert_int_eq(rc, 0);
314 
315 	qb_log(LOG_INFO, "write to file 1");
316 	qb_log(LOG_INFO, "write to file 1 again");
317 
318 	rc = stat("test1.log", &st);
319 	ck_assert_int_eq(rc, 0);
320 	ck_assert_int_ge(st.st_size, 32);
321 
322 	/* Test reopen with NULL arg */
323 	rc = qb_log_file_reopen(lf, NULL);
324 	ck_assert_int_eq(rc, 0);
325 	qb_log(LOG_INFO, "write to file 1 and again");
326 	qb_log(LOG_INFO, "write to file 1 yet again");
327 	rc = stat("test1.log", &st);
328 	ck_assert_int_eq(rc, 0);
329 	ck_assert_int_ge(st.st_size, 64);
330 
331 	/* Test reopen with new file */
332 	rc = qb_log_file_reopen(lf, "test2.log");
333 	ck_assert_int_eq(rc, 0);
334 
335 	qb_log(LOG_INFO, "write to file 2");
336 	qb_log(LOG_INFO, "write to file 2 again");
337 
338 	rc = stat("test2.log", &st);
339 	ck_assert_int_eq(rc, 0);
340 	ck_assert_int_ge(st.st_size, 32);
341 
342 	unlink("test1.log");
343 	unlink("test2.log");
344 }
345 END_TEST
346 
START_TEST(test_timestamps)347 START_TEST(test_timestamps)
348 {
349 	int32_t t;
350 	int32_t rc;
351 	int a,b,c,d;
352 
353 	qb_log_init("test", LOG_USER, LOG_EMERG);
354 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
355 
356 	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
357 	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
358 			       QB_LOG_FILTER_FILE, "*", LOG_INFO);
359 	ck_assert_int_eq(rc, 0);
360 
361 	/* normal timestamp */
362 	qb_log_format_set(t, "%t %b");
363 	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
364 	ck_assert_int_eq(rc, 0);
365 
366 	qb_log(LOG_INFO, "The time now is (see left)");
367 	rc = sscanf(test_buf+7, "%d:%d:%d.%d", &a, &b, &c, &d);
368 	ck_assert_int_eq(rc, 3);
369 
370 	/* millisecond timestamp */
371 	qb_log_format_set(t, "%T %b");
372 	qb_log(LOG_INFO, "The time now is precisely (see left)");
373 	rc = sscanf(test_buf+7, "%d:%d:%d.%d", &a, &b, &c, &d);
374 	ck_assert_int_eq(rc, 4);
375 }
376 END_TEST
377 
378 
START_TEST(test_line_length)379 START_TEST(test_line_length)
380 {
381 	int32_t t;
382 	int32_t rc;
383 	int i;
384 	char bigbuf[4097];
385 
386 	qb_log_init("test", LOG_USER, LOG_EMERG);
387 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
388 
389 	t = qb_log_custom_open(_test_length_logger, NULL, NULL, NULL);
390 	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
391 			  QB_LOG_FILTER_FORMAT, "*", LOG_WARNING);
392 	ck_assert_int_eq(rc, 0);
393 	qb_log_format_set(t, "[%p] %b");
394 	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
395 	ck_assert_int_eq(rc, 0);
396 	rc = qb_log_ctl(t, QB_LOG_CONF_MAX_LINE_LEN, 32);
397 	ck_assert_int_eq(rc, 0);
398 	rc = qb_log_ctl(t, QB_LOG_CONF_ELLIPSIS, QB_TRUE);
399 	ck_assert_int_eq(rc, 0);
400 
401 	/* captures last log */
402 	memset(test_buf, 0, sizeof(test_buf));
403 	test_priority = 0;
404 	num_msgs = 0;
405 
406 	qb_log(LOG_ERR, "Short message");
407 	qb_log(LOG_ERR, "This is a longer message 123456789012345678901234567890");
408 	qb_log(LOG_ERR, "Long message with parameters %d %s", 1234, "Oh yes it is");
409 
410 	ck_assert_int_eq(num_msgs, 3);
411 	ck_assert_int_eq(last_length, 31);
412 
413 	ck_assert_str_eq(test_buf+28, "...");
414 
415 	rc = qb_log_ctl(t, QB_LOG_CONF_ELLIPSIS, QB_FALSE);
416 	ck_assert_int_eq(rc, 0);
417 
418 	qb_log(LOG_ERR, "Long message with parameters %d %s", 1234, "Oh yes it is");
419 	ck_assert_str_ne(test_buf+28, "...");
420 
421 	/* Long lines */
422 	num_msgs = 0;
423 	rc = qb_log_ctl(t, QB_LOG_CONF_MAX_LINE_LEN, 4096);
424 	ck_assert_int_eq(rc, 0);
425 
426 	for (i=0; i<4096; i++) {
427 		bigbuf[i] = '0'+(i%10);
428 	}
429 	bigbuf[4096] = '\0';
430 	qb_log(LOG_ERR, "%s", bigbuf);
431 	ck_assert_int_eq(num_msgs, 1);
432 	ck_assert_int_eq(last_length, 4095);
433 }
434 END_TEST
435 
START_TEST(test_log_basic)436 START_TEST(test_log_basic)
437 {
438 	int32_t t;
439 	int32_t rc;
440 
441 	qb_log_init("test", LOG_USER, LOG_EMERG);
442 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
443 
444 	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
445 	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
446 			  QB_LOG_FILTER_FORMAT, "Angus", LOG_WARNING);
447 	ck_assert_int_eq(rc, 0);
448 	qb_log_format_set(t, "%b");
449 	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
450 	ck_assert_int_eq(rc, 0);
451 
452 	/* captures last log */
453 	memset(test_buf, 0, sizeof(test_buf));
454 	test_priority = 0;
455 	num_msgs = 0;
456 
457 	/*
458 	 * test filtering by format
459 	 */
460 	qb_log(LOG_INFO, "Hello Angus, how are you?");
461 	qb_log(LOG_WARNING, "Hello Steven, how are you?");
462 	qb_log(LOG_ERR, "Hello Andrew, how are you?");
463 	qb_log(LOG_ERR, "Hello Angus, how are you?");
464 	qb_log(LOG_EMERG, "Hello Anna, how are you?");
465 	ck_assert_int_eq(test_priority, LOG_ERR);
466 	ck_assert_int_eq(num_msgs, 1);
467 	ck_assert_str_eq(test_buf, "Hello Angus, how are you?");
468 
469 
470 	/*
471 	 * test filtering by file regex
472  	 */
473 	qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
474 			  QB_LOG_FILTER_FORMAT, "*", LOG_TRACE);
475 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
476 			  QB_LOG_FILTER_FILE_REGEX, "^fakefile*", LOG_DEBUG);
477 
478 	num_msgs = 0;
479 	qb_log_from_external_source(__func__, "fakefile_logging", "%s bla", LOG_INFO,
480 				    56, 0, "filename/lineno");
481 	qb_log_from_external_source(__func__, "do_not_log_fakefile_logging", "%s bla", LOG_INFO,
482 				    56, 0, "filename/lineno");
483 	ck_assert_int_eq(num_msgs, 1);
484 
485 	/*
486 	 * test filtering by format regex
487  	 */
488 	qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
489 			  QB_LOG_FILTER_FORMAT, "*", LOG_TRACE);
490 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
491 			  QB_LOG_FILTER_FORMAT_REGEX, "^one", LOG_WARNING);
492 
493 	num_msgs = 0;
494 	qb_log(LOG_INFO, "one two three");
495 	qb_log(LOG_ERR, "testing one two three");
496 	qb_log(LOG_WARNING, "one two three");
497 	qb_log(LOG_ERR, "one two three");
498 	qb_log(LOG_EMERG, "one two three");
499 	ck_assert_int_eq(num_msgs, 3);
500 
501 	/*
502 	 * test filtering by function and regex
503 	 */
504 	qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
505 			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
506 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
507 			  QB_LOG_FILTER_FUNCTION_REGEX, "^log_.*please", LOG_WARNING);
508 
509 	num_msgs = 0;
510 	qb_log(LOG_ERR, "try if you: log_it_please()");
511 	log_it_please();
512 	ck_assert_int_eq(num_msgs, 3);
513 
514 	qb_log_filter_ctl(t, QB_LOG_FILTER_REMOVE,
515 			  QB_LOG_FILTER_FUNCTION_REGEX, "log_it_please", LOG_WARNING);
516 
517 	/*
518 	 * test filtering by function
519 	 */
520 	qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
521 			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
522 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
523 			  QB_LOG_FILTER_FUNCTION, "log_it_please", LOG_WARNING);
524 
525 	num_msgs = 0;
526 	qb_log(LOG_ERR, "try if you: log_it_please()");
527 	log_it_please();
528 	ck_assert_int_eq(num_msgs, 3);
529 
530 	qb_log_filter_ctl(t, QB_LOG_FILTER_REMOVE,
531 			  QB_LOG_FILTER_FUNCTION, "log_it_please", LOG_WARNING);
532 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
533 			  QB_LOG_FILTER_FUNCTION, __func__, LOG_DEBUG);
534 
535 	num_msgs = 0;
536 	log_it_please();
537 	ck_assert_int_eq(num_msgs, 0);
538 	qb_log(LOG_DEBUG, "try if you: log_it_please()");
539 	ck_assert_int_eq(num_msgs, 1);
540 
541 	qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
542 			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
543 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
544 			  QB_LOG_FILTER_FUNCTION,
545 			  "log_also,log_and_this_too",
546 			  LOG_DEBUG);
547 	num_msgs = 0;
548 	log_also();
549 	log_and_this_too();
550 	ck_assert_int_eq(num_msgs, 2);
551 
552 	qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
553 			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
554 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
555 			  QB_LOG_FILTER_FILE, "fakefile.c,"__FILE__",otherfakefile", LOG_DEBUG);
556 	/*
557 	 * make sure we can pass in a null filename or function name.
558 	 */
559 	qb_log_from_external_source(__func__, NULL, "%s", LOG_INFO,
560 				    __LINE__, 0, "null filename");
561 	qb_log_from_external_source(NULL, __FILE__, "%s", LOG_INFO,
562 				    __LINE__, 0, "null function");
563 
564 	/* check same file/lineno logs with different formats work
565 	 */
566 	num_msgs = 0;
567 	qb_log_from_external_source(__func__, __FILE__, "%s bla", LOG_INFO,
568 				    56, 0, "filename/lineno");
569 	ck_assert_int_eq(num_msgs, 1);
570 	ck_assert_str_eq(test_buf, "filename/lineno bla");
571 
572 	num_msgs = 0;
573 	qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
574 				    56, 0, "same filename/lineno");
575 	ck_assert_int_eq(num_msgs, 1);
576 	ck_assert_str_eq(test_buf, "same filename/lineno");
577 
578 	/* check filtering works on same file/lineno but different
579 	 * log level.
580 	 */
581 	qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
582 			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
583 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
584 			  QB_LOG_FILTER_FILE, __FILE__, LOG_INFO);
585 
586 	num_msgs = 0;
587 	qb_log_from_external_source(__func__, __FILE__,
588 				    "same filename/lineno, this level %d",
589 				    LOG_INFO, 56, 0, LOG_INFO);
590 	ck_assert_int_eq(num_msgs, 1);
591 	ck_assert_str_eq(test_buf, "same filename/lineno, this level 6");
592 
593 	num_msgs = 0;
594 	qb_log_from_external_source(__func__, __FILE__,
595 				    "same filename/lineno, this level %d",
596 				    LOG_DEBUG, 56, 0, LOG_DEBUG);
597 	ck_assert_int_eq(num_msgs, 0);
598 }
599 END_TEST
600 
_test_tags_stringify(uint32_t tags)601 static const char *_test_tags_stringify(uint32_t tags)
602 {
603 	if (tags == 1) {
604 		return "ONE";
605 	} else if (tags == 8) {
606 		return "ATE";
607 	} else {
608 		return "ANY";
609 	}
610 }
611 
START_TEST(test_log_format)612 START_TEST(test_log_format)
613 {
614 	int32_t t;
615 	/* following size/length related equation holds in the context of use:
616 	   strlen(cmp_str) = strlen(host_str) + X; X ~ 20 < sizeof(host_str) */
617 	char host_str[256];
618 	char cmp_str[2 * sizeof(host_str)];
619 
620 	qb_log_init("test", LOG_USER, LOG_DEBUG);
621 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
622 
623 	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
624 	qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
625 
626 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
627 			  QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
628 	qb_log_format_set(t, "%p %f %b");
629 
630 	qb_log(LOG_DEBUG, "Angus");
631 	ck_assert_str_eq(test_buf, "debug check_log.c Angus");
632 	qb_log(LOG_INFO, "Angus");
633 	ck_assert_str_eq(test_buf, "info check_log.c Angus");
634 	qb_log(LOG_NOTICE, "Angus");
635 	ck_assert_str_eq(test_buf, "notice check_log.c Angus");
636 	qb_log(LOG_WARNING, "Angus");
637 	ck_assert_str_eq(test_buf, "warning check_log.c Angus");
638 	qb_log(LOG_ERR, "Angus");
639 	ck_assert_str_eq(test_buf, "error check_log.c Angus");
640 	qb_log(LOG_CRIT, "Angus");
641 	ck_assert_str_eq(test_buf, "crit check_log.c Angus");
642 	qb_log(LOG_ALERT, "Angus");
643 	ck_assert_str_eq(test_buf, "alert check_log.c Angus");
644 	qb_log(LOG_EMERG, "Angus");
645 	ck_assert_str_eq(test_buf, "emerg check_log.c Angus");
646 
647 	qb_log_tags_stringify_fn_set(_test_tags_stringify);
648 	qb_log_format_set(t, "%g %b");
649 
650 	qb_logt(LOG_INFO, 0, "Angus");
651 	ck_assert_str_eq(test_buf, "ANY Angus");
652 	qb_logt(LOG_INFO, 1, "Angus");
653 	ck_assert_str_eq(test_buf, "ONE Angus");
654 	qb_logt(LOG_INFO, 5, "Angus");
655 	ck_assert_str_eq(test_buf, "ANY Angus");
656 	qb_logt(LOG_INFO, 8, "Angus");
657 	ck_assert_str_eq(test_buf, "ATE Angus");
658 
659 	qb_log_format_set(t, "%-15f %b");
660 	qb_log(LOG_WARNING, "Andrew");
661 	ck_assert_str_eq(test_buf, "    check_log.c Andrew");
662 
663 	qb_log_tags_stringify_fn_set(NULL);
664 
665 	gethostname(host_str, sizeof(host_str));
666 	host_str[sizeof(host_str) - 1] = '\0';
667 
668 	qb_log_format_set(t, "%P %H %N %b");
669 	qb_log(LOG_INFO, "Angus");
670 	snprintf(cmp_str, sizeof(cmp_str), "%d %s test Angus", getpid(),
671 		 host_str);
672 	ck_assert_str_eq(test_buf, cmp_str);
673 
674 	qb_log_format_set(t, "%3N %H %P %b");
675 	qb_log(LOG_INFO, "Angus");
676 	snprintf(cmp_str, sizeof(cmp_str), "tes %s %d Angus", host_str,
677 		 getpid());
678 	ck_assert_str_eq(test_buf, cmp_str);
679 }
680 END_TEST
681 
START_TEST(test_log_enable)682 START_TEST(test_log_enable)
683 {
684 	int32_t t;
685 	int32_t state;
686 
687 	qb_log_init("test", LOG_USER, LOG_DEBUG);
688 	state = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_STATE_GET, 0);
689 	ck_assert_int_eq(state, QB_LOG_STATE_ENABLED);
690 	state = qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0);
691 	ck_assert_int_eq(state, QB_LOG_STATE_DISABLED);
692 	state = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0);
693 	ck_assert_int_eq(state, QB_LOG_STATE_DISABLED);
694 
695 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
696 	state = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_STATE_GET, 0);
697 	ck_assert_int_eq(state, QB_LOG_STATE_DISABLED);
698 
699 	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
700 	qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
701 
702 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
703 			  QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
704 	qb_log_format_set(t, "%b");
705 
706 	qb_log(LOG_DEBUG, "Hello");
707 	ck_assert_str_eq(test_buf, "Hello");
708 
709 	num_msgs = 0;
710 	qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_FALSE);
711 	qb_log(LOG_DEBUG, "Goodbye");
712 	ck_assert_int_eq(num_msgs, 0);
713 	qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
714 	qb_log(LOG_DEBUG, "Hello again");
715 	ck_assert_int_eq(num_msgs, 1);
716 	ck_assert_str_eq(test_buf, "Hello again");
717 }
718 END_TEST
719 
720 #define ITERATIONS 100000
thr_send_logs_2(void * ctx)721 static void *thr_send_logs_2(void *ctx)
722 {
723 	int32_t i;
724 	printf("%s\n", __func__);
725 
726 	for (i = 0; i < ITERATIONS; i++) {
727 		qb_log(LOG_INFO, "bla bla");
728 		qb_log(LOG_INFO, "blue blue");
729 		qb_log(LOG_INFO, "bra bra");
730 		qb_log(LOG_INFO, "bro bro");
731 		qb_log(LOG_INFO, "brown brown");
732 		qb_log(LOG_INFO, "booo booo");
733 		qb_log(LOG_INFO, "bogus bogus");
734 		qb_log(LOG_INFO, "bungu bungu");
735 	}
736 	return (NULL);
737 }
738 
thr_send_logs_1(void * ctx)739 static void *thr_send_logs_1(void *ctx)
740 {
741 	int32_t i;
742 
743 	printf("%s\n", __func__);
744 	for (i = 0; i < ITERATIONS; i++) {
745 		qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
746 					    __LINE__, 0, "foo soup");
747 		qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
748 					    __LINE__, 0, "fungus soup");
749 		qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
750 					    __LINE__, 0, "fruity soup");
751 		qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
752 					    __LINE__, 0, "free soup");
753 		qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
754 					    __LINE__, 0, "frot soup");
755 		qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
756 					    __LINE__, 0, "fresh soup");
757 		qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
758 					    __LINE__, 0, "fattening soup");
759 
760 	}
761 	return (NULL);
762 }
763 
764 #define THREADS 4
START_TEST(test_log_threads)765 START_TEST(test_log_threads)
766 {
767 	pthread_t threads[THREADS];
768 	pthread_attr_t thread_attr[THREADS];
769 	int32_t i;
770 	int32_t rc;
771 	int32_t lf;
772 	void *retval;
773 
774 	qb_log_init("test", LOG_USER, LOG_DEBUG);
775 	lf = qb_log_file_open("threads.log");
776 	rc = qb_log_filter_ctl(lf, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE,
777 					   __FILE__, LOG_DEBUG);
778 	ck_assert_int_eq(rc, 0);
779 	qb_log_format_set(lf, "[%p] [%l] %b");
780 	rc = qb_log_ctl(lf, QB_LOG_CONF_ENABLED, QB_TRUE);
781 	ck_assert_int_eq(rc, 0);
782 	rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
783 	ck_assert_int_eq(rc, 0);
784 
785 	for (i = 0; i < THREADS/2; i++) {
786 		pthread_attr_init(&thread_attr[i]);
787 
788 		pthread_attr_setdetachstate(&thread_attr[i],
789 					    PTHREAD_CREATE_JOINABLE);
790 		pthread_create(&threads[i], &thread_attr[i],
791 			       thr_send_logs_1, NULL);
792 	}
793 	for (i = THREADS/2; i < THREADS; i++) {
794 		pthread_attr_init(&thread_attr[i]);
795 
796 		pthread_attr_setdetachstate(&thread_attr[i],
797 					    PTHREAD_CREATE_JOINABLE);
798 		pthread_create(&threads[i], &thread_attr[i],
799 			       thr_send_logs_2, NULL);
800 	}
801 	for (i = 0; i < THREADS; i++) {
802 		pthread_join(threads[i], &retval);
803 	}
804 
805 }
806 END_TEST
807 
START_TEST(test_log_long_msg)808 START_TEST(test_log_long_msg)
809 {
810 	int lpc;
811 	int rc;
812 	int i, max = 1000;
813 	char *buffer = calloc(1, max);
814 
815 	qb_log_init("test", LOG_USER, LOG_DEBUG);
816 	rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
817 	ck_assert_int_eq(rc, 0);
818 	rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024);
819 	ck_assert_int_eq(rc, 0);
820 	rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
821 	ck_assert_int_eq(rc, 0);
822 	rc = qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
823 			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
824 	ck_assert_int_eq(rc, 0);
825 
826 	for (lpc = 500; lpc < max; lpc++) {
827 		lpc++;
828 		for(i = 0; i < max; i++) {
829 			buffer[i] = 'a' + (i % 10);
830 		}
831 		buffer[lpc%600] = 0;
832 		qb_log(LOG_INFO, "Message %d %d - %s", lpc, lpc%600, buffer);
833 	}
834 
835         qb_log_blackbox_write_to_file("blackbox.dump");
836         qb_log_blackbox_print_from_file("blackbox.dump");
837 	unlink("blackbox.dump");
838 	qb_log_fini();
839 }
840 END_TEST
841 
START_TEST(test_threaded_logging)842 START_TEST(test_threaded_logging)
843 {
844 	int32_t t;
845 	int32_t rc;
846 
847 	qb_log_init("test", LOG_USER, LOG_EMERG);
848 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
849 
850 	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
851 	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
852 			       QB_LOG_FILTER_FILE, "*", LOG_INFO);
853 	ck_assert_int_eq(rc, 0);
854 	qb_log_format_set(t, "%b");
855 	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
856 	ck_assert_int_eq(rc, 0);
857 	rc = qb_log_ctl(t, QB_LOG_CONF_THREADED, QB_TRUE);
858 	ck_assert_int_eq(rc, 0);
859 	qb_log_thread_start();
860 
861 	memset(test_buf, 0, sizeof(test_buf));
862 	test_priority = 0;
863 	num_msgs = 0;
864 
865 	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
866 	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
867 	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
868 	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
869 	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
870 	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
871 	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
872 	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
873 	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
874 	qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
875 
876 	qb_log_fini();
877 
878 	ck_assert_int_eq(num_msgs, 10);
879 }
880 END_TEST
881 
882 #ifdef HAVE_PTHREAD_SETSCHEDPARAM
START_TEST(test_threaded_logging_bad_sched_params)883 START_TEST(test_threaded_logging_bad_sched_params)
884 {
885 	int32_t t;
886 	int32_t rc;
887 
888 	qb_log_init("test", LOG_USER, LOG_EMERG);
889 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
890 
891 	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
892 	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
893 			       QB_LOG_FILTER_FILE, "*", LOG_INFO);
894 	ck_assert_int_eq(rc, 0);
895 	qb_log_format_set(t, "%b");
896 	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
897 	ck_assert_int_eq(rc, 0);
898 	rc = qb_log_ctl(t, QB_LOG_CONF_THREADED, QB_TRUE);
899 	ck_assert_int_eq(rc, 0);
900 
901 #if defined(SCHED_RR)
902 #define QB_SCHED SCHED_RR
903 #elif defined(SCHED_FIFO)
904 #define QB_SCHED SCHED_FIFO
905 #else
906 #define QB_SCHED (-1)
907 #endif
908 	rc = qb_log_thread_priority_set(QB_SCHED, -1);
909 	ck_assert_int_eq(rc, 0);
910 
911 	rc = qb_log_thread_start();
912 	ck_assert_int_ne(rc, 0);
913 	qb_log_fini();
914 }
915 END_TEST
916 #endif
917 
START_TEST(test_extended_information)918 START_TEST(test_extended_information)
919 {
920 	int32_t t;
921 	int32_t rc;
922 	int extended;
923 
924 	qb_log_init("test", LOG_USER, LOG_DEBUG);
925 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
926 
927 	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
928 	_ck_assert_int(t, >, QB_LOG_STDOUT);
929 	qb_log_format_set(t, "%b");
930 	rc = qb_log_filter_fn_set(NULL);
931 	ck_assert_int_eq(rc, 0);
932 	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL, QB_LOG_FILTER_FILE,
933 			       "*", LOG_TRACE);
934 	ck_assert_int_eq(rc, 0);
935 	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL, QB_LOG_FILTER_FORMAT,
936 			       "*", LOG_TRACE);
937 	ck_assert_int_eq(rc, 0);
938 	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FORMAT,
939 			       "*", LOG_TRACE);
940 	ck_assert_int_eq(rc, 0);
941 	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
942 	ck_assert_int_eq(rc, 0);
943 
944 	for (extended = QB_FALSE; extended <= QB_TRUE; ++extended) {
945 		rc = qb_log_ctl(t, QB_LOG_CONF_EXTENDED, extended);
946 		ck_assert_int_eq(rc, 0);
947 
948 		num_msgs = 0;
949 
950 		memset(test_buf, 0, sizeof(test_buf));
951 		qb_log(LOG_ERR, "message with no extended information");
952 		ck_assert_str_eq(test_buf, "message with no extended information");
953 
954 		memset(test_buf, 0, sizeof(test_buf));
955 		qb_log(LOG_ERR, "message with empty extended information "QB_XS);
956 		ck_assert_str_eq(test_buf, "message with empty extended information ");
957 
958 		memset(test_buf, 0, sizeof(test_buf));
959 		qb_log(LOG_ERR, QB_XS" message with only extended information");
960 		ck_assert_str_eq(test_buf, extended?
961 				 "| message with only extended information" : "");
962 
963 		memset(test_buf, 0, sizeof(test_buf));
964 		qb_log(LOG_ERR, "message with extended information "QB_XS" (namely this)");
965 		ck_assert_str_eq(test_buf, extended?
966 				 "message with extended information | (namely this)"
967 				 : "message with extended information ");
968 
969 		ck_assert_int_eq(num_msgs, (extended? 4 : 3));
970 	}
971 	qb_log_fini();
972 }
973 END_TEST
974 
tagtest_stringify_tag(uint32_t tag)975 static const char *tagtest_stringify_tag(uint32_t tag)
976 {
977 	static char buf[32];
978 	sprintf(buf, "%5" PRIu32, tag);
979 	return buf;
980 }
981 
START_TEST(test_zero_tags)982 START_TEST(test_zero_tags)
983 {
984 	int32_t rc;
985 	int32_t t;
986 
987 	qb_log_init("test", LOG_USER, LOG_EMERG);
988 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
989 
990 	t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
991 	rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
992 			       QB_LOG_FILTER_FILE, "*", LOG_INFO);
993 	ck_assert_int_eq(rc, 0);
994 
995 	qb_log_format_set(t, "[%g] %b");
996 	qb_log_tags_stringify_fn_set(tagtest_stringify_tag);
997 	rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
998 	ck_assert_int_eq(rc, 0);
999 
1000 	qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
1001 			  QB_LOG_FILTER_FILE, "*", LOG_TRACE);
1002 
1003 	qb_log_from_external_source("function", "filename", "%s: %d", LOG_DEBUG, 356, 2, "testlog", 2);
1004 	ck_assert_str_eq(test_buf, "[    2] testlog: 2");
1005 
1006 	qb_log_from_external_source("function", "filename", "%s: %d", LOG_DEBUG, 356, 0, "testlog", 0);
1007 	ck_assert_str_eq(test_buf, "[    2] testlog: 0");
1008 
1009 	qb_log_fini();
1010 
1011 
1012 }
1013 END_TEST
1014 
1015 #ifdef USE_JOURNAL
START_TEST(test_journal)1016 START_TEST(test_journal)
1017 {
1018 	int rc;
1019 	const char *msg;
1020 	size_t len;
1021 	pid_t log_pid;
1022 	sd_journal *jnl;
1023 	int count = 0;
1024 	const char *msgid="f77379a8490b408bbe5f6940505a777b";
1025 
1026 	qb_log_init("check_log", LOG_USER, LOG_DEBUG);
1027 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
1028 	rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_USE_JOURNAL, 1);
1029 	ck_assert_int_eq(rc, 0);
1030 	qb_log2(msgid, LOG_ERR, "Test message 1 from libqb");
1031 
1032 	qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
1033 	rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_USE_JOURNAL, 1);
1034 	ck_assert_int_eq(rc, -EINVAL);
1035 	sleep(1);
1036 
1037 	/* Check it reached the journal */
1038 	rc = sd_journal_open(&jnl, 0);
1039 	ck_assert_int_eq(rc, 0);
1040 	rc = sd_journal_seek_tail(jnl);
1041 	ck_assert_int_eq(rc, 0);
1042 	SD_JOURNAL_FOREACH_BACKWARDS(jnl) {
1043 	    rc = sd_journal_get_data(jnl, "_PID", (const void **)&msg, &len);
1044 	    ck_assert_int_eq(rc, 0);
1045 	    sscanf(msg, "_PID=%d", &log_pid);
1046 	    fprintf(stderr, "PID message = '%s' - pid = %d (pid=%d, parent=%d)\n", msg, log_pid, getpid(), getppid());
1047 	    if (log_pid == getpid()) {
1048 	        rc = sd_journal_get_data(jnl, "MESSAGE", (const void **)&msg, &len);
1049 		ck_assert_int_eq(rc, 0);
1050 	        rc = sd_journal_get_data(jnl, "MESSAGE_ID", (const void **)&msg, &len);
1051 		ck_assert_int_eq(rc, 0);
1052 		ck_assert_str_eq(msg+11, msgid);
1053 		break;
1054 	    }
1055 	    if (++count > 20) {
1056 		    break;
1057             }
1058         }
1059 	sd_journal_close(jnl);
1060 	ck_assert_int_lt(count, 20);
1061 }
1062 END_TEST
1063 #else
1064 START_TEST(test_syslog)
1065 {
1066 	int rc;
1067 
1068 	qb_log_init("flip", LOG_USER, LOG_INFO);
1069 	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
1070 
1071 	qb_log(LOG_ERR, "first as flip");
1072 	ck_assert_int_eq(_syslog_opened, 1);
1073 	ck_assert_str_eq(_syslog_ident, "flip");
1074 
1075 	qb_log_ctl2(QB_LOG_SYSLOG, QB_LOG_CONF_IDENT, QB_LOG_CTL2_S("flop"));
1076 	qb_log(LOG_ERR, "second as flop");
1077 	ck_assert_str_eq(_syslog_ident, "flop");
1078 
1079 	/* This test only runs if USE_JOURNAL is undefined, so should always fail */
1080 	rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_USE_JOURNAL, 1);
1081 	ck_assert_int_eq(rc, -EOPNOTSUPP);
1082 
1083 	qb_log_fini();
1084 }
1085 END_TEST
1086 #endif
1087 
1088 static Suite *
log_suite(void)1089 log_suite(void)
1090 {
1091 	TCase *tc;
1092 	Suite *s = suite_create("logging");
1093 
1094 	add_tcase(s, tc, test_va_serialize);
1095 	add_tcase(s, tc, test_log_stupid_inputs);
1096 	add_tcase(s, tc, test_log_basic);
1097 	add_tcase(s, tc, test_log_format);
1098 	add_tcase(s, tc, test_log_enable);
1099 	add_tcase(s, tc, test_log_threads, 360);
1100 	add_tcase(s, tc, test_log_long_msg);
1101 	add_tcase(s, tc, test_log_filter_fn);
1102 	add_tcase(s, tc, test_threaded_logging);
1103 	add_tcase(s, tc, test_line_length);
1104 	add_tcase(s, tc, test_file_logging);
1105 #ifdef HAVE_PTHREAD_SETSCHEDPARAM
1106 	add_tcase(s, tc, test_threaded_logging_bad_sched_params);
1107 #endif
1108 	add_tcase(s, tc, test_timestamps);
1109 	add_tcase(s, tc, test_extended_information);
1110 	add_tcase(s, tc, test_zero_tags);
1111 /*
1112  * You can still use syslog and journal in a normal application,
1113  * but the syslog_override code doesn't work when -lsystemd is present
1114  */
1115 #ifdef USE_JOURNAL
1116         add_tcase(s, tc, test_journal);
1117 #else
1118 	add_tcase(s, tc, test_syslog);
1119 #endif
1120 
1121 	return s;
1122 }
1123 
1124 int32_t
main(void)1125 main(void)
1126 {
1127 	int32_t number_failed;
1128 
1129 	Suite *s = log_suite();
1130 	SRunner *sr = srunner_create(s);
1131 
1132 	srunner_run_all(sr, CK_VERBOSE);
1133 	number_failed = srunner_ntests_failed(sr);
1134 	srunner_free(sr);
1135 	return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
1136 }
1137