6 #include <dlogutil-internal.h>
10 static char buffer[10240];
11 static size_t buffer_count = 0;
12 static bool fake_write;
13 static int partial_write;
14 ssize_t __real_write(int fd, const void *buf, size_t count);
15 ssize_t __wrap_write(int fd, const void *buf, size_t count)
21 return __real_write(fd, buf, count);
23 assert(count < sizeof buffer);
24 memcpy(buffer, buf, count);
31 static bool fail_localtime_r;
32 struct tm *__real_localtime_r(const time_t *timep, struct tm *result);
33 struct tm *__wrap_localtime_r(const time_t *timep, struct tm *result)
35 return fail_localtime_r ? NULL : __real_localtime_r(timep, result);
38 static int fail_alloc;
39 void *__real_malloc(size_t size);
40 void *__real_calloc(size_t nmemb, size_t size);
41 void *__wrap_malloc(size_t size)
48 return __real_malloc(size);
50 void *__wrap_calloc(size_t nmemb, size_t size)
52 return fail_alloc ? NULL : __real_calloc(nmemb, size);
55 static bool fail_strndup;
56 char *__real_strndup(const char *s, size_t n);
57 char *__wrap_strndup(const char *s, size_t n)
59 return fail_strndup ? NULL : __real_strndup(s, n);
62 static bool fail_strdup;
63 char *__real_strdup(const char *s);
64 char *__wrap_strdup(const char *s)
66 return fail_strdup ? NULL : __real_strdup(s);
69 static bool fail_list_add;
70 bool __real_list_add(list_head *head, elem_value value);
71 bool __wrap_list_add(list_head *head, elem_value value)
73 return fail_list_add ? false : __real_list_add(head, value);
76 /* Timestamps are shown in the everyday format so
77 * it's good to be able to work with those numbers
78 * where possible instead of the underlying single
79 * integer (but see below). */
81 #define SECONDS 1 // the base unit of the sec timestamp
82 #define MINUTES (60 * SECONDS)
83 #define HOURS (60 * MINUTES)
84 #define DAYS (24 * HOURS)
86 #define JANUARY (-1 * DAYS) // dates start from Jan 01, not Jan 00
87 #define FEBRUARY (JANUARY + 31 * DAYS)
88 #define MARCH (FEBRUARY + 28 * DAYS) // 1970, so no 29th
90 /* The nano timestamp is a bit more of a monolith,
91 * but can still be meaningfully split up into the
92 * milliseconds part and the remainder since all
93 * timestamps seem to only show the former. */
96 #define MICROSECONDS (1000 * NANOSECONDS)
97 #define MILLISECONDS (1000 * MICROSECONDS)
99 static void standard_test_msg(struct dlogutil_entry_with_msg *entry, const char *msg, size_t msg_len)
101 *entry = (struct dlogutil_entry_with_msg) {
103 .len = sizeof entry->header + msg_len,
104 .priority = DLOG_INFO,
107 .sec_sent_mono = 3205048,
108 .sec_sent_real = MARCH + 14*DAYS + 23*HOURS + 22*MINUTES + 51*SECONDS,
109 .sec_recv_mono = 365467,
110 .sec_recv_real = FEBRUARY + 1*DAYS + 0*HOURS + 5*MINUTES + 17*SECONDS,
111 .nsec_sent_mono = 235*MILLISECONDS + 123*MICROSECONDS + 213*NANOSECONDS,
112 .nsec_sent_real = 451*MILLISECONDS + 435*MICROSECONDS + 135*NANOSECONDS,
113 .nsec_recv_mono = 346*MILLISECONDS + 253*MICROSECONDS + 662*NANOSECONDS,
114 .nsec_recv_real = 734*MILLISECONDS + 543*MICROSECONDS + 254*NANOSECONDS,
119 memcpy(entry->msg, msg, msg_len); // strcpy won't do because msg has an embedded \0 as the tag delimiter
120 for (size_t i = 0; i < msg_len; ++i)
122 entry->header.tag_len = i;
125 assert(entry->header.tag_len >= 0);
127 /* Despite the comment about the single int above,
128 * sometimes we still have to work with it. Make
129 * sure we know the other representation in each
130 * case so that we can easily identify failures. */
131 assert(entry->header.sec_sent_mono == FEBRUARY + 7*DAYS + 2*HOURS + 17*MINUTES + 28*SECONDS);
132 assert(entry->header.sec_sent_real == 6304971);
133 assert(entry->header.sec_recv_mono == JANUARY + 5*DAYS + 5*HOURS + 31*MINUTES + 7*SECONDS);
134 assert(entry->header.sec_recv_real == 2678717);
137 static void invalid_test_msg(struct dlogutil_entry_with_msg *entry, const char *msg, size_t msg_len)
139 standard_test_msg(entry, msg, msg_len);
141 entry->header.pid = -123;
142 entry->header.tid = -456;
143 entry->header.nsec_sent_mono = -78;
144 entry->header.nsec_sent_real = -90;
146 fixup_pipe_msg(entry, msg_len);
149 struct logprint_test_case {
150 log_print_format format;
151 log_priority priority;
156 void check_logprint_testcases(struct dlogutil_entry_with_msg *entry, const struct logprint_test_case *tests, size_t tests_n)
160 for (size_t i = 0; i < tests_n; ++i) {
161 entry->header.priority = tests[i].priority;
162 assert(log_print_log_line((struct log_format){
163 .format = tests[i].format,
164 .color = tests[i].color_enabled,
165 }, 0, &entry->header) > 0);
166 fprintf(stderr, "format=%d, expected %s<, got %s<", tests[i].format, tests[i].result, buffer);
167 assert(!strcmp(tests[i].result, buffer));
173 void check_logprint_testcases_standard(const char *msg, size_t msg_len, const struct logprint_test_case *tests, size_t tests_n)
175 struct dlogutil_entry_with_msg entry;
176 standard_test_msg(&entry, msg, msg_len);
178 check_logprint_testcases(&entry, tests, tests_n);
181 void check_logprint_testcases_invalid(const char *msg, size_t msg_len, const struct logprint_test_case *tests, size_t tests_n)
183 struct dlogutil_entry_with_msg entry;
184 invalid_test_msg(&entry, msg, msg_len);
186 check_logprint_testcases(&entry, tests, tests_n);
189 #define CHECK_LOGPRINT_TESTCASES(MSG, TESTS) check_logprint_testcases_standard(MSG, sizeof MSG, TESTS, NELEMS(TESTS))
190 #define CHECK_LOGPRINT_TESTCASES_INVALID(MSG, TESTS) check_logprint_testcases_invalid(MSG, sizeof MSG, TESTS, NELEMS(TESTS))
192 void check_log_print_log_line()
194 static const struct logprint_test_case tests_basic[] = {
195 // formats using the SENT timestamp
196 {FORMAT_TIME , DLOG_INFO, false, "03-14 23:22:51.451+0000 I/BASIC TAG( 4228): Basic message.\n" },
197 {FORMAT_LONG , DLOG_INFO, false, "[ 03-14 23:22:51.451 I/BASIC TAG P 4228, T 4567]\nBasic message.\n\n" },
198 {FORMAT_THREADTIME , DLOG_INFO, false, "03-14 23:22:51.451+0000 I/BASIC TAG(P 4228, T 4567): Basic message.\n" },
199 {FORMAT_KERNELTIME , DLOG_INFO, false, "3205048.235 I/BASIC TAG(P 4228, T 4567): Basic message.\n" },
201 // formats using the RECV timestamp
202 {FORMAT_RECV_REALTIME, DLOG_INFO, false, "02-01 00:05:17.734 I/BASIC TAG(P 4228, T 4567): Basic message.\n" },
203 {FORMAT_RWTIME , DLOG_INFO, false, "02-01 00:05:17 [3205048.235] I/BASIC TAG(P 4228, T 4567): Basic message.\n"},
205 // formats without a timestamp
206 {FORMAT_BRIEF , DLOG_INFO, false, "I/BASIC TAG( 4228): Basic message.\n" },
207 {FORMAT_PROCESS , DLOG_INFO, false, "I( 4228) Basic message. (BASIC TAG)\n" },
208 {FORMAT_TAG , DLOG_INFO, false, "I/BASIC TAG: Basic message.\n" },
209 {FORMAT_THREAD , DLOG_INFO, false, "I(P 4228, T 4567) Basic message.\n" },
210 {FORMAT_RAW , DLOG_INFO, false, "Basic message.\n" },
212 {FORMAT_JSON , DLOG_INFO, false, "{" \
213 "\"priority\":\"info\"," \
216 "\"recv_real\":\"1970-02-01T00:05:17+0000\"," \
217 "\"recv_mono\":365467.346253662," \
218 "\"sent_real\":\"1970-03-14T23:22:51+0000\"," \
219 "\"sent_mono\":3205048.235123213," \
220 "\"tag\":\"BASIC TAG\"," \
221 "\"msg\":\"Basic message.\"" \
224 CHECK_LOGPRINT_TESTCASES("BASIC TAG\0Basic message.", tests_basic);
226 // Color coded headers
227 static const struct logprint_test_case tests_colors[] = {
229 {FORMAT_TIME , DLOG_FATAL, true, "\033[35;1m03-14 23:22:51.451+0000 F/COLORFUL TAG( 4228): \033[0mBasic message.\n" },
230 {FORMAT_LONG , DLOG_FATAL, true, "\033[35;1m[ 03-14 23:22:51.451 F/COLORFUL TAG P 4228, T 4567]\n\033[0mBasic message.\n\n" },
231 {FORMAT_THREADTIME , DLOG_FATAL, true, "\033[35;1m03-14 23:22:51.451+0000 F/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n" },
232 {FORMAT_KERNELTIME , DLOG_FATAL, true, "\033[35;1m3205048.235 F/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n" },
233 {FORMAT_RECV_REALTIME, DLOG_FATAL, true, "\033[35;1m02-01 00:05:17.734 F/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n" },
234 {FORMAT_RWTIME , DLOG_FATAL, true, "\033[35;1m02-01 00:05:17 [3205048.235] F/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n"},
235 {FORMAT_BRIEF , DLOG_FATAL, true, "\033[35;1mF/COLORFUL TAG( 4228): \033[0mBasic message.\n" },
236 {FORMAT_PROCESS , DLOG_FATAL, true, "\033[35;1mF( 4228) \033[0mBasic message.\033[35;1m (COLORFUL TAG)\n\033[0m" },
237 {FORMAT_TAG , DLOG_FATAL, true, "\033[35;1mF/COLORFUL TAG: \033[0mBasic message.\n" },
238 {FORMAT_THREAD , DLOG_FATAL, true, "\033[35;1mF(P 4228, T 4567) \033[0mBasic message.\n" },
239 {FORMAT_RAW , DLOG_FATAL, true, "Basic message.\n" },
242 {FORMAT_TIME , DLOG_ERROR, true, "\033[31;1m03-14 23:22:51.451+0000 E/COLORFUL TAG( 4228): \033[0mBasic message.\n" },
243 {FORMAT_LONG , DLOG_ERROR, true, "\033[31;1m[ 03-14 23:22:51.451 E/COLORFUL TAG P 4228, T 4567]\n\033[0mBasic message.\n\n" },
244 {FORMAT_THREADTIME , DLOG_ERROR, true, "\033[31;1m03-14 23:22:51.451+0000 E/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n" },
245 {FORMAT_KERNELTIME , DLOG_ERROR, true, "\033[31;1m3205048.235 E/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n" },
246 {FORMAT_RECV_REALTIME, DLOG_ERROR, true, "\033[31;1m02-01 00:05:17.734 E/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n" },
247 {FORMAT_RWTIME , DLOG_ERROR, true, "\033[31;1m02-01 00:05:17 [3205048.235] E/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n"},
248 {FORMAT_BRIEF , DLOG_ERROR, true, "\033[31;1mE/COLORFUL TAG( 4228): \033[0mBasic message.\n" },
249 {FORMAT_PROCESS , DLOG_ERROR, true, "\033[31;1mE( 4228) \033[0mBasic message.\033[31;1m (COLORFUL TAG)\n\033[0m" },
250 {FORMAT_TAG , DLOG_ERROR, true, "\033[31;1mE/COLORFUL TAG: \033[0mBasic message.\n" },
251 {FORMAT_THREAD , DLOG_ERROR, true, "\033[31;1mE(P 4228, T 4567) \033[0mBasic message.\n" },
252 {FORMAT_RAW , DLOG_ERROR, true, "Basic message.\n" },
255 {FORMAT_TIME , DLOG_WARN , true, "\033[33;1m03-14 23:22:51.451+0000 W/COLORFUL TAG( 4228): \033[0mBasic message.\n" },
256 {FORMAT_LONG , DLOG_WARN , true, "\033[33;1m[ 03-14 23:22:51.451 W/COLORFUL TAG P 4228, T 4567]\n\033[0mBasic message.\n\n" },
257 {FORMAT_THREADTIME , DLOG_WARN , true, "\033[33;1m03-14 23:22:51.451+0000 W/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n" },
258 {FORMAT_KERNELTIME , DLOG_WARN , true, "\033[33;1m3205048.235 W/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n" },
259 {FORMAT_RECV_REALTIME, DLOG_WARN , true, "\033[33;1m02-01 00:05:17.734 W/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n" },
260 {FORMAT_RWTIME , DLOG_WARN , true, "\033[33;1m02-01 00:05:17 [3205048.235] W/COLORFUL TAG(P 4228, T 4567): \033[0mBasic message.\n"},
261 {FORMAT_BRIEF , DLOG_WARN , true, "\033[33;1mW/COLORFUL TAG( 4228): \033[0mBasic message.\n" },
262 {FORMAT_PROCESS , DLOG_WARN , true, "\033[33;1mW( 4228) \033[0mBasic message.\033[33;1m (COLORFUL TAG)\n\033[0m" },
263 {FORMAT_TAG , DLOG_WARN , true, "\033[33;1mW/COLORFUL TAG: \033[0mBasic message.\n" },
264 {FORMAT_THREAD , DLOG_WARN , true, "\033[33;1mW(P 4228, T 4567) \033[0mBasic message.\n" },
265 {FORMAT_RAW , DLOG_WARN , true, "Basic message.\n" },
267 // Information -- no color coding needed
268 {FORMAT_TIME , DLOG_INFO , true , "03-14 23:22:51.451+0000 I/COLORFUL TAG( 4228): Basic message.\n" },
269 {FORMAT_LONG , DLOG_INFO , true , "[ 03-14 23:22:51.451 I/COLORFUL TAG P 4228, T 4567]\nBasic message.\n\n" },
270 {FORMAT_THREADTIME , DLOG_INFO , true , "03-14 23:22:51.451+0000 I/COLORFUL TAG(P 4228, T 4567): Basic message.\n" },
271 {FORMAT_KERNELTIME , DLOG_INFO , true , "3205048.235 I/COLORFUL TAG(P 4228, T 4567): Basic message.\n" },
272 {FORMAT_RECV_REALTIME, DLOG_INFO , true , "02-01 00:05:17.734 I/COLORFUL TAG(P 4228, T 4567): Basic message.\n" },
273 {FORMAT_RWTIME , DLOG_INFO , true , "02-01 00:05:17 [3205048.235] I/COLORFUL TAG(P 4228, T 4567): Basic message.\n"},
274 {FORMAT_BRIEF , DLOG_INFO , true , "I/COLORFUL TAG( 4228): Basic message.\n" },
275 {FORMAT_PROCESS , DLOG_INFO , true , "I( 4228) Basic message. (COLORFUL TAG)\n" },
276 {FORMAT_TAG , DLOG_INFO , true , "I/COLORFUL TAG: Basic message.\n" },
277 {FORMAT_THREAD , DLOG_INFO , true , "I(P 4228, T 4567) Basic message.\n" },
278 {FORMAT_RAW , DLOG_INFO , true , "Basic message.\n" },
280 // Color coding disabled
281 {FORMAT_TIME , DLOG_FATAL, false, "03-14 23:22:51.451+0000 F/COLORFUL TAG( 4228): Basic message.\n" },
283 CHECK_LOGPRINT_TESTCASES("COLORFUL TAG\0Basic message.", tests_colors);
285 // Empty tag has special handling and gets replaced.
286 static const struct logprint_test_case tests_tagless[] = {
287 // formats using the SENT timestamp
288 {FORMAT_RECV_REALTIME, DLOG_INFO, false, "02-01 00:05:17.734 I/DLOG_ERROR_NOTAG(P 4228, T 4567): Tagless\n"},
289 {FORMAT_BRIEF , DLOG_INFO, false, "I/DLOG_ERROR_NOTAG( 4228): Tagless\n" },
290 {FORMAT_PROCESS , DLOG_INFO, false, "I( 4228) Tagless (DLOG_ERROR_NOTAG)\n" },
292 CHECK_LOGPRINT_TESTCASES("\0Tagless", tests_tagless);
294 /* Some formats insert the extra info (timestamp, tag etc) every time they
295 * find a line break. The tag itself is never broken up though. */
296 static const struct logprint_test_case tests_linebreak[] = {
297 {FORMAT_LONG, DLOG_INFO, false,
298 "[ 03-14 23:22:51.451 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES P 4228, T 4567]\n"
299 "And\nso\ndoes\nthis\nmessage.\n\n" },
300 {FORMAT_KERNELTIME, DLOG_INFO, false,
301 "3205048.235 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES(P 4228, T 4567): And\n"
302 "3205048.235 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES(P 4228, T 4567): so\n"
303 "3205048.235 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES(P 4228, T 4567): does\n"
304 "3205048.235 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES(P 4228, T 4567): this\n"
305 "3205048.235 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES(P 4228, T 4567): message.\n" },
306 {FORMAT_RECV_REALTIME, DLOG_INFO, false,
307 "02-01 00:05:17.734 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES(P 4228, T 4567): And\n"
308 "02-01 00:05:17.734 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES(P 4228, T 4567): so\n"
309 "02-01 00:05:17.734 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES(P 4228, T 4567): does\n"
310 "02-01 00:05:17.734 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES(P 4228, T 4567): this\n"
311 "02-01 00:05:17.734 I/THIS\nTAG\nTAKES\nMULTIPLE\nLINES(P 4228, T 4567): message.\n" },
312 {FORMAT_PROCESS, DLOG_INFO, false,
313 "I( 4228) And (THIS\nTAG\nTAKES\nMULTIPLE\nLINES)\n"
314 "I( 4228) so (THIS\nTAG\nTAKES\nMULTIPLE\nLINES)\n"
315 "I( 4228) does (THIS\nTAG\nTAKES\nMULTIPLE\nLINES)\n"
316 "I( 4228) this (THIS\nTAG\nTAKES\nMULTIPLE\nLINES)\n"
317 "I( 4228) message. (THIS\nTAG\nTAKES\nMULTIPLE\nLINES)\n" },
319 CHECK_LOGPRINT_TESTCASES("THIS\nTAG\nTAKES\nMULTIPLE\nLINES\0And\nso\ndoes\nthis\nmessage.", tests_linebreak);
321 /* The extras' length gets to be capped (regardless
322 * of which side of the message they are put on). */
323 static const struct logprint_test_case tests_long_metadata[] = {
325 {FORMAT_LONG, DLOG_INFO, false,
326 "[ 03-14 23:22:51.451 I/THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS"
328 {FORMAT_KERNELTIME, DLOG_INFO, false,
329 "3205048.235 I/THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTfoo1\n"
330 "3205048.235 I/THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTfoo2\n" },
331 {FORMAT_RECV_REALTIME, DLOG_INFO, false,
332 "02-01 00:05:17.734 I/THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS Ifoo1\n"
333 "02-01 00:05:17.734 I/THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS Ifoo2\n" },
334 {FORMAT_PROCESS, DLOG_INFO, false,
335 "I( 4228) foo1 (THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TA"
336 "I( 4228) foo2 (THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TA" },
339 {FORMAT_LONG, DLOG_WARN, true,
340 "\033[33;1m[ 03-14 23:22:51.451 W/THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS\033[0m"
342 {FORMAT_KERNELTIME, DLOG_WARN, true,
343 "\033[33;1m3205048.235 W/THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGT\033[0mfoo1\n"
344 "\033[33;1m3205048.235 W/THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGT\033[0mfoo2\n" },
345 {FORMAT_RECV_REALTIME, DLOG_WARN, true,
346 "\033[33;1m02-01 00:05:17.734 W/THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS I\033[0mfoo1\n"
347 "\033[33;1m02-01 00:05:17.734 W/THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS I\033[0mfoo2\n" },
348 {FORMAT_PROCESS, DLOG_WARN, true,
349 "\033[33;1mW( 4228) \033[0mfoo1\033[33;1m (THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TA\033[0m"
350 "\033[33;1mW( 4228) \033[0mfoo2\033[33;1m (THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TA\033[0m" },
352 CHECK_LOGPRINT_TESTCASES("THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH ~ THIS TAG IS OVER 128 CHARS IN LENGTH\0foo1\nfoo2", tests_long_metadata);
354 static const struct logprint_test_case tests_no_msg[] = {
355 {FORMAT_BRIEF , DLOG_INFO, false, "I/SOME_TAG( 4228): DLOG_ERROR_NOMSG\n" },
356 {FORMAT_RAW , DLOG_INFO, false, "DLOG_ERROR_NOMSG\n" },
357 {FORMAT_PROCESS, DLOG_INFO, false, "I( 4228) DLOG_ERROR_NOMSG (SOME_TAG)\n" },
358 {FORMAT_LONG , DLOG_INFO, false, "[ 03-14 23:22:51.451 I/SOME_TAG P 4228, T 4567]\n"
359 "DLOG_ERROR_NOMSG\n\n" },
361 {FORMAT_BRIEF , DLOG_WARN, true, "\033[33;1mW/SOME_TAG( 4228): \033[0mDLOG_ERROR_NOMSG\n" },
362 {FORMAT_RAW , DLOG_WARN, true, "DLOG_ERROR_NOMSG\n" },
363 {FORMAT_PROCESS, DLOG_WARN, true, "\033[33;1mW( 4228) \033[0mDLOG_ERROR_NOMSG\033[33;1m (SOME_TAG)\n\033[0m"},
364 {FORMAT_LONG , DLOG_WARN, true, "\033[33;1m[ 03-14 23:22:51.451 W/SOME_TAG P 4228, T 4567]\n\033[0m"
365 "DLOG_ERROR_NOMSG\n\n" },
367 CHECK_LOGPRINT_TESTCASES("SOME_TAG\0", tests_no_msg);
369 static const struct logprint_test_case tests_no_nothing[] = {
370 {FORMAT_BRIEF , DLOG_INFO, false, "I/DLOG_ERROR_NOTAG( 4228): DLOG_ERROR_NOMSG\n" },
371 {FORMAT_RAW , DLOG_INFO, false, "DLOG_ERROR_NOMSG\n" },
372 {FORMAT_PROCESS, DLOG_INFO, false, "I( 4228) DLOG_ERROR_NOMSG (DLOG_ERROR_NOTAG)\n" },
373 {FORMAT_LONG , DLOG_INFO, false, "[ 03-14 23:22:51.451 I/DLOG_ERROR_NOTAG P 4228, T 4567]\n"
374 "DLOG_ERROR_NOMSG\n\n" },
376 {FORMAT_BRIEF , DLOG_WARN, true, "\033[33;1mW/DLOG_ERROR_NOTAG( 4228): \033[0mDLOG_ERROR_NOMSG\n" },
377 {FORMAT_RAW , DLOG_WARN, true, "DLOG_ERROR_NOMSG\n" },
378 {FORMAT_PROCESS, DLOG_WARN, true, "\033[33;1mW( 4228) \033[0mDLOG_ERROR_NOMSG\033[33;1m "
379 "(DLOG_ERROR_NOTAG)\n\033[0m"},
380 {FORMAT_LONG , DLOG_WARN, true, "\033[33;1m[ 03-14 23:22:51.451 W/DLOG_ERROR_NOTAG P 4228, T 4567]\n\033[0m"
381 "DLOG_ERROR_NOMSG\n\n" },
383 CHECK_LOGPRINT_TESTCASES("\0", tests_no_nothing);
385 static const struct logprint_test_case tests_two_zeros[] = {
386 {FORMAT_BRIEF , DLOG_INFO, false, "I/DLOG_ERROR_NOTAG( 4228): DLOG_ERROR_NOMSG\n" },
387 {FORMAT_RAW , DLOG_INFO, false, "DLOG_ERROR_NOMSG\n" },
388 {FORMAT_PROCESS, DLOG_INFO, false, "I( 4228) DLOG_ERROR_NOMSG (DLOG_ERROR_NOTAG)\n" },
389 {FORMAT_LONG , DLOG_INFO, false, "[ 03-14 23:22:51.451 I/DLOG_ERROR_NOTAG P 4228, T 4567]\n"
390 "DLOG_ERROR_NOMSG\n\n" },
392 {FORMAT_BRIEF , DLOG_WARN, true, "\033[33;1mW/DLOG_ERROR_NOTAG( 4228): \033[0mDLOG_ERROR_NOMSG\n" },
393 {FORMAT_RAW , DLOG_WARN, true, "DLOG_ERROR_NOMSG\n" },
394 {FORMAT_PROCESS, DLOG_WARN, true, "\033[33;1mW( 4228) \033[0mDLOG_ERROR_NOMSG\033[33;1m "
395 "(DLOG_ERROR_NOTAG)\n\033[0m"},
396 {FORMAT_LONG , DLOG_WARN, true, "\033[33;1m[ 03-14 23:22:51.451 W/DLOG_ERROR_NOTAG P 4228, T 4567]\n\033[0m"
397 "DLOG_ERROR_NOMSG\n\n" },
399 CHECK_LOGPRINT_TESTCASES("\0\0", tests_two_zeros);
401 static const struct logprint_test_case tests_garbage[] = {
402 {FORMAT_BRIEF , DLOG_INFO, false, "I/DLOG_ERROR_NOTAG( 4228): DLOG_ERROR_NOMSG\n" },
403 {FORMAT_RAW , DLOG_INFO, false, "DLOG_ERROR_NOMSG\n" },
404 {FORMAT_PROCESS, DLOG_INFO, false, "I( 4228) DLOG_ERROR_NOMSG (DLOG_ERROR_NOTAG)\n" },
405 {FORMAT_LONG , DLOG_INFO, false, "[ 03-14 23:22:51.451 I/DLOG_ERROR_NOTAG P 4228, T 4567]\n"
406 "DLOG_ERROR_NOMSG\n\n" },
408 {FORMAT_BRIEF , DLOG_WARN, true, "\033[33;1mW/DLOG_ERROR_NOTAG( 4228): \033[0mDLOG_ERROR_NOMSG\n" },
409 {FORMAT_RAW , DLOG_WARN, true, "DLOG_ERROR_NOMSG\n" },
410 {FORMAT_PROCESS, DLOG_WARN, true, "\033[33;1mW( 4228) \033[0mDLOG_ERROR_NOMSG\033[33;1m "
411 "(DLOG_ERROR_NOTAG)\n\033[0m"},
412 {FORMAT_LONG , DLOG_WARN, true, "\033[33;1m[ 03-14 23:22:51.451 W/DLOG_ERROR_NOTAG P 4228, T 4567]\n\033[0m"
413 "DLOG_ERROR_NOMSG\n\n" },
415 CHECK_LOGPRINT_TESTCASES("\0\0GARBAGE", tests_garbage);
417 static const struct logprint_test_case tests_only_one_zero[] = {
418 {FORMAT_BRIEF , DLOG_INFO, false, "I/THIS_IS_WEIRD( 4228): DLOG_ERROR_NOMSG\n" },
419 {FORMAT_RAW , DLOG_INFO, false, "DLOG_ERROR_NOMSG\n" },
420 {FORMAT_PROCESS, DLOG_INFO, false, "I( 4228) DLOG_ERROR_NOMSG (THIS_IS_WEIRD)\n" },
421 {FORMAT_LONG , DLOG_INFO, false, "[ 03-14 23:22:51.451 I/THIS_IS_WEIRD P 4228, T 4567]\n"
422 "DLOG_ERROR_NOMSG\n\n" },
424 {FORMAT_BRIEF , DLOG_WARN, true, "\033[33;1mW/THIS_IS_WEIRD( 4228): \033[0mDLOG_ERROR_NOMSG\n" },
425 {FORMAT_RAW , DLOG_WARN, true, "DLOG_ERROR_NOMSG\n" },
426 {FORMAT_PROCESS, DLOG_WARN, true, "\033[33;1mW( 4228) \033[0mDLOG_ERROR_NOMSG\033[33;1m "
427 "(THIS_IS_WEIRD)\n\033[0m"},
428 {FORMAT_LONG , DLOG_WARN, true, "\033[33;1m[ 03-14 23:22:51.451 W/THIS_IS_WEIRD P 4228, T 4567]\n\033[0m"
429 "DLOG_ERROR_NOMSG\n\n" },
431 CHECK_LOGPRINT_TESTCASES("THIS_IS_WEIRD", tests_only_one_zero);
433 static const struct logprint_test_case tests_fixup_pipe[] = {
434 // formats using the SENT timestamp (nominally)
435 {FORMAT_TIME , DLOG_INFO, false, "02-01 00:05:17.734+0000 I/BASIC TAG( 0): Basic message.\n"
436 "[dlog inline warning: modified invalid timestamp]\n" },
437 {FORMAT_LONG , DLOG_INFO, false, "[ 02-01 00:05:17.734 I/BASIC TAG P 0, T 0]\n"
439 "[dlog inline warning: modified invalid timestamp]\n\n" },
440 {FORMAT_THREADTIME , DLOG_INFO, false, "02-01 00:05:17.734+0000 I/BASIC TAG(P 0, T 0): Basic message.\n"
441 "[dlog inline warning: modified invalid timestamp]\n" },
442 {FORMAT_KERNELTIME , DLOG_INFO, false, "365467.346 I/BASIC TAG(P 0, T 0): Basic message.\n"
443 "365467.346 I/BASIC TAG(P 0, T 0): [dlog inline warning: modified invalid timestamp]\n" },
445 // formats using the RECV timestamp
446 {FORMAT_RECV_REALTIME, DLOG_INFO, false, "02-01 00:05:17.734 I/BASIC TAG(P 0, T 0): Basic message.\n"
447 "02-01 00:05:17.734 I/BASIC TAG(P 0, T 0): [dlog inline warning: modified invalid timestamp]\n" },
448 {FORMAT_RWTIME , DLOG_INFO, false, "02-01 00:05:17 [365467.346] I/BASIC TAG(P 0, T 0): Basic message.\n"
449 "[dlog inline warning: modified invalid timestamp]\n" },
451 // formats without a timestamp
452 {FORMAT_BRIEF , DLOG_INFO, false, "I/BASIC TAG( 0): Basic message.\n"
453 "[dlog inline warning: modified invalid timestamp]\n" },
454 {FORMAT_PROCESS , DLOG_INFO, false, "I( 0) Basic message. (BASIC TAG)\n"
455 "I( 0) [dlog inline warning: modified invalid timestamp] (BASIC TAG)\n" },
456 {FORMAT_TAG , DLOG_INFO, false, "I/BASIC TAG: Basic message.\n"
457 "[dlog inline warning: modified invalid timestamp]\n" },
458 {FORMAT_THREAD , DLOG_INFO, false, "I(P 0, T 0) Basic message.\n"
459 "[dlog inline warning: modified invalid timestamp]\n" },
460 {FORMAT_RAW , DLOG_INFO, false, "Basic message.\n"
461 "[dlog inline warning: modified invalid timestamp]\n" },
463 {FORMAT_JSON , DLOG_INFO, false, "{" \
464 "\"priority\":\"info\"," \
467 "\"recv_real\":\"1970-02-01T00:05:17+0000\"," \
468 "\"recv_mono\":365467.346253662," \
469 "\"sent_real\":\"1970-02-01T00:05:17+0000\"," \
470 "\"sent_mono\":365467.346253662," \
471 "\"tag\":\"BASIC TAG\"," \
472 "\"msg\":\"Basic message.\\n" \
473 "[dlog inline warning: modified invalid timestamp]\"" \
476 CHECK_LOGPRINT_TESTCASES_INVALID("BASIC TAG\0Basic message.", tests_fixup_pipe);
479 char *json_escape_string(char *in);
480 void check_json_escape_string_testcase(char *in, char *correct)
482 char *out = json_escape_string(in);
484 assert(!strcmp(out, correct));
492 const char *json_priority_name(log_priority prio);
493 struct timespec entry_get_ts(const dlogutil_entry_s *entry, bool sent, bool mono);
494 char *log_format_json(char *default_buffer, size_t default_buffer_size, const dlogutil_entry_s *entry, size_t *p_outLength, char *tag, char *msg);
497 // TODO: Failure testing
498 check_json_escape_string_testcase("abc/def", "abc/def");
499 check_json_escape_string_testcase("\x01\x02\x03", "\\u0001\\u0002\\u0003");
500 check_json_escape_string_testcase("\x1A\x1B\x1C", "\\u001A\\u001B\\u001C");
501 check_json_escape_string_testcase("\x1D\x1E\x1F", "\\u001D\\u001E\\u001F");
502 check_json_escape_string_testcase("\"\\\b\f\n\r\t", "\\\"\\\\\\b\\f\\n\\r\\t");
503 check_json_escape_string_testcase("zażółć gęślą jaźń", "zażółć gęślą jaźń");
504 check_json_escape_string_testcase("삼성", "삼성");
505 check_json_escape_string_testcase("タイゼン", "タイゼン");
506 check_json_escape_string_testcase("🏀", "🏀");
508 assert(!strcmp(json_priority_name(DLOG_VERBOSE), "verbose"));
509 assert(!strcmp(json_priority_name(DLOG_DEBUG), "debug"));
510 assert(!strcmp(json_priority_name(DLOG_INFO), "info"));
511 assert(!strcmp(json_priority_name(DLOG_WARN), "warning"));
512 assert(!strcmp(json_priority_name(DLOG_ERROR), "error"));
513 assert(!strcmp(json_priority_name(DLOG_FATAL), "fatal"));
514 assert(!strcmp(json_priority_name(DLOG_SILENT), "silent"));
515 assert(!strcmp(json_priority_name(DLOG_UNKNOWN), "unknown"));
516 assert(!strcmp(json_priority_name(123), "unknown"));
518 char data[] = "tag\0important message";
519 dlogutil_entry_s *ent = calloc(1, sizeof(dlogutil_entry_s) + sizeof data);
521 ent->len = sizeof data;
523 strncpy(ent->msg, data, ent->len);
524 ent->priority = DLOG_DEBUG;
530 #define TEST_EMPTY_TIMESTAMP() \
531 ent->nsec_sent_mono = ent->nsec_recv_mono = ent->nsec_sent_real = ent->nsec_recv_real = -1; \
532 ts = entry_get_ts(ent, CURRENT_SENT, CURRENT_MONO); \
533 assert(ts.tv_sec == 0); \
534 assert(ts.tv_nsec == 0)
535 #define TEST_SINGLE_TIMESTAMP(which, to_set, expected) \
536 ent->sec_##which = ent->nsec_##which = to_set; \
537 ts = entry_get_ts(ent, CURRENT_SENT, CURRENT_MONO); \
538 assert(ts.tv_sec == expected); \
539 assert(ts.tv_nsec == expected)
541 #define CURRENT_MONO true
542 #define CURRENT_SENT true
543 TEST_EMPTY_TIMESTAMP();
544 TEST_SINGLE_TIMESTAMP(recv_real, 1, 1);
545 TEST_SINGLE_TIMESTAMP(sent_real, 2, 2);
546 TEST_SINGLE_TIMESTAMP(recv_mono, 3, 3);
547 TEST_SINGLE_TIMESTAMP(sent_mono, 4, 4);
550 #define CURRENT_SENT false
551 TEST_EMPTY_TIMESTAMP();
552 TEST_SINGLE_TIMESTAMP(sent_real, 1, 1);
553 TEST_SINGLE_TIMESTAMP(recv_real, 2, 2);
554 TEST_SINGLE_TIMESTAMP(sent_mono, 3, 3);
555 TEST_SINGLE_TIMESTAMP(recv_mono, 4, 4);
559 #define CURRENT_MONO false
560 #define CURRENT_SENT true
561 TEST_EMPTY_TIMESTAMP();
562 TEST_SINGLE_TIMESTAMP(recv_mono, 1, 0);
563 TEST_SINGLE_TIMESTAMP(sent_mono, 2, 0);
564 TEST_SINGLE_TIMESTAMP(recv_real, 3, 3);
565 TEST_SINGLE_TIMESTAMP(sent_real, 4, 4);
568 #define CURRENT_SENT false
569 TEST_EMPTY_TIMESTAMP();
570 TEST_SINGLE_TIMESTAMP(sent_mono, 1, 0);
571 TEST_SINGLE_TIMESTAMP(recv_mono, 2, 0);
572 TEST_SINGLE_TIMESTAMP(sent_real, 3, 3);
573 TEST_SINGLE_TIMESTAMP(recv_real, 4, 4);
577 #undef TEST_EMPTY_TIMESTAMP
578 #undef TEST_SINGLE_TIMESTAMP
583 ent->nsec_sent_mono = ent->nsec_recv_mono = ent->nsec_sent_real = ent->nsec_recv_real = -1;
584 assert(log_format_json(buf, sizeof(buf), ent, &out_len, "tag", "message") == buf);
585 assert(strlen(buf) == out_len);
586 assert(!strcmp(buf, "{" \
587 "\"priority\":\"debug\"," \
591 "\"msg\":\"message\"" \
595 target = log_format_json(NULL, out_len, ent, &out_len, "tag", "message");
597 assert(target != buf);
598 assert(strlen(target) == out_len);
599 assert(!strcmp(buf, target));
602 ent->sec_sent_mono = ent->nsec_sent_mono = 21;
603 ent->sec_recv_mono = ent->nsec_recv_mono = 22;
604 ent->sec_sent_real = ent->nsec_sent_real = 23242527;
605 ent->sec_recv_real = ent->nsec_recv_real = 28293031;
606 assert(log_format_json(buf, sizeof(buf), ent, &out_len, "tag", "message") == buf);
607 assert(strlen(buf) == out_len);
608 assert(!strcmp(buf, "{"\
609 "\"priority\":\"debug\","\
612 "\"recv_real\":\"1970-11-24T11:10:31+0000\","\
613 "\"recv_mono\":22.000000022,"\
614 "\"sent_real\":\"1970-09-27T00:15:27+0000\","\
615 "\"sent_mono\":21.000000021,"\
617 "\"msg\":\"message\""\
620 char data2[] = "∫\0\x01\x02\x03\x14\x15\x16\"\\\b\f\n\r\t🤔";
621 assert(sizeof data == sizeof data2);
622 strncpy(ent->msg, data2, ent->len);
623 assert(log_format_json(buf, sizeof(buf), ent, &out_len, "∫", "\x01\x02\x03\x14\x15\x16\"\\\b\f\n\r\t🤔") == buf);
624 assert(strlen(buf) == out_len);
625 assert(!strcmp(buf, "{"\
626 "\"priority\":\"debug\","\
629 "\"recv_real\":\"1970-11-24T11:10:31+0000\","\
630 "\"recv_mono\":22.000000022,"\
631 "\"sent_real\":\"1970-09-27T00:15:27+0000\","\
632 "\"sent_mono\":21.000000021,"\
634 "\"msg\":\"\\u0001\\u0002\\u0003\\u0014\\u0015\\u0016\\\"\\\\\\b\\f\\n\\r\\t🤔\""\
640 void check_syscall_failure_handling()
642 dlogutil_filter_options_s *const filter = log_filter_new();
644 assert(!dlogutil_filter_options_set_tid(filter, 123));
645 assert(!dlogutil_filter_options_set_pid(filter, 456));
646 assert(!log_add_filter_rule(filter, "FOO:E"));
648 dlogutil_filter_options_s *const clone = log_filter_from_filter(filter);
650 log_filter_free(clone);
653 assert(!log_filter_new());
654 assert(!log_filter_from_filter(filter));
655 assert(TIZEN_ERROR_OUT_OF_MEMORY == dlogutil_filter_options_set_tid(filter, 123));
656 assert(TIZEN_ERROR_OUT_OF_MEMORY == dlogutil_filter_options_set_pid(filter, 456));
659 // Not really a syscall, but eh
660 fail_list_add = true;
661 assert(TIZEN_ERROR_OUT_OF_MEMORY == log_add_filter_rule(filter, "FOO:E"));
662 fail_list_add = false;
665 assert(!log_filter_from_filter(filter));
666 assert(TIZEN_ERROR_OUT_OF_MEMORY == dlogutil_filter_options_set_filterspec(filter, "FOO:E"));
667 assert(TIZEN_ERROR_OUT_OF_MEMORY == log_add_filter_rule(filter, "FOO:E"));
670 fail_strndup = true; // N
671 assert(TIZEN_ERROR_OUT_OF_MEMORY == dlogutil_filter_options_set_filterspec(filter, "FOO:E"));
672 fail_strndup = false;
674 /* the array size is an arbitrary value between 512, i.e. the size of the default buffer,
675 * and 4096, i.e. LOG_MAX_PAYLOAD_SIZE (higher should also work but would be pointless). */
677 [0 ... 41] = 'A', // tag
679 [43 ... sizeof msg - 2] = 'a', // msg
680 [sizeof msg - 1] = '\0'
682 struct dlogutil_entry_with_msg entry;
683 standard_test_msg(&entry, msg, sizeof msg);
685 struct log_format format = {
686 .format = FORMAT_TIME,
691 assert(-1 == log_print_log_line(format, 0, &entry.header));
694 fail_localtime_r = true;
695 assert(-1 == log_print_log_line(format, 0, &entry.header));
696 fail_localtime_r = false;
699 assert(0 == log_print_log_line(format, 0, &entry.header));
702 assert(17 == log_print_log_line(format, 0, &entry.header));
705 log_filter_free(filter);
708 void check_invalid_input()
710 const dlogutil_entry_s entry = { .len = 1 };
713 assert(dlogutil_entry_get_message(&entry, &data) == TIZEN_ERROR_NO_DATA);
716 assert(dlogutil_entry_get_tag(&entry, &data) == TIZEN_ERROR_NO_DATA);
719 dlogutil_filter_options_s *const filter = log_filter_new();
721 assert(TIZEN_ERROR_INVALID_PARAMETER == log_add_filter_rule(filter, ":D")); // >mfw tagless rule gets processed correctly
722 log_filter_free(filter);
725 void check_log_format_from_string()
727 static const struct {
729 log_print_format format;
730 } expected_formats[] = {
731 {"brief" , FORMAT_BRIEF },
732 {" brief" , FORMAT_OFF },
733 {"tag" , FORMAT_TAG },
734 {"tagging up turf", FORMAT_OFF },
735 {"process" , FORMAT_PROCESS },
736 {"long" , FORMAT_LONG },
737 {"thien long" , FORMAT_OFF },
738 {"threadtime" , FORMAT_THREADTIME},
739 {"kerneltime" , FORMAT_KERNELTIME},
740 {"hammertime" , FORMAT_OFF },
743 for (size_t i = 0; i < NELEMS(expected_formats); ++i)
744 assert(log_format_from_string(expected_formats[i].string) == expected_formats[i].format);
747 void check_get_format_sorting()
749 static const struct {
750 log_print_format format;
751 dlogutil_sorting_order_e sorting;
752 } expected_sorting[] = {
753 {FORMAT_TAG , DLOGUTIL_SORT_DEFAULT },
754 {FORMAT_PROCESS , DLOGUTIL_SORT_DEFAULT },
755 {FORMAT_THREAD , DLOGUTIL_SORT_DEFAULT },
756 {FORMAT_RAW , DLOGUTIL_SORT_DEFAULT },
757 {FORMAT_BRIEF , DLOGUTIL_SORT_DEFAULT },
758 {FORMAT_TIME , DLOGUTIL_SORT_SENT_REAL},
759 {FORMAT_THREADTIME , DLOGUTIL_SORT_SENT_REAL},
760 {FORMAT_KERNELTIME , DLOGUTIL_SORT_SENT_MONO},
761 {FORMAT_LONG , DLOGUTIL_SORT_SENT_REAL},
762 {FORMAT_RWTIME , DLOGUTIL_SORT_RECV_REAL},
763 {FORMAT_RECV_REALTIME, DLOGUTIL_SORT_RECV_REAL},
766 for (size_t i = 0; i < NELEMS(expected_sorting); ++i) {
767 assert(get_format_sorting(expected_sorting[i].format) == expected_sorting[i].sorting);
771 void check_filter_pri_to_char()
773 static const struct {
777 {DLOG_VERBOSE , 'V' },
783 {DLOG_SILENT , 'S' },
784 }, expected_pris[] = {
785 {DLOG_UNKNOWN , '0' },
786 {DLOG_DEFAULT , '1' },
787 {DLOG_VERBOSE , '2' },
793 {DLOG_VERBOSE , '8' }, // makes little sense but ok
794 {DLOG_VERBOSE , '9' }, // ditto
796 {DLOG_VERBOSE , 'v' },
802 {DLOG_SILENT , 's' },
803 {DLOG_DEFAULT , '*' },
805 {DLOG_UNKNOWN , 'l' },
806 {DLOG_UNKNOWN , 'L' },
807 {DLOG_UNKNOWN , ' ' },
808 {DLOG_UNKNOWN , '\a'},
809 {DLOG_UNKNOWN , '\0'},
810 }, expected_chars[] = {
811 {DLOG_DEFAULT , '?' },
812 {DLOG_UNKNOWN , '?' },
813 {(log_priority)42, '?' },
814 {(log_priority)-9, '?' },
817 for (size_t i = 0; i < NELEMS(convertibles); ++i) {
818 assert(filter_pri_to_char(convertibles[i].pri) == convertibles[i].c);
819 assert(filter_char_to_pri(convertibles[i].c) == convertibles[i].pri);
822 for (size_t i = 0; i < NELEMS(expected_pris); ++i)
823 assert(filter_char_to_pri(expected_pris[i].c) == expected_pris[i].pri);
825 for (size_t i = 0; i < NELEMS(expected_chars); ++i)
826 assert(filter_pri_to_char(expected_chars[i].pri) == expected_chars[i].c);
829 void log_filter_default()
831 dlogutil_filter_options_s *const filter = log_filter_new();
832 bool ret = log_filter_need_apply_default(filter);
834 log_filter_free(filter);
839 check_log_format_from_string();
840 check_get_format_sorting();
841 check_filter_pri_to_char();
842 check_log_print_log_line();
843 check_invalid_input();
844 check_syscall_failure_handling();
846 log_filter_default();