mirror of
https://gitlab.freedesktop.org/libinput/libei.git
synced 2025-12-31 11:10:08 +01:00
230 lines
6.3 KiB
C
230 lines
6.3 KiB
C
/* SPDX-License-Identifier: MIT */
|
|
/*
|
|
* Copyright © 2020 Red Hat, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice (including the next
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
* Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
|
|
#include "util-macros.h"
|
|
#include "util-color.h"
|
|
#include "util-strings.h"
|
|
#include "libei-private.h"
|
|
|
|
struct ei_log_context {
|
|
const char *file;
|
|
const char *func;
|
|
int line;
|
|
};
|
|
|
|
_public_
|
|
OBJECT_IMPLEMENT_GETTER(ei_log_context, file, const char *);
|
|
_public_
|
|
OBJECT_IMPLEMENT_GETTER(ei_log_context, func, const char *);
|
|
_public_
|
|
OBJECT_IMPLEMENT_GETTER(ei_log_context, line, unsigned int);
|
|
|
|
static void
|
|
ei_default_log_handler(struct ei *ei,
|
|
enum ei_log_priority priority,
|
|
const char *message,
|
|
struct ei_log_context *ctx)
|
|
{
|
|
struct lut {
|
|
const char *color;
|
|
const char *prefix;
|
|
} lut[] = {
|
|
{ .color = ansi_colorcode[RED], .prefix = "<undefined>", }, /* debug starts at 10 */
|
|
{ .color = ansi_colorcode[HIGHLIGHT], .prefix = "DEBUG", },
|
|
{ .color = ansi_colorcode[GREEN], .prefix = "INFO", },
|
|
{ .color = ansi_colorcode[BLUE], .prefix = "WARN", },
|
|
{ .color = ansi_colorcode[RED], .prefix = "ERROR", },
|
|
};
|
|
static time_t last_time = 0;
|
|
const char *reset_code = ansi_colorcode[RESET];
|
|
|
|
run_only_once {
|
|
if (!isatty(STDERR_FILENO)) {
|
|
struct lut *l;
|
|
ARRAY_FOR_EACH(lut, l)
|
|
l->color = "";
|
|
reset_code = "";
|
|
}
|
|
}
|
|
|
|
time_t now = time(NULL);
|
|
char timestamp[64];
|
|
|
|
if (last_time != now) {
|
|
struct tm *tm = localtime(&now);
|
|
strftime(timestamp, sizeof(timestamp), "%T", tm);
|
|
} else {
|
|
xsnprintf(timestamp, sizeof(timestamp), "...");
|
|
}
|
|
|
|
size_t idx = priority/10;
|
|
assert(idx < ARRAY_LENGTH(lut));
|
|
fprintf(stderr, " %8s | %s%4s%s | %s\n", timestamp,
|
|
lut[idx].color, lut[idx].prefix, reset_code, message);
|
|
|
|
last_time = now;
|
|
}
|
|
|
|
_public_ void
|
|
ei_log_set_handler(struct ei *ei, ei_log_handler log_handler)
|
|
{
|
|
ei->log.handler = log_handler ? log_handler : ei_default_log_handler;
|
|
}
|
|
|
|
_public_ void
|
|
ei_log_set_priority(struct ei *ei, enum ei_log_priority priority)
|
|
{
|
|
switch (priority) {
|
|
case EI_LOG_PRIORITY_DEBUG:
|
|
case EI_LOG_PRIORITY_INFO:
|
|
case EI_LOG_PRIORITY_WARNING:
|
|
case EI_LOG_PRIORITY_ERROR:
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
ei->log.priority = priority;
|
|
}
|
|
|
|
_public_ enum ei_log_priority
|
|
ei_log_get_priority(const struct ei *ei)
|
|
{
|
|
return ei->log.priority;
|
|
}
|
|
|
|
void
|
|
ei_log_msg(struct ei *ei,
|
|
enum ei_log_priority priority,
|
|
const char *file, int lineno, const char *func,
|
|
const char *format, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
ei_log_msg_va(ei, priority, file, lineno, func, format, args);
|
|
va_end(args);
|
|
}
|
|
|
|
void
|
|
ei_log_msg_va(struct ei *ei,
|
|
enum ei_log_priority priority,
|
|
const char *file, int lineno, const char *func,
|
|
const char *format,
|
|
va_list ap)
|
|
{
|
|
if (ei->log.priority > priority || !ei->log.handler)
|
|
return;
|
|
|
|
_cleanup_free_ char *message = xvaprintf(format, ap);
|
|
struct ei_log_context ctx = {
|
|
.file = file,
|
|
.line = lineno,
|
|
.func = func,
|
|
};
|
|
ei->log.handler(ei, priority, message, &ctx);
|
|
}
|
|
|
|
#ifdef _enable_tests_
|
|
#include "util-munit.h"
|
|
|
|
struct log_handler_check {
|
|
enum ei_log_priority min_priority;
|
|
const char *expected_message;
|
|
};
|
|
|
|
static void
|
|
test_loghandler(struct ei *ei,
|
|
enum ei_log_priority priority,
|
|
const char *message,
|
|
struct ei_log_context *ctx)
|
|
{
|
|
struct log_handler_check *check = ei_get_user_data(ei);
|
|
|
|
munit_assert_int(priority, >=, check->min_priority);
|
|
munit_assert_string_equal(message, check->expected_message);
|
|
/* Second arg is the line number, if this code ever moves further up,
|
|
* this test may fail */
|
|
munit_assert_int(ei_log_context_get_line(ctx), >, 170);
|
|
munit_assert_true(strendswith(ei_log_context_get_file(ctx), "libei-log.c"));
|
|
munit_assert_string_equal(ei_log_context_get_func(ctx), "test_log_handler");
|
|
}
|
|
|
|
MUNIT_TEST(test_log_handler)
|
|
{
|
|
struct log_handler_check check = {0};
|
|
struct ei *ei = ei_new(&check);
|
|
|
|
munit_assert_ptr_equal(ei->log.handler, ei_default_log_handler);
|
|
munit_assert_int(ei->log.priority, ==, EI_LOG_PRIORITY_INFO);
|
|
|
|
ei_log_set_handler(ei, test_loghandler);
|
|
|
|
check.min_priority = EI_LOG_PRIORITY_INFO; /* default */
|
|
check.expected_message = "info message";
|
|
|
|
log_debug(ei, "default is below this level");
|
|
log_info(ei, "info message");
|
|
|
|
check.expected_message = "error message";
|
|
log_error(ei, "error message");
|
|
|
|
check.min_priority = EI_LOG_PRIORITY_ERROR;
|
|
ei_log_set_priority(ei, EI_LOG_PRIORITY_ERROR);
|
|
munit_assert_int(ei->log.priority, ==, EI_LOG_PRIORITY_ERROR);
|
|
log_error(ei, "error message");
|
|
log_warn(ei, "warn message");
|
|
log_info(ei, "info message");
|
|
log_debug(ei, "debug message");
|
|
|
|
ei_log_set_priority(ei, EI_LOG_PRIORITY_DEBUG);
|
|
|
|
/* Make sure they come through at the right priority */
|
|
check.min_priority = EI_LOG_PRIORITY_ERROR;
|
|
check.expected_message = "error message";
|
|
log_error(ei, "error message");
|
|
check.min_priority = EI_LOG_PRIORITY_WARNING;
|
|
check.expected_message = "warn message";
|
|
log_warn(ei, "warn message");
|
|
check.min_priority = EI_LOG_PRIORITY_INFO;
|
|
check.expected_message = "info message";
|
|
log_info(ei, "info message");
|
|
check.min_priority = EI_LOG_PRIORITY_DEBUG;
|
|
check.expected_message = "debug message";
|
|
log_debug(ei, "debug message");
|
|
|
|
/* Can't capture this easily, so this is mostly just a crash test */
|
|
ei_log_set_handler(ei, NULL);
|
|
munit_assert_ptr_equal(ei->log.handler, ei_default_log_handler);
|
|
log_debug(ei, "ignore this, testing NULL log handler");
|
|
|
|
ei_unref(ei);
|
|
|
|
return MUNIT_OK;
|
|
}
|
|
#endif
|