==> 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}