skip to content
==> tests/log.c <==
1/* The log: lines reach the fd with stamps and levels, the recent ring keeps the last ones,
2 * a full queue drops and counts instead of blocking. */
3#include "mesh/check.h"
4#include "mesh/log.h"
5#include "mesh/text.h"
6
7#include <fcntl.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11
12int main(void) {
13    int fds[2];
14    CHECK(pipe(fds) == 0);
15    fcntl(fds[0], F_SETFL, O_NONBLOCK);
16    mesh_log_set_fd(fds[1]);
17    mesh_info("hello %d", 1);
18    mesh_error("bad %s", "thing");
19    mesh_log_flush(2000);
20    char buf[256] = {0};
21    ssize_t n = read(fds[0], buf, sizeof buf - 1);
22    CHECK(n > 0);
23    /* "HH:MM:SS.mmm INFO  hello 1\nHH:MM:SS.mmm ERROR bad thing\n" */
24    CHECK(strstr(buf, " INFO  hello 1\n") == buf + 12);
25    CHECK(strstr(buf, " ERROR bad thing\n") != NULL);
26    CHECK(buf[2] == ':' && buf[5] == ':' && buf[8] == '.');
27    char **lines;
28    size_t k = mesh_log_recent(5, &lines);
29    CHECK_U(k, 2);
30    CHECK(strstr(lines[1], "ERROR bad thing") != NULL);
31    for (size_t i = 0; i < k; i++) free(lines[i]);
32    free(lines);
33    CHECK_U(mesh_log_dropped(), 0);
34    /* Nobody reads: the pipe fills, then the queue; emitting still returns at once. */
35    for (int i = 0; i < 20000; i++) mesh_info("line %d of a reader-less pipe, long enough to fill it quickly .......", i);
36    CHECK(mesh_log_dropped() > 0);
37    k = mesh_log_recent(2000, &lines);
38    CHECK_U(k, 1000);
39    CHECK(strstr(lines[999], "line 19999 ") != NULL);
40    for (size_t i = 0; i < k; i++) free(lines[i]);
41    free(lines);
42    return mesh_check_done();
43}