Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/lib/log_format.c b/lib/log_format.c
index 6c29f0a..82fa1eb 100644
--- a/lib/log_format.c
+++ b/lib/log_format.c
@@ -1,852 +1,853 @@
/*
* Copyright (C) 2011 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* libqb is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* libqb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#include <ctype.h>
#include <qb/qbdefs.h>
#include "log_int.h"
static qb_log_tags_stringify_fn _user_tags_stringify_fn;
/*
* syslog prioritynames, facility names to value mapping
* Some C libraries build this in to their headers, but it is non-portable
* so logsys supplies its own version.
*/
struct syslog_names {
const char *c_name;
int32_t c_val;
};
static struct syslog_names prioritynames[] = {
{"emerg", LOG_EMERG},
{"alert", LOG_ALERT},
{"crit", LOG_CRIT},
{"error", LOG_ERR},
{"warning", LOG_WARNING},
{"notice", LOG_NOTICE},
{"info", LOG_INFO},
{"debug", LOG_DEBUG},
{"trace", LOG_TRACE},
{NULL, -1}
};
struct syslog_names facilitynames[] = {
{"auth", LOG_AUTH},
#if defined(LOG_AUTHPRIV)
{"authpriv", LOG_AUTHPRIV},
#endif
{"cron", LOG_CRON},
{"daemon", LOG_DAEMON},
#if defined(LOG_FTP)
{"ftp", LOG_FTP},
#endif
{"kern", LOG_KERN},
{"lpr", LOG_LPR},
{"mail", LOG_MAIL},
{"news", LOG_NEWS},
{"syslog", LOG_SYSLOG},
{"user", LOG_USER},
{"uucp", LOG_UUCP},
{"local0", LOG_LOCAL0},
{"local1", LOG_LOCAL1},
{"local2", LOG_LOCAL2},
{"local3", LOG_LOCAL3},
{"local4", LOG_LOCAL4},
{"local5", LOG_LOCAL5},
{"local6", LOG_LOCAL6},
{"local7", LOG_LOCAL7},
{NULL, -1}
};
static const char log_month_name[][4] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static pthread_rwlock_t _formatlock;
void
qb_log_format_init(void)
{
int32_t i;
struct qb_log_target *t;
i = pthread_rwlock_init(&_formatlock, NULL);
assert(i == 0);
for (i = 0; i < QB_LOG_TARGET_MAX; i++) {
t = qb_log_target_get(i);
t->format = strdup("[%p] %b");
}
}
void
qb_log_format_fini(void)
{
struct qb_log_target *t;
int32_t i;
pthread_rwlock_destroy(&_formatlock);
for (i = 0; i < QB_LOG_TARGET_MAX; i++) {
t = qb_log_target_get(i);
free(t->format);
}
}
void
qb_log_format_set(int32_t target, const char *format)
{
char modified_format[256];
struct qb_log_target *t = qb_log_target_get(target);
pthread_rwlock_wrlock(&_formatlock);
free(t->format);
if (format) {
qb_log_target_format_static(target, format, modified_format);
t->format = strdup(modified_format);
} else {
t->format = strdup("[%p] %b");
}
assert(t->format != NULL);
pthread_rwlock_unlock(&_formatlock);
}
/* Convert string "auth" to equivalent number "LOG_AUTH" etc. */
int32_t
qb_log_facility2int(const char *fname)
{
int32_t i;
if (fname == NULL) {
return -EINVAL;
}
for (i = 0; facilitynames[i].c_name != NULL; i++) {
if (strcmp(fname, facilitynames[i].c_name) == 0) {
return facilitynames[i].c_val;
}
}
return -EINVAL;
}
/* Convert number "LOG_AUTH" to equivalent string "auth" etc. */
const char *
qb_log_facility2str(int32_t fnum)
{
int32_t i;
for (i = 0; facilitynames[i].c_name != NULL; i++) {
if (facilitynames[i].c_val == fnum) {
return facilitynames[i].c_name;
}
}
return NULL;
}
const char *
qb_log_priority2str(uint8_t priority)
{
if (priority > LOG_TRACE) {
return prioritynames[LOG_TRACE].c_name;
}
return prioritynames[priority].c_name;
}
void
qb_log_tags_stringify_fn_set(qb_log_tags_stringify_fn fn)
{
_user_tags_stringify_fn = fn;
}
static int
_strcpy_cutoff(char *dest, const char *src, size_t cutoff, int ralign,
size_t buf_len)
{
size_t len = strlen(src);
if (buf_len <= 1) {
if (buf_len == 0)
dest[0] = 0;
return 0;
}
if (cutoff == 0) {
cutoff = len;
}
cutoff = QB_MIN(cutoff, buf_len - 1);
len = QB_MIN(len, cutoff);
if (ralign) {
memset(dest, ' ', cutoff - len);
memcpy(dest + cutoff - len, src, len);
} else {
memcpy(dest, src, len);
memset(dest + len, ' ', cutoff - len);
}
dest[cutoff] = '\0';
return cutoff;
}
/*
* This function will do static formatting (for things that don't
* change on each log message).
*
* %P PID
* %N name passed into qb_log_init
* %H hostname
*
* any number between % and character specify field length to pad or chop
*/
void
qb_log_target_format_static(int32_t target, const char * format,
char *output_buffer)
{
char tmp_buf[255];
unsigned int format_buffer_idx = 0;
unsigned int output_buffer_idx = 0;
size_t cutoff;
uint32_t len;
int ralign;
int c;
struct qb_log_target *t = qb_log_target_get(target);
if (format == NULL) {
return;
}
while ((c = format[format_buffer_idx])) {
cutoff = 0;
ralign = QB_FALSE;
if (c != '%') {
output_buffer[output_buffer_idx++] = c;
format_buffer_idx++;
} else {
const char *p;
unsigned int percent_buffer_idx = format_buffer_idx;
format_buffer_idx += 1;
if (format[format_buffer_idx] == '-') {
ralign = QB_TRUE;
format_buffer_idx += 1;
}
if (isdigit(format[format_buffer_idx])) {
cutoff = atoi(&format[format_buffer_idx]);
}
while (isdigit(format[format_buffer_idx])) {
format_buffer_idx += 1;
}
switch (format[format_buffer_idx]) {
case 'P':
snprintf(tmp_buf, 30, "%d", getpid());
p = tmp_buf;
break;
case 'N':
p = t->name;
break;
case 'H':
- if (gethostname(tmp_buf, 255) == 0) {
- tmp_buf[254] = '\0';
+ if (gethostname(tmp_buf, sizeof(tmp_buf)) == 0) {
+ tmp_buf[sizeof(tmp_buf) - 1] = '\0';
} else {
- (void)strlcpy(tmp_buf, "localhost", 255);
+ (void)strlcpy(tmp_buf, "localhost",
+ sizeof(tmp_buf));
}
p = tmp_buf;
break;
default:
p = &format[percent_buffer_idx];
cutoff = (format_buffer_idx - percent_buffer_idx + 1);
ralign = QB_FALSE;
break;
}
len = _strcpy_cutoff(output_buffer + output_buffer_idx,
p, cutoff, ralign,
(QB_LOG_MAX_LEN -
output_buffer_idx));
output_buffer_idx += len;
format_buffer_idx += 1;
}
if (output_buffer_idx >= QB_LOG_MAX_LEN - 1) {
break;
}
}
output_buffer[output_buffer_idx] = '\0';
}
/*
* %n FUNCTION NAME
* %f FILENAME
* %l FILELINE
* %p PRIORITY
* %t TIMESTAMP
* %b BUFFER
* %g SUBSYSTEM
*
* any number between % and character specify field length to pad or chop
*/
void
qb_log_target_format(int32_t target,
struct qb_log_callsite *cs,
time_t current_time,
const char *formatted_message, char *output_buffer)
{
char tmp_buf[128];
struct tm tm_res;
unsigned int format_buffer_idx = 0;
unsigned int output_buffer_idx = 0;
size_t cutoff;
uint32_t len;
int ralign;
int c;
struct qb_log_target *t = qb_log_target_get(target);
pthread_rwlock_rdlock(&_formatlock);
if (t->format == NULL) {
pthread_rwlock_unlock(&_formatlock);
return;
}
while ((c = t->format[format_buffer_idx])) {
cutoff = 0;
ralign = QB_FALSE;
if (c != '%') {
output_buffer[output_buffer_idx++] = c;
format_buffer_idx++;
} else {
const char *p;
format_buffer_idx += 1;
if (t->format[format_buffer_idx] == '-') {
ralign = QB_TRUE;
format_buffer_idx += 1;
}
if (isdigit(t->format[format_buffer_idx])) {
cutoff = atoi(&t->format[format_buffer_idx]);
}
while (isdigit(t->format[format_buffer_idx])) {
format_buffer_idx += 1;
}
switch (t->format[format_buffer_idx]) {
case 'g':
if (_user_tags_stringify_fn) {
p = _user_tags_stringify_fn(cs->tags);
} else {
p = "";
}
break;
case 'n':
p = cs->function;
break;
case 'f':
#ifdef BUILDING_IN_PLACE
p = cs->filename;
#else
p = strrchr(cs->filename, '/');
if (p == NULL) {
p = cs->filename;
} else {
p++; /* move past the "/" */
}
#endif /* BUILDING_IN_PLACE */
break;
case 'l':
snprintf(tmp_buf, 30, "%d", cs->lineno);
p = tmp_buf;
break;
case 't':
(void)localtime_r(&current_time, &tm_res);
snprintf(tmp_buf, TIME_STRING_SIZE,
"%s %02d %02d:%02d:%02d",
log_month_name[tm_res.tm_mon],
tm_res.tm_mday, tm_res.tm_hour,
tm_res.tm_min, tm_res.tm_sec);
p = tmp_buf;
break;
case 'b':
p = formatted_message;
break;
case 'p':
if (cs->priority > LOG_TRACE) {
p = prioritynames[LOG_TRACE].c_name;
} else {
p = prioritynames[cs->priority].c_name;
}
break;
default:
p = "";
break;
}
len = _strcpy_cutoff(output_buffer + output_buffer_idx,
p, cutoff, ralign,
(QB_LOG_MAX_LEN -
output_buffer_idx));
output_buffer_idx += len;
format_buffer_idx += 1;
}
if (output_buffer_idx >= QB_LOG_MAX_LEN - 1) {
break;
}
}
pthread_rwlock_unlock(&_formatlock);
if (output_buffer[output_buffer_idx - 1] == '\n') {
output_buffer[output_buffer_idx - 1] = '\0';
} else {
output_buffer[output_buffer_idx] = '\0';
}
}
/*
* These wrappers around strl* functions just return the
* number of characters written, not the number of characters
* requested to be written.
*/
static size_t
my_strlcpy(char *dest, const char * src, size_t maxlen)
{
size_t rc = strlcpy(dest, src, maxlen);
/* maxlen includes NUL, so -1 */
return QB_MIN(rc, maxlen-1);
}
static size_t
my_strlcat(char *dest, const char * src, size_t maxlen)
{
size_t rc = strlcat(dest, src, maxlen);
return QB_MIN(rc, maxlen-1);
}
size_t
qb_vsnprintf_serialize(char *serialize, size_t max_len,
const char *fmt, va_list ap)
{
char *format;
char *p;
char *qb_xc;
int type_long = QB_FALSE;
int type_longlong = QB_FALSE;
int sformat_length = 0;
int sformat_precision = QB_FALSE;
uint32_t location = my_strlcpy(serialize, fmt, max_len) + 1;
/* Assume serialized output always wants extended information
* (@todo: add variant of this function that takes argument for whether
* to print extended information, and make this a macro with that
* argument set to QB_TRUE, so callers can honor extended setting)
*/
if ((qb_xc = strchr(serialize, QB_XC)) != NULL) {
*qb_xc = *(qb_xc + 1)? '|' : '\0';
}
format = (char *)fmt;
for (;;) {
type_long = QB_FALSE;
type_longlong = QB_FALSE;
p = strchrnul((const char *)format, '%');
if (*p == '\0') {
break;
}
format = p + 1;
reprocess:
switch (format[0]) {
case '#': /* alternate form conversion, ignore */
case '-': /* left adjust, ignore */
case ' ': /* a space, ignore */
case '+': /* a sign should be used, ignore */
case '\'': /* group in thousands, ignore */
case 'I': /* glibc-ism locale alternative, ignore */
format++;
goto reprocess;
case '.': /* precision, ignore */
format++;
sformat_precision = QB_TRUE;
goto reprocess;
case '0': /* field width, ignore */
case '1': /* field width, ignore */
case '2': /* field width, ignore */
case '3': /* field width, ignore */
case '4': /* field width, ignore */
case '5': /* field width, ignore */
case '6': /* field width, ignore */
case '7': /* field width, ignore */
case '8': /* field width, ignore */
case '9': /* field width, ignore */
if (sformat_precision) {
sformat_length *= 10;
sformat_length += (format[0] - '0');
}
format++;
goto reprocess;
case '*': /* variable field width, save */ {
int arg_int = va_arg(ap, int);
if (location + sizeof (int) > max_len) {
return max_len;
}
memcpy(&serialize[location], &arg_int, sizeof (int));
location += sizeof(int);
format++;
goto reprocess;
}
case 'l':
format++;
type_long = QB_TRUE;
if (*format == 'l') {
type_long = QB_FALSE;
type_longlong = QB_TRUE;
format++;
}
goto reprocess;
case 'd': /* int argument */
case 'i': /* int argument */
case 'o': /* unsigned int argument */
case 'u':
case 'x':
case 'X':
if (type_long) {
long int arg_int;
if (location + sizeof (long int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, long int);
memcpy(&serialize[location], &arg_int,
sizeof(long int));
location += sizeof(long int);
format++;
break;
} else if (type_longlong) {
long long int arg_int;
if (location + sizeof (long long int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, long long int);
memcpy(&serialize[location], &arg_int,
sizeof(long long int));
location += sizeof(long long int);
format++;
break;
} else {
int arg_int;
if (location + sizeof (int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, int);
memcpy(&serialize[location], &arg_int,
sizeof(int));
location += sizeof(int);
format++;
break;
}
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
case 'a':
case 'A':
{
double arg_double;
if (location + sizeof (double) > max_len) {
return max_len;
}
arg_double = va_arg(ap, double);
memcpy (&serialize[location], &arg_double, sizeof (double));
location += sizeof(double);
format++;
break;
}
case 'c':
{
int arg_int;
unsigned char arg_char;
if (location + sizeof (unsigned int) > max_len) {
return max_len;
}
arg_int = va_arg(ap, unsigned int);
arg_char = (unsigned char)arg_int;
memcpy (&serialize[location], &arg_char, sizeof (unsigned char));
location += sizeof(unsigned char);
break;
}
case 's':
{
char *arg_string;
arg_string = va_arg(ap, char *);
if (arg_string == NULL) {
location += my_strlcpy(&serialize[location],
"(null)",
QB_MIN(strlen("(null)") + 1,
max_len - location));
} else if (sformat_length) {
location += my_strlcpy(&serialize[location],
arg_string,
QB_MIN(sformat_length + 1,
(max_len - location)));
} else {
location += my_strlcpy(&serialize[location],
arg_string,
QB_MIN(strlen(arg_string) + 1,
max_len - location));
}
location++;
break;
}
case 'p':
{
ptrdiff_t arg_pointer = va_arg(ap, ptrdiff_t);
if (location + sizeof (ptrdiff_t) > max_len) {
return max_len;
}
memcpy(&serialize[location], &arg_pointer, sizeof(ptrdiff_t));
location += sizeof(ptrdiff_t);
break;
}
case '%':
if (location + 1 > max_len) {
return max_len;
}
serialize[location++] = '%';
sformat_length = 0;
sformat_precision = QB_FALSE;
break;
}
}
return (location);
}
#define MINI_FORMAT_STR_LEN 20
size_t
qb_vsnprintf_deserialize(char *string, size_t str_len, const char *buf)
{
char *p;
char *format;
char fmt[MINI_FORMAT_STR_LEN];
int fmt_pos;
uint32_t location = 0;
uint32_t data_pos = strlen(buf) + 1;
int type_long = QB_FALSE;
int type_longlong = QB_FALSE;
int len;
string[0] = '\0';
format = (char *)buf;
for (;;) {
type_long = QB_FALSE;
type_longlong = QB_FALSE;
p = strchrnul((const char *)format, '%');
if (*p == '\0') {
return my_strlcat(string, format, str_len) + 1;
}
/* copy from current to the next % */
len = p - format;
memcpy(&string[location], format, len);
location += len;
format = p;
/* start building up the format for snprintf */
fmt_pos = 0;
fmt[fmt_pos++] = *format;
format++;
reprocess:
switch (format[0]) {
case '#': /* alternate form conversion, ignore */
case '-': /* left adjust, ignore */
case ' ': /* a space, ignore */
case '+': /* a sign should be used, ignore */
case '\'': /* group in thousands, ignore */
case 'I': /* glibc-ism locale alternative, ignore */
case '.': /* precision, ignore */
case '0': /* field width, ignore */
case '1': /* field width, ignore */
case '2': /* field width, ignore */
case '3': /* field width, ignore */
case '4': /* field width, ignore */
case '5': /* field width, ignore */
case '6': /* field width, ignore */
case '7': /* field width, ignore */
case '8': /* field width, ignore */
case '9': /* field width, ignore */
fmt[fmt_pos++] = *format;
format++;
goto reprocess;
case '*': {
int arg_int;
memcpy(&arg_int, &buf[data_pos], sizeof(int));
data_pos += sizeof(int);
fmt_pos += snprintf(&fmt[fmt_pos],
MINI_FORMAT_STR_LEN - fmt_pos,
"%d", arg_int);
format++;
goto reprocess;
}
case 'l':
fmt[fmt_pos++] = *format;
format++;
type_long = QB_TRUE;
if (*format == 'l') {
type_long = QB_FALSE;
type_longlong = QB_TRUE;
}
goto reprocess;
case 'd': /* int argument */
case 'i': /* int argument */
case 'o': /* unsigned int argument */
case 'u':
case 'x':
case 'X':
if (type_long) {
long int arg_int;
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
memcpy(&arg_int, &buf[data_pos], sizeof(long int));
location += snprintf(&string[location],
str_len - location,
fmt, arg_int);
data_pos += sizeof(long int);
format++;
break;
} else if (type_longlong) {
long long int arg_int;
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
memcpy(&arg_int, &buf[data_pos], sizeof(long long int));
location += snprintf(&string[location],
str_len - location,
fmt, arg_int);
data_pos += sizeof(long long int);
format++;
break;
} else {
int arg_int;
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
memcpy(&arg_int, &buf[data_pos], sizeof(int));
location += snprintf(&string[location],
str_len - location,
fmt, arg_int);
data_pos += sizeof(int);
format++;
break;
}
case 'e':
case 'E':
case 'f':
case 'F':
case 'g':
case 'G':
case 'a':
case 'A':
{
double arg_double;
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
memcpy(&arg_double, &buf[data_pos], sizeof(double));
location += snprintf(&string[location],
str_len - location,
fmt, arg_double);
data_pos += sizeof(double);
format++;
break;
}
case 'c':
{
unsigned char *arg_char;
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
arg_char = (unsigned char*)&buf[data_pos];
location += snprintf(&string[location],
str_len - location,
fmt, *arg_char);
data_pos += sizeof(unsigned char);
format++;
break;
}
case 's':
{
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
len = snprintf(&string[location],
str_len - location,
fmt, &buf[data_pos]);
location += len;
/* don't use len as there might be a len modifier */
data_pos += strlen(&buf[data_pos]) + 1;
format++;
break;
}
case 'p':
{
ptrdiff_t pt;
memcpy(&pt, &buf[data_pos],
sizeof(ptrdiff_t));
fmt[fmt_pos++] = *format;
fmt[fmt_pos++] = '\0';
location += snprintf(&string[location],
str_len - location,
fmt, pt);
data_pos += sizeof(void*);
format++;
break;
}
case '%':
string[location++] = '%';
format++;
break;
}
}
return location;
}
diff --git a/tests/check_log.c b/tests/check_log.c
index d7ac70b..8538620 100644
--- a/tests/check_log.c
+++ b/tests/check_log.c
@@ -1,859 +1,864 @@
/*
* Copyright (c) 2011-2015 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Angus Salkeld <asalkeld@redhat.com>
*
* This file is part of libqb.
*
* libqb is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* libqb is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with libqb. If not, see <http://www.gnu.org/licenses/>.
*/
#include "os_base.h"
#include <pthread.h>
#include <check.h>
#include <qb/qbdefs.h>
#include <qb/qbutil.h>
#include <qb/qblog.h>
#ifdef HAVE_SYSLOG_TESTS
#include "_syslog_override.h"
#endif
extern size_t qb_vsnprintf_serialize(char *serialize, size_t max_len, const char *fmt, va_list ap);
extern size_t qb_vsnprintf_deserialize(char *string, size_t strlen, const char *buf);
static void
format_this(char *out, const char *fmt, ...)
{
char buf[QB_LOG_MAX_LEN];
va_list ap;
va_start(ap, fmt);
qb_vsnprintf_serialize(buf, QB_LOG_MAX_LEN, fmt, ap);
qb_vsnprintf_deserialize(out, QB_LOG_MAX_LEN, buf);
va_end(ap);
}
static void
format_this_up_to(char *out, size_t max_len, const char *fmt, ...)
{
char buf[QB_LOG_MAX_LEN];
va_list ap;
va_start(ap, fmt);
qb_vsnprintf_serialize(buf, max_len, fmt, ap);
qb_vsnprintf_deserialize(out, QB_LOG_MAX_LEN, buf);
va_end(ap);
}
START_TEST(test_va_serialize)
{
char buf[QB_LOG_MAX_LEN];
char cmp_buf[QB_LOG_MAX_LEN];
format_this(buf, "one line");
ck_assert_str_eq(buf, "one line");
format_this(buf, "p1:%p, p2:%p", format_this, buf);
snprintf(cmp_buf, QB_LOG_MAX_LEN, "p1:%p, p2:%p", format_this, buf);
ck_assert_str_eq(buf, cmp_buf);
format_this(buf, "s1:%s, s2:%s", "Yes", "Never");
ck_assert_str_eq(buf, "s1:Yes, s2:Never");
format_this(buf, "s1:%s, s2:%s", "Yes", "Never");
ck_assert_str_eq(buf, "s1:Yes, s2:Never");
format_this(buf, "d1:%d, d2:%5i, d3:%04i", 23, 37, 84);
ck_assert_str_eq(buf, "d1:23, d2: 37, d3:0084");
format_this(buf, "f1:%.5f, f2:%.2f", 23.34109, 23.34109);
ck_assert_str_eq(buf, "f1:23.34109, f2:23.34");
format_this(buf, ":%s:", "Hello, world!");
ck_assert_str_eq(buf, ":Hello, world!:");
format_this(buf, ":%15s:", "Hello, world!");
ck_assert_str_eq(buf, ": Hello, world!:");
format_this(buf, ":%.10s:", "Hello, world!");
ck_assert_str_eq(buf, ":Hello, wor:");
format_this(buf, ":%-10s:", "Hello, world!");
ck_assert_str_eq(buf, ":Hello, world!:");
format_this(buf, ":%-15s:", "Hello, world!");
ck_assert_str_eq(buf, ":Hello, world! :");
format_this(buf, ":%.15s:", "Hello, world!");
ck_assert_str_eq(buf, ":Hello, world!:");
format_this(buf, ":%15.10s:", "Hello, world!");
ck_assert_str_eq(buf, ": Hello, wor:");
format_this(buf, ":%-15.10s:", "Hello, world!");
ck_assert_str_eq(buf, ":Hello, wor :");
format_this(buf, ":%*d:", 8, 96);
ck_assert_str_eq(buf, ": 96:");
format_this_up_to(buf, 11, "123456789____");
ck_assert_str_eq(buf, "123456789_");
format_this(buf, "Client %s.%.9s wants to fence (%s) '%s' with device '%s'",
"bla", "foooooooooooooooooo",
"action", "target", "hoop");
ck_assert_str_eq(buf,
"Client bla.foooooooo wants to fence (action) 'target' with device 'hoop'");
format_this(buf, "Node %s now has process list: %.32x (was %.32x)",
"18builder", 2, 0);
ck_assert_str_eq(buf, "Node 18builder now has process list: 00000000000000000000000000000002 (was 00000000000000000000000000000000)");
}
END_TEST
START_TEST(test_log_stupid_inputs)
{
int32_t rc;
/* shouldn't crash with out an init() */
qb_log_fini();
/* not init'ed */
rc = qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "bla", LOG_TRACE);
ck_assert_int_eq(rc, -EINVAL);
rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 2000);
ck_assert_int_eq(rc, -EINVAL);
qb_log(LOG_INFO, "not init'd");
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
__LINE__, 0, "also not init'd");
qb_log_init("test", LOG_USER, LOG_DEBUG);
/* non-opened log file */
rc = qb_log_filter_ctl(21, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "bla", LOG_TRACE);
ck_assert_int_eq(rc, -EBADF);
rc = qb_log_ctl(21, QB_LOG_CONF_PRIORITY_BUMP, -1);
ck_assert_int_eq(rc, -EBADF);
/* target < 0 or >= 32 */
rc = qb_log_filter_ctl(41, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "bla", LOG_TRACE);
ck_assert_int_eq(rc, -EBADF);
rc = qb_log_ctl(-1, QB_LOG_CONF_PRIORITY_BUMP, -1);
ck_assert_int_eq(rc, -EBADF);
/* crap values to filter_ctl() */
rc = qb_log_filter_ctl(QB_LOG_SYSLOG, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, NULL, LOG_INFO);
ck_assert_int_eq(rc, -EINVAL);
rc = qb_log_filter_ctl(QB_LOG_SYSLOG, 56,
QB_LOG_FILTER_FILE, "boja", LOG_INFO);
ck_assert_int_eq(rc, -EINVAL);
/* crap values to ctl() */
rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, -2000);
ck_assert_int_eq(rc, -EINVAL);
rc = qb_log_ctl(QB_LOG_BLACKBOX, 67, 2000);
ck_assert_int_eq(rc, -EINVAL);
rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_SIZE, 2000);
ck_assert_int_eq(rc, -ENOSYS);
}
END_TEST
static char test_buf[QB_LOG_MAX_LEN];
static uint8_t test_priority;
static int32_t num_msgs;
/*
* to test that we get what we expect.
*/
static void
_test_logger(int32_t t,
struct qb_log_callsite *cs,
time_t timestamp, const char *msg)
{
test_buf[0] = '\0';
qb_log_target_format(t, cs, timestamp, msg, test_buf);
test_priority = cs->priority;
num_msgs++;
}
static void log_also(void)
{
qb_log(LOG_INFO, "yes please");
}
static void log_and_this_too(void)
{
qb_log(LOG_INFO, "this too please");
}
static void log_it_please(void)
{
qb_enter();
qb_log(LOG_TRACE, "A:%d B:%d C:%d", 1, 2, 3);
qb_log(LOG_DEBUG, "A:%d B:%d C:%d", 1, 2, 3);
errno = EEXIST;
qb_perror(LOG_WARNING, "bogus error");
errno = 0;
qb_log(LOG_INFO, "A:%d B:%d C:%d", 1, 2, 3);
qb_log(LOG_NOTICE, "A:%d B:%d C:%d", 1, 2, 3);
qb_log(LOG_WARNING, "A:%d B:%d C:%d", 1, 2, 3);
qb_log(LOG_ERR, "A:%d B:%d C:%d", 1, 2, 3);
qb_leave();
}
static int32_t _cust_t = -1;
static void
m_filter(struct qb_log_callsite *cs)
{
if ((cs->priority >= LOG_ALERT &&
cs->priority <= LOG_INFO) ||
cs->tags > 0) {
qb_bit_set(cs->targets, _cust_t);
} else {
qb_bit_clear(cs->targets, _cust_t);
}
}
START_TEST(test_log_filter_fn)
{
int32_t rc;
qb_log_init("test", LOG_USER, LOG_EMERG);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
_cust_t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
_ck_assert_int(_cust_t, >, QB_LOG_BLACKBOX);
rc = qb_log_ctl(_cust_t, QB_LOG_CONF_ENABLED, QB_TRUE);
ck_assert_int_eq(rc, 0);
/*
* test the custom filter function.
* make sure qb_log, and qb_log_from_external_source are filtered.
*/
qb_log_filter_fn_set(m_filter);
num_msgs = 0;
qb_log(LOG_NOTICE, "qb_log_filter_fn_set good");
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
__LINE__, 0, "qb_log_filter_fn_set good");
qb_log(LOG_TRACE, "qb_log_filter_fn_set bad");
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_DEBUG,
__LINE__, 44, "qb_log_filter_fn_set woot");
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_DEBUG,
__LINE__, 0, "qb_log_filter_fn_set bad");
ck_assert_int_eq(num_msgs, 3);
}
END_TEST
START_TEST(test_log_basic)
{
int32_t t;
int32_t rc;
qb_log_init("test", LOG_USER, LOG_EMERG);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FORMAT, "Angus", LOG_WARNING);
ck_assert_int_eq(rc, 0);
qb_log_format_set(t, "%b");
rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
ck_assert_int_eq(rc, 0);
/* captures last log */
memset(test_buf, 0, sizeof(test_buf));
test_priority = 0;
num_msgs = 0;
/*
* test filtering by format
*/
qb_log(LOG_INFO, "Hello Angus, how are you?");
qb_log(LOG_WARNING, "Hello Steven, how are you?");
qb_log(LOG_ERR, "Hello Andrew, how are you?");
qb_log(LOG_ERR, "Hello Angus, how are you?");
qb_log(LOG_EMERG, "Hello Anna, how are you?");
ck_assert_int_eq(test_priority, LOG_ERR);
ck_assert_int_eq(num_msgs, 1);
ck_assert_str_eq(test_buf, "Hello Angus, how are you?");
/*
* test filtering by file regex
*/
qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
QB_LOG_FILTER_FORMAT, "*", LOG_TRACE);
qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE_REGEX, "^fakefile*", LOG_DEBUG);
num_msgs = 0;
qb_log_from_external_source(__func__, "fakefile_logging", "%s bla", LOG_INFO,
56, 0, "filename/lineno");
qb_log_from_external_source(__func__, "do_not_log_fakefile_logging", "%s bla", LOG_INFO,
56, 0, "filename/lineno");
ck_assert_int_eq(num_msgs, 1);
/*
* test filtering by format regex
*/
qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
QB_LOG_FILTER_FORMAT, "*", LOG_TRACE);
qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FORMAT_REGEX, "^one", LOG_WARNING);
num_msgs = 0;
qb_log(LOG_INFO, "one two three");
qb_log(LOG_ERR, "testing one two three");
qb_log(LOG_WARNING, "one two three");
qb_log(LOG_ERR, "one two three");
qb_log(LOG_EMERG, "one two three");
ck_assert_int_eq(num_msgs, 3);
/*
* test filtering by function and regex
*/
qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FUNCTION_REGEX, "^log_.*please", LOG_WARNING);
num_msgs = 0;
qb_log(LOG_ERR, "try if you: log_it_please()");
log_it_please();
ck_assert_int_eq(num_msgs, 3);
qb_log_filter_ctl(t, QB_LOG_FILTER_REMOVE,
QB_LOG_FILTER_FUNCTION_REGEX, "log_it_please", LOG_WARNING);
/*
* test filtering by function
*/
qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FUNCTION, "log_it_please", LOG_WARNING);
num_msgs = 0;
qb_log(LOG_ERR, "try if you: log_it_please()");
log_it_please();
ck_assert_int_eq(num_msgs, 3);
qb_log_filter_ctl(t, QB_LOG_FILTER_REMOVE,
QB_LOG_FILTER_FUNCTION, "log_it_please", LOG_WARNING);
qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FUNCTION, __func__, LOG_DEBUG);
num_msgs = 0;
log_it_please();
ck_assert_int_eq(num_msgs, 0);
qb_log(LOG_DEBUG, "try if you: log_it_please()");
ck_assert_int_eq(num_msgs, 1);
qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FUNCTION,
"log_also,log_and_this_too",
LOG_DEBUG);
num_msgs = 0;
log_also();
log_and_this_too();
ck_assert_int_eq(num_msgs, 2);
qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "fakefile.c,"__FILE__",otherfakefile", LOG_DEBUG);
/*
* make sure we can pass in a null filename or function name.
*/
qb_log_from_external_source(__func__, NULL, "%s", LOG_INFO,
__LINE__, 0, "null filename");
qb_log_from_external_source(NULL, __FILE__, "%s", LOG_INFO,
__LINE__, 0, "null function");
/* check same file/lineno logs with different formats work
*/
num_msgs = 0;
qb_log_from_external_source(__func__, __FILE__, "%s bla", LOG_INFO,
56, 0, "filename/lineno");
ck_assert_int_eq(num_msgs, 1);
ck_assert_str_eq(test_buf, "filename/lineno bla");
num_msgs = 0;
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
56, 0, "same filename/lineno");
ck_assert_int_eq(num_msgs, 1);
ck_assert_str_eq(test_buf, "same filename/lineno");
/* check filtering works on same file/lineno but different
* log level.
*/
qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL,
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, __FILE__, LOG_INFO);
num_msgs = 0;
qb_log_from_external_source(__func__, __FILE__,
"same filename/lineno, this level %d",
LOG_INFO, 56, 0, LOG_INFO);
ck_assert_int_eq(num_msgs, 1);
ck_assert_str_eq(test_buf, "same filename/lineno, this level 6");
num_msgs = 0;
qb_log_from_external_source(__func__, __FILE__,
"same filename/lineno, this level %d",
LOG_DEBUG, 56, 0, LOG_DEBUG);
ck_assert_int_eq(num_msgs, 0);
}
END_TEST
static const char *_test_tags_stringify(uint32_t tags)
{
if (tags == 1) {
return "ONE";
} else if (tags == 8) {
return "ATE";
} else {
return "ANY";
}
}
START_TEST(test_log_format)
{
int32_t t;
- char cmp_str[256];
+ /* following size/length related equation holds in the context of use:
+ strlen(cmp_str) = strlen(host_str) + X; X ~ 20 < sizeof(host_str) */
char host_str[256];
+ char cmp_str[2 * sizeof(host_str)];
qb_log_init("test", LOG_USER, LOG_DEBUG);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
qb_log_format_set(t, "%p %f %b");
qb_log(LOG_DEBUG, "Angus");
ck_assert_str_eq(test_buf, "debug check_log.c Angus");
qb_log(LOG_INFO, "Angus");
ck_assert_str_eq(test_buf, "info check_log.c Angus");
qb_log(LOG_NOTICE, "Angus");
ck_assert_str_eq(test_buf, "notice check_log.c Angus");
qb_log(LOG_WARNING, "Angus");
ck_assert_str_eq(test_buf, "warning check_log.c Angus");
qb_log(LOG_ERR, "Angus");
ck_assert_str_eq(test_buf, "error check_log.c Angus");
qb_log(LOG_CRIT, "Angus");
ck_assert_str_eq(test_buf, "crit check_log.c Angus");
qb_log(LOG_ALERT, "Angus");
ck_assert_str_eq(test_buf, "alert check_log.c Angus");
qb_log(LOG_EMERG, "Angus");
ck_assert_str_eq(test_buf, "emerg check_log.c Angus");
qb_log_tags_stringify_fn_set(_test_tags_stringify);
qb_log_format_set(t, "%g %b");
qb_logt(LOG_INFO, 0, "Angus");
ck_assert_str_eq(test_buf, "ANY Angus");
qb_logt(LOG_INFO, 1, "Angus");
ck_assert_str_eq(test_buf, "ONE Angus");
qb_logt(LOG_INFO, 5, "Angus");
ck_assert_str_eq(test_buf, "ANY Angus");
qb_logt(LOG_INFO, 8, "Angus");
ck_assert_str_eq(test_buf, "ATE Angus");
qb_log_format_set(t, "%-15f %b");
qb_log(LOG_WARNING, "Andrew");
ck_assert_str_eq(test_buf, " check_log.c Andrew");
qb_log_tags_stringify_fn_set(NULL);
- gethostname(host_str, 256);
+ gethostname(host_str, sizeof(host_str));
+ host_str[sizeof(host_str) - 1] = '\0';
qb_log_format_set(t, "%P %H %N %b");
qb_log(LOG_INFO, "Angus");
- snprintf(cmp_str, 256, "%d %s test Angus", getpid(), host_str);
+ snprintf(cmp_str, sizeof(cmp_str), "%d %s test Angus", getpid(),
+ host_str);
ck_assert_str_eq(test_buf, cmp_str);
qb_log_format_set(t, "%3N %H %P %b");
qb_log(LOG_INFO, "Angus");
- snprintf(cmp_str, 256, "tes %s %d Angus", host_str, getpid());
+ snprintf(cmp_str, sizeof(cmp_str), "tes %s %d Angus", host_str,
+ getpid());
ck_assert_str_eq(test_buf, cmp_str);
}
END_TEST
START_TEST(test_log_enable)
{
int32_t t;
int32_t state;
qb_log_init("test", LOG_USER, LOG_DEBUG);
state = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_STATE_GET, 0);
ck_assert_int_eq(state, QB_LOG_STATE_ENABLED);
state = qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_STATE_GET, 0);
ck_assert_int_eq(state, QB_LOG_STATE_DISABLED);
state = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_STATE_GET, 0);
ck_assert_int_eq(state, QB_LOG_STATE_DISABLED);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
state = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_STATE_GET, 0);
ck_assert_int_eq(state, QB_LOG_STATE_DISABLED);
t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
qb_log_format_set(t, "%b");
qb_log(LOG_DEBUG, "Hello");
ck_assert_str_eq(test_buf, "Hello");
num_msgs = 0;
qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_FALSE);
qb_log(LOG_DEBUG, "Goodbye");
ck_assert_int_eq(num_msgs, 0);
qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
qb_log(LOG_DEBUG, "Hello again");
ck_assert_int_eq(num_msgs, 1);
ck_assert_str_eq(test_buf, "Hello again");
}
END_TEST
#define ITERATIONS 100000
static void *thr_send_logs_2(void *ctx)
{
int32_t i;
printf("%s\n", __func__);
for (i = 0; i < ITERATIONS; i++) {
qb_log(LOG_INFO, "bla bla");
qb_log(LOG_INFO, "blue blue");
qb_log(LOG_INFO, "bra bra");
qb_log(LOG_INFO, "bro bro");
qb_log(LOG_INFO, "brown brown");
qb_log(LOG_INFO, "booo booo");
qb_log(LOG_INFO, "bogus bogus");
qb_log(LOG_INFO, "bungu bungu");
}
return (NULL);
}
static void *thr_send_logs_1(void *ctx)
{
int32_t i;
printf("%s\n", __func__);
for (i = 0; i < ITERATIONS; i++) {
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
__LINE__, 0, "foo soup");
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
__LINE__, 0, "fungus soup");
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
__LINE__, 0, "fruity soup");
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
__LINE__, 0, "free soup");
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
__LINE__, 0, "frot soup");
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
__LINE__, 0, "fresh soup");
qb_log_from_external_source(__func__, __FILE__, "%s", LOG_INFO,
__LINE__, 0, "fattening soup");
}
return (NULL);
}
#define THREADS 4
START_TEST(test_log_threads)
{
pthread_t threads[THREADS];
pthread_attr_t thread_attr[THREADS];
int32_t i;
int32_t rc;
int32_t lf;
void *retval;
qb_log_init("test", LOG_USER, LOG_DEBUG);
lf = qb_log_file_open("threads.log");
rc = qb_log_filter_ctl(lf, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FILE,
__FILE__, LOG_DEBUG);
ck_assert_int_eq(rc, 0);
qb_log_format_set(lf, "[%p] [%l] %b");
rc = qb_log_ctl(lf, QB_LOG_CONF_ENABLED, QB_TRUE);
ck_assert_int_eq(rc, 0);
rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
ck_assert_int_eq(rc, 0);
for (i = 0; i < THREADS/2; i++) {
pthread_attr_init(&thread_attr[i]);
pthread_attr_setdetachstate(&thread_attr[i],
PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[i], &thread_attr[i],
thr_send_logs_1, NULL);
}
for (i = THREADS/2; i < THREADS; i++) {
pthread_attr_init(&thread_attr[i]);
pthread_attr_setdetachstate(&thread_attr[i],
PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[i], &thread_attr[i],
thr_send_logs_2, NULL);
}
for (i = 0; i < THREADS; i++) {
pthread_join(threads[i], &retval);
}
}
END_TEST
START_TEST(test_log_long_msg)
{
int lpc;
int rc;
int i, max = 1000;
char *buffer = calloc(1, max);
qb_log_init("test", LOG_USER, LOG_DEBUG);
rc = qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
ck_assert_int_eq(rc, 0);
rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024);
ck_assert_int_eq(rc, 0);
rc = qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
ck_assert_int_eq(rc, 0);
rc = qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_TRACE);
ck_assert_int_eq(rc, 0);
for (lpc = 500; lpc < max; lpc++) {
lpc++;
for(i = 0; i < max; i++) {
buffer[i] = 'a' + (i % 10);
}
buffer[lpc%600] = 0;
qb_log(LOG_INFO, "Message %d %d - %s", lpc, lpc%600, buffer);
}
qb_log_blackbox_write_to_file("blackbox.dump");
qb_log_blackbox_print_from_file("blackbox.dump");
unlink("blackbox.dump");
qb_log_fini();
}
END_TEST
START_TEST(test_threaded_logging)
{
int32_t t;
int32_t rc;
qb_log_init("test", LOG_USER, LOG_EMERG);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD,
QB_LOG_FILTER_FILE, "*", LOG_INFO);
ck_assert_int_eq(rc, 0);
qb_log_format_set(t, "%b");
rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
ck_assert_int_eq(rc, 0);
rc = qb_log_ctl(t, QB_LOG_CONF_THREADED, QB_TRUE);
ck_assert_int_eq(rc, 0);
qb_log_thread_start();
memset(test_buf, 0, sizeof(test_buf));
test_priority = 0;
num_msgs = 0;
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log(LOG_INFO, "Yoda how old are you? - %d", __LINE__);
qb_log_fini();
ck_assert_int_eq(num_msgs, 10);
}
END_TEST
START_TEST(test_extended_information)
{
int32_t t;
int32_t rc;
int extended;
qb_log_init("test", LOG_USER, LOG_DEBUG);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
t = qb_log_custom_open(_test_logger, NULL, NULL, NULL);
_ck_assert_int(t, >, QB_LOG_STDOUT);
qb_log_format_set(t, "%b");
rc = qb_log_filter_fn_set(NULL);
ck_assert_int_eq(rc, 0);
rc = qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL, QB_LOG_FILTER_FILE,
"*", LOG_TRACE);
ck_assert_int_eq(rc, 0);
rc = qb_log_filter_ctl(t, QB_LOG_FILTER_CLEAR_ALL, QB_LOG_FILTER_FORMAT,
"*", LOG_TRACE);
ck_assert_int_eq(rc, 0);
rc = qb_log_filter_ctl(t, QB_LOG_FILTER_ADD, QB_LOG_FILTER_FORMAT,
"*", LOG_TRACE);
ck_assert_int_eq(rc, 0);
rc = qb_log_ctl(t, QB_LOG_CONF_ENABLED, QB_TRUE);
ck_assert_int_eq(rc, 0);
for (extended = QB_FALSE; extended <= QB_TRUE; ++extended) {
rc = qb_log_ctl(t, QB_LOG_CONF_EXTENDED, extended);
ck_assert_int_eq(rc, 0);
num_msgs = 0;
memset(test_buf, 0, sizeof(test_buf));
qb_log(LOG_ERR, "message with no extended information");
ck_assert_str_eq(test_buf, "message with no extended information");
memset(test_buf, 0, sizeof(test_buf));
qb_log(LOG_ERR, "message with empty extended information "QB_XS);
ck_assert_str_eq(test_buf, "message with empty extended information ");
memset(test_buf, 0, sizeof(test_buf));
qb_log(LOG_ERR, QB_XS" message with only extended information");
ck_assert_str_eq(test_buf, extended?
"| message with only extended information" : "");
memset(test_buf, 0, sizeof(test_buf));
qb_log(LOG_ERR, "message with extended information "QB_XS" (namely this)");
ck_assert_str_eq(test_buf, extended?
"message with extended information | (namely this)"
: "message with extended information ");
ck_assert_int_eq(num_msgs, (extended? 4 : 3));
}
qb_log_fini();
}
END_TEST
#ifdef HAVE_SYSLOG_TESTS
START_TEST(test_syslog)
{
qb_log_init("flip", LOG_USER, LOG_INFO);
qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_TRUE);
qb_log(LOG_ERR, "first as flip");
ck_assert_int_eq(_syslog_opened, 1);
ck_assert_str_eq(_syslog_ident, "flip");
qb_log_ctl2(QB_LOG_SYSLOG, QB_LOG_CONF_IDENT, QB_LOG_CTL2_S("flop"));
qb_log(LOG_ERR, "second as flop");
ck_assert_str_eq(_syslog_ident, "flop");
qb_log_fini();
}
END_TEST
#endif
static Suite *
log_suite(void)
{
TCase *tc;
Suite *s = suite_create("logging");
tc = tcase_create("va_serialize");
tcase_add_test(tc, test_va_serialize);
suite_add_tcase(s, tc);
tc = tcase_create("limits");
tcase_add_test(tc, test_log_stupid_inputs);
suite_add_tcase(s, tc);
tc = tcase_create("basic");
tcase_add_test(tc, test_log_basic);
suite_add_tcase(s, tc);
tc = tcase_create("format");
tcase_add_test(tc, test_log_format);
suite_add_tcase(s, tc);
tc = tcase_create("enable");
tcase_add_test(tc, test_log_enable);
suite_add_tcase(s, tc);
tc = tcase_create("threads");
tcase_add_test(tc, test_log_threads);
tcase_set_timeout(tc, 360);
suite_add_tcase(s, tc);
tc = tcase_create("long_msg");
tcase_add_test(tc, test_log_long_msg);
suite_add_tcase(s, tc);
tc = tcase_create("filter_ft");
tcase_add_test(tc, test_log_filter_fn);
suite_add_tcase(s, tc);
tc = tcase_create("threaded_logging");
tcase_add_test(tc, test_threaded_logging);
suite_add_tcase(s, tc);
tc = tcase_create("extended_information");
tcase_add_test(tc, test_extended_information);
suite_add_tcase(s, tc);
#ifdef HAVE_SYSLOG_TESTS
tc = tcase_create("syslog");
tcase_add_test(tc, test_syslog);
suite_add_tcase(s, tc);
#endif
return s;
}
int32_t
main(void)
{
int32_t number_failed;
Suite *s = log_suite();
SRunner *sr = srunner_create(s);
srunner_run_all(sr, CK_VERBOSE);
number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Feb 27, 3:59 AM (1 d, 6 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1459652
Default Alt Text
(45 KB)

Event Timeline