2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include <logcommon.h>
24 #include <dlog_ioctl.h>
50 const char *mode_names[] = {
52 [MODE_TIMER] = "timer",
53 [MODE_CONTINUOUS] = "continuous",
54 [MODE_MONITOR] = "monitor",
55 [MODE_PRIORITY] = "priority",
56 [MODE_PRIORITY_EXACT] = "priority_exact",
57 [MODE_LIMIT] = "limit",
58 [MODE_PID_CORRECT] = "pid_correct",
59 [MODE_PID_WRONG] = "pid_wrong",
60 [MODE_TID_CORRECT] = "tid_correct",
61 [MODE_TID_WRONG] = "tid_wrong",
62 [MODE_TAG_CORRECT] = "tag_correct",
63 [MODE_TAG_WRONG] = "tag_wrong",
64 [MODE_PREFIX_CORRECT] = "prefix_correct",
65 [MODE_PREFIX_WRONG] = "prefix_wrong",
66 [MODE_SORTING] = "sorting",
67 [MODE_TRAITS] = "traits",
68 [MODE_CLEAR] = "clear",
69 [MODE_ALIAS] = "alias",
70 [MODE_NEGATIVE] = "negative",
73 const char *mode_desc[] = {
74 [MODE_DUMP] = "test getting logs in the dump mode",
75 [MODE_TIMER] = "same, but waiting on each log to simulate work",
76 [MODE_CONTINUOUS] = "test getting logs in the continuous mode",
77 [MODE_MONITOR] = "test that monitor mode skips all the old logs",
78 [MODE_PRIORITY] = "only warning and above, we should get only error logs",
79 [MODE_PRIORITY_EXACT] = "only warning, we should get no logs",
80 [MODE_LIMIT] = "limit to 100 logs without filtering, we should get exactly 50 error and exactly 50 info logs",
81 [MODE_PID_CORRECT] = "filter PID to the correct one, we should get same results as in the normal test mode",
82 [MODE_PID_WRONG] = "filter PID to the wrong one, we should get no logs",
83 [MODE_TID_CORRECT] = "filter TID to the correct one, we should get same results as in the normal test mode",
84 [MODE_TID_WRONG] = "filter TID to the wrong one, we should get no logs",
85 [MODE_TAG_CORRECT] = "filter the tag to the correct one, we should get same results as in the normal testmode",
86 [MODE_TAG_WRONG] = "filter the tag to a wrong one, we should get no logs",
87 [MODE_PREFIX_CORRECT] = "filter the tag to the correct one via prefix, we should get same results as in the normal test mode",
88 [MODE_PREFIX_WRONG] = "filter the tag to a wrong one via prefix, we should get same results as in the normal test mode",
90 [MODE_SORTING] = "test timestamp sorting -- in this case, the PID is ignored",
91 [MODE_TRAITS] = "test buffer traits functionality -- in this case, the PID is ignored",
92 [MODE_CLEAR] = "test clearing functionality -- in this case, the PID is ignored",
93 [MODE_ALIAS] = "test buffer aliasing -- in this case, the PID is ignored",
94 [MODE_NEGATIVE] = "test whether libdlogutil errors out correctly",
97 void print_usage_and_die(const char *name)
99 fprintf(stderr, "Usage: %s TEST PID TYPE\n"
100 "where PID is the process id of the logging process,\n"
101 "TYPE is \"pipe\" or \"logger\" depending on the backend used,\n"
102 "and TEST chooses a test and is one of the following:\n", name);
104 for (size_t i = 0; i < MODE_INVALID; ++i)
105 fprintf(stderr, " - %s: %s\n", mode_names[i], mode_desc[i]);
110 enum test_mode choose_mode(const char *name)
112 for (size_t i = 0; i < MODE_INVALID; ++i)
113 if (!strcmp(name, mode_names[i]))
119 void assert_suffix(const char *string, const char *suffix)
121 int add = (int)strlen(string) - strlen(suffix);
122 assert(add >= 0 && !strcmp(string + add, suffix));
125 /* The amount of logs is deterministic and based on buffer size,
126 * log header size, the amount of logs sent and their contents. */
127 #define PIPE_ERRORS 4681
128 #define PIPE_INFOS 4681
130 void get_logs_main(enum test_mode mode, bool pipe, pid_t pid)
132 bool continuous = mode == MODE_CONTINUOUS;
133 bool monitor = mode == MODE_MONITOR;
140 dlogutil_config_s *c = dlogutil_config_create();
143 dlogutil_config_buffer_add(c, LOG_ID_MAIN);
147 assert(dlogutil_config_filter_filterspec(c, "*:W") == 0);
149 case MODE_PRIORITY_EXACT:
150 assert(dlogutil_config_filter_filterspec(c, "*:=W") == 0);
152 case MODE_PID_CORRECT:
153 assert(dlogutil_config_filter_pid(c, pid) == 0);
156 assert(dlogutil_config_filter_pid(c, pid ^ 1) == 0);
158 case MODE_TID_CORRECT:
159 assert(dlogutil_config_filter_tid(c, pid) == 0);
162 assert(dlogutil_config_filter_tid(c, pid ^ 1) == 0);
164 case MODE_TAG_CORRECT:
165 dlogutil_config_filter_filterspec(c, "SRPOL_LOGGER");
168 dlogutil_config_filter_filterspec(c, "SRPOL_WRONG");
170 case MODE_PREFIX_CORRECT:
171 dlogutil_config_filter_filterspec(c, "SRPOL*");
173 case MODE_PREFIX_WRONG:
174 dlogutil_config_filter_filterspec(c, "WRONG*");
180 dlogutil_state_s *s = NULL;
182 r = dlogutil_config_mode_set_continuous(c);
184 r = dlogutil_config_mode_set_monitor(c);
186 r = dlogutil_config_mode_set_dump(c, mode == MODE_LIMIT ? 100 : DLOGUTIL_MAX_DUMP_SIZE);
189 assert(dlogutil_config_connect(c, &s) == 0);
192 struct timespec a, b;
197 clock_gettime(CLOCK_MONOTONIC, &a);
198 r = dlogutil_get_log(s, continuous || monitor ? 1000 : -1, &e);
199 clock_gettime(CLOCK_MONOTONIC, &b);
200 unsigned dt = (b.tv_sec - a.tv_sec) * 1000 + (b.tv_nsec - a.tv_nsec) / 1000000;
207 r = dlogutil_entry_get_priority(e, &prio);
210 const char *tag, *msg;
211 r = dlogutil_entry_get_tag(e, &tag);
213 r = dlogutil_entry_get_message(e, &msg);
216 assert(!strcmp(tag, "SRPOL_LOGGER"));
219 r = dlogutil_entry_get_pid(e, &apid);
221 r = dlogutil_entry_get_tid(e, &atid);
230 assert_suffix(msg, "test data, level: error");
234 assert_suffix(msg, "test data, level: info");
240 if (mode == MODE_TIMER)
241 nanosleep(&(struct timespec) {
243 .tv_nsec = rand() % (1 << 18),
248 if (continuous || monitor) {
249 assert(r == TIZEN_ERROR_TIMED_OUT);
252 assert(r == TIZEN_ERROR_NO_DATA);
259 dlogutil_state_destroy(s);
260 dlogutil_config_destroy(c);
265 case MODE_CONTINUOUS:
266 case MODE_PID_CORRECT:
267 case MODE_TID_CORRECT:
268 case MODE_TAG_CORRECT:
269 case MODE_PREFIX_CORRECT:
271 assert(error_count == PIPE_ERRORS);
272 assert(info_count == PIPE_INFOS);
274 assert(abs(error_count - info_count) <= 1);
279 assert(error_count == PIPE_ERRORS);
281 assert(error_count > 0);
282 assert(info_count == 0);
285 case MODE_PRIORITY_EXACT:
289 case MODE_PREFIX_WRONG:
290 assert(error_count == 0);
291 assert(info_count == 0);
294 assert(error_count == 50);
295 assert(info_count == 50);
302 unsigned int MB(unsigned int x)
304 return 1024 * 1024 * x;
307 void traits_main(bool pipe)
309 dlogutil_config_s *config = dlogutil_config_create();
312 assert(dlogutil_config_buffer_add(config, LOG_ID_MAIN) == 0);
313 assert(dlogutil_config_buffer_add(config, LOG_ID_KMSG) == 0);
315 dlogutil_state_s *state;
316 assert(dlogutil_config_connect(config, &state) == 0);
317 dlogutil_config_destroy(config);
320 assert(dlogutil_buffer_get_name(LOG_ID_MAIN, &name) == 0);
321 assert(!strcmp(name, "main"));
323 assert(dlogutil_buffer_get_name(LOG_ID_KMSG, &name) == 0);
324 assert(!strcmp(name, "kmsg"));
326 unsigned int capacity, usage;
327 assert(dlogutil_buffer_get_capacity(state, LOG_ID_MAIN, &capacity) == 0);
328 assert(dlogutil_buffer_get_usage(state, LOG_ID_MAIN, &usage) == 0);
330 assert(capacity == MB(1));
332 int fd = open("/dev/log_main", O_RDONLY);
333 int real_capacity = ioctl(fd, LOGGER_GET_LOG_BUF_SIZE);
335 assert(capacity == real_capacity);
339 assert(dlogutil_buffer_get_capacity(state, LOG_ID_KMSG, &capacity) == 0);
340 assert(dlogutil_buffer_get_usage(state, LOG_ID_KMSG, &usage) == 0);
341 assert(capacity == MB(1));
343 dlogutil_sorting_order_e type;
344 assert(dlogutil_buffer_get_default_ts_type(LOG_ID_MAIN, &type) == 0);
345 assert(type == (pipe ? DLOGUTIL_SORT_RECV_MONO : DLOGUTIL_SORT_SENT_REAL));
348 assert(dlogutil_buffer_check_ts_type_available(LOG_ID_MAIN, DLOGUTIL_SORT_SENT_MONO, &available) == 0);
349 assert(available == pipe);
351 assert(dlogutil_buffer_check_ts_type_available(LOG_ID_MAIN, DLOGUTIL_SORT_SENT_REAL, &available) == 0);
354 assert(dlogutil_buffer_check_ts_type_available(LOG_ID_MAIN, DLOGUTIL_SORT_RECV_MONO, &available) == 0);
355 assert(available == pipe);
357 assert(dlogutil_buffer_check_ts_type_available(LOG_ID_MAIN, DLOGUTIL_SORT_RECV_REAL, &available) == 0);
358 assert(available == pipe);
360 assert(dlogutil_buffer_check_ts_type_available(LOG_ID_KMSG, DLOGUTIL_SORT_SENT_MONO, &available) == 0);
363 assert(dlogutil_buffer_check_ts_type_available(LOG_ID_KMSG, DLOGUTIL_SORT_SENT_REAL, &available) == 0);
366 assert(dlogutil_buffer_check_ts_type_available(LOG_ID_KMSG, DLOGUTIL_SORT_RECV_MONO, &available) == 0);
369 assert(dlogutil_buffer_check_ts_type_available(LOG_ID_KMSG, DLOGUTIL_SORT_RECV_REAL, &available) == 0);
372 dlogutil_state_destroy(state);
375 void clear_main(void)
378 dlogutil_config_s *c = dlogutil_config_create();
380 assert(dlogutil_config_buffer_add(c, LOG_ID_MAIN) == 0);
384 assert(dlogutil_config_connect(c, &s) == 0);
385 assert(dlogutil_buffer_clear(s, LOG_ID_MAIN) == 0);
386 dlogutil_state_destroy(s);
388 assert(dlogutil_config_mode_set_dump(c, DLOGUTIL_MAX_DUMP_SIZE) == 0);
389 assert(dlogutil_config_connect(c, &s) == 0);
391 assert(dlogutil_get_log(s, 1000, &e) == TIZEN_ERROR_NO_DATA);
392 dlogutil_state_destroy(s);
394 dlogutil_config_destroy(c);
397 bool sorting_check(dlogutil_sorting_order_e o)
399 dlogutil_config_s *config = dlogutil_config_create();
402 assert(dlogutil_config_buffer_add(config, LOG_ID_MAIN) == 0);
403 assert(dlogutil_config_sorting_enable(config) == 0);
404 assert(dlogutil_config_order_set(config, o) == 0);
405 assert(dlogutil_config_mode_set_dump(config, DLOGUTIL_MAX_DUMP_SIZE) == 0);
408 assert(dlogutil_config_connect(config, &s) == 0);
410 struct timespec t = {
418 int r = dlogutil_get_log(s, -1, &e);
419 if (r == TIZEN_ERROR_NO_DATA)
423 struct timespec t_new;
424 r = dlogutil_entry_get_timestamp(e, o, &t_new);
425 if (r == TIZEN_ERROR_NO_DATA) {
430 assert(t.tv_sec <= t_new.tv_sec);
431 assert(t.tv_sec < t_new.tv_sec || t.tv_nsec <= t_new.tv_nsec);
437 dlogutil_state_destroy(s);
438 dlogutil_config_destroy(config);
442 void sorting_main(int left)
444 #define ONE(ts) left -= sorting_check(ts) ? 1 : 0
446 ONE(DLOGUTIL_SORT_RECV_MONO);
447 ONE(DLOGUTIL_SORT_RECV_REAL);
448 ONE(DLOGUTIL_SORT_SENT_MONO);
449 ONE(DLOGUTIL_SORT_SENT_REAL);
456 void alias_main(bool pipe)
458 dlogutil_config_s *config = dlogutil_config_create();
460 assert(dlogutil_config_buffer_add(config, LOG_ID_MAIN) == 0);
461 assert(dlogutil_config_buffer_add(config, LOG_ID_APPS) == 0);
462 assert(dlogutil_config_buffer_add(config, LOG_ID_RADIO) == 0);
463 assert(dlogutil_config_buffer_add(config, LOG_ID_SYSTEM) == 0);
464 assert(dlogutil_config_buffer_add(config, LOG_ID_KMSG) == 0);
466 dlogutil_state_s *state;
467 assert(dlogutil_config_connect(config, &state) == 0);
468 dlogutil_config_destroy(config);
471 assert(dlogutil_buffer_get_alias(state, LOG_ID_MAIN, &id) == 0);
472 assert(id == LOG_ID_MAIN);
473 assert(dlogutil_buffer_get_alias(state, LOG_ID_APPS, &id) == 0);
474 assert(id == (pipe ? LOG_ID_APPS : LOG_ID_INVALID));
475 assert(dlogutil_buffer_get_alias(state, LOG_ID_RADIO, &id) == 0);
476 assert(id == (pipe ? LOG_ID_RADIO : LOG_ID_RADIO));
477 assert(dlogutil_buffer_get_alias(state, LOG_ID_SYSTEM, &id) == 0);
478 assert(id == (pipe ? LOG_ID_SYSTEM : LOG_ID_MAIN));
479 assert(dlogutil_buffer_get_alias(state, LOG_ID_KMSG, &id) == 0);
480 assert(id == LOG_ID_KMSG);
482 dlogutil_state_destroy(state);
485 void negative_main(void)
487 dlogutil_config_s *config = dlogutil_config_create();
489 assert(dlogutil_config_buffer_add(config, LOG_ID_MAIN) == 0);
491 dlogutil_state_s *state;
492 assert(dlogutil_config_connect(config, &state) == 0);
493 dlogutil_config_destroy(config);
495 void *bad_ptr = (void *)0xFA1l;
497 assert(TIZEN_ERROR_INVALID_PARAMETER == dlogutil_config_buffer_add(NULL, LOG_ID_MAIN));
499 dlogutil_config_s *c = dlogutil_config_create();
501 assert(TIZEN_ERROR_INVALID_PARAMETER == dlogutil_config_buffer_add(c, LOG_ID_INVALID));
502 assert(TIZEN_ERROR_INVALID_PARAMETER == dlogutil_config_buffer_add(c, LOG_ID_MAX));
503 assert(TIZEN_ERROR_INVALID_PARAMETER == dlogutil_config_buffer_add(c, (log_id_t) -1));
504 assert(TIZEN_ERROR_INVALID_PARAMETER == dlogutil_config_buffer_add(c, (log_id_t) 98));
507 assert(TIZEN_ERROR_NONE == dlogutil_config_mode_set_continuous(c));
509 assert(TIZEN_ERROR_INVALID_PARAMETER == dlogutil_config_connect(c, &s)); // empty set
511 assert(TIZEN_ERROR_NONE == dlogutil_config_buffer_add(c, LOG_ID_MAIN));
512 assert(TIZEN_ERROR_NONE == dlogutil_config_buffer_add(c, LOG_ID_KMSG));
513 assert(TIZEN_ERROR_NOT_SUPPORTED == dlogutil_config_connect(c, &s)); // incompatible pair
515 // Invalid single buffer
516 const log_id_t invalid_ids[] =
524 for (size_t i = 0; i < NELEMS(invalid_ids); ++i) {
525 const log_id_t id = invalid_ids[i];
526 assert(dlogutil_buffer_clear(state, id) ==
527 TIZEN_ERROR_INVALID_PARAMETER);
528 assert(dlogutil_buffer_get_capacity(state, id, bad_ptr) ==
529 TIZEN_ERROR_INVALID_PARAMETER);
530 assert(dlogutil_buffer_get_usage(state, id, bad_ptr) ==
531 TIZEN_ERROR_INVALID_PARAMETER);
532 assert(dlogutil_buffer_get_name(id, bad_ptr) ==
533 TIZEN_ERROR_INVALID_PARAMETER);
534 assert(dlogutil_buffer_get_default_ts_type(id, bad_ptr) ==
535 TIZEN_ERROR_INVALID_PARAMETER);
536 assert(dlogutil_buffer_check_ts_type_available(id, DLOGUTIL_SORT_SENT_MONO, bad_ptr) ==
537 TIZEN_ERROR_INVALID_PARAMETER);
540 // Retrieval of data from NULL
541 assert(dlogutil_entry_get_tid(NULL, bad_ptr) ==
542 TIZEN_ERROR_INVALID_PARAMETER);
543 assert(dlogutil_entry_get_pid(NULL, bad_ptr) ==
544 TIZEN_ERROR_INVALID_PARAMETER);
545 assert(dlogutil_entry_get_priority(NULL, bad_ptr) ==
546 TIZEN_ERROR_INVALID_PARAMETER);
547 assert(dlogutil_entry_get_timestamp(NULL, DLOGUTIL_SORT_RECV_MONO, bad_ptr) ==
548 TIZEN_ERROR_INVALID_PARAMETER);
549 assert(dlogutil_entry_get_tag(NULL, bad_ptr) ==
550 TIZEN_ERROR_INVALID_PARAMETER);
551 assert(dlogutil_entry_get_message(NULL, bad_ptr) ==
552 TIZEN_ERROR_INVALID_PARAMETER);
553 assert(dlogutil_buffer_get_alias(NULL, LOG_ID_MAIN, bad_ptr) ==
554 TIZEN_ERROR_INVALID_PARAMETER);
556 // Retrieval of data into NULL
557 assert(dlogutil_entry_get_tid(bad_ptr, NULL) ==
558 TIZEN_ERROR_INVALID_PARAMETER);
559 assert(dlogutil_entry_get_pid(bad_ptr, NULL) ==
560 TIZEN_ERROR_INVALID_PARAMETER);
561 assert(dlogutil_entry_get_priority(bad_ptr, NULL) ==
562 TIZEN_ERROR_INVALID_PARAMETER);
563 assert(dlogutil_entry_get_timestamp(bad_ptr, DLOGUTIL_SORT_RECV_MONO, NULL) ==
564 TIZEN_ERROR_INVALID_PARAMETER);
565 assert(dlogutil_entry_get_tag(bad_ptr, NULL) ==
566 TIZEN_ERROR_INVALID_PARAMETER);
567 assert(dlogutil_entry_get_message(bad_ptr, NULL) ==
568 TIZEN_ERROR_INVALID_PARAMETER);
569 assert(dlogutil_buffer_get_name(LOG_ID_MAIN, NULL) ==
570 TIZEN_ERROR_INVALID_PARAMETER);
571 assert(dlogutil_buffer_get_capacity(state, LOG_ID_MAIN, NULL) ==
572 TIZEN_ERROR_INVALID_PARAMETER);
573 assert(dlogutil_buffer_get_usage(state, LOG_ID_MAIN, NULL) ==
574 TIZEN_ERROR_INVALID_PARAMETER);
575 assert(dlogutil_buffer_get_default_ts_type(LOG_ID_MAIN, NULL) ==
576 TIZEN_ERROR_INVALID_PARAMETER);
577 assert(dlogutil_buffer_check_ts_type_available(LOG_ID_MAIN, DLOGUTIL_SORT_RECV_MONO, NULL) ==
578 TIZEN_ERROR_INVALID_PARAMETER);
579 assert(dlogutil_buffer_get_alias(bad_ptr, LOG_ID_MAIN, NULL) ==
580 TIZEN_ERROR_INVALID_PARAMETER);
583 assert(dlogutil_entry_get_timestamp(bad_ptr, 1337, bad_ptr) ==
584 TIZEN_ERROR_INVALID_PARAMETER);
587 assert(dlogutil_config_filter_tid(NULL, 0) ==
588 TIZEN_ERROR_INVALID_PARAMETER);
589 assert(dlogutil_config_filter_pid(NULL, 0) ==
590 TIZEN_ERROR_INVALID_PARAMETER);
591 assert(dlogutil_config_filter_filterspec(NULL, "TIZEN") ==
592 TIZEN_ERROR_INVALID_PARAMETER);
593 assert(dlogutil_config_sorting_disable(NULL) ==
594 TIZEN_ERROR_INVALID_PARAMETER);
595 assert(dlogutil_config_sorting_enable(NULL) ==
596 TIZEN_ERROR_INVALID_PARAMETER);
597 assert(dlogutil_config_sorting_enable_with_size(NULL, 7) ==
598 TIZEN_ERROR_INVALID_PARAMETER);
599 assert(dlogutil_config_order_set(NULL, DLOGUTIL_SORT_RECV_MONO) ==
600 TIZEN_ERROR_INVALID_PARAMETER);
603 assert(dlogutil_buffer_get_alias(bad_ptr, LOG_ID_INVALID, bad_ptr) ==
604 TIZEN_ERROR_INVALID_PARAMETER);
605 assert(dlogutil_buffer_get_alias(bad_ptr, LOG_ID_MAX, bad_ptr) ==
606 TIZEN_ERROR_INVALID_PARAMETER);
607 assert(dlogutil_buffer_get_alias(bad_ptr, (log_id_t) -1, bad_ptr) ==
608 TIZEN_ERROR_INVALID_PARAMETER);
609 assert(dlogutil_buffer_get_alias(bad_ptr, (log_id_t) 99, bad_ptr) ==
610 TIZEN_ERROR_INVALID_PARAMETER);
612 // Destroying a NULL - no error, but doesn't crash either
613 dlogutil_config_destroy(NULL);
616 dlogutil_config_destroy(c);
617 dlogutil_state_destroy(state);
621 int main(int argc, char **argv)
624 print_usage_and_die(argv[0]);
625 enum test_mode t = choose_mode(argv[1]);
626 if (t == MODE_INVALID)
627 print_usage_and_die(argv[0]);
629 pid_t pid = atoi(argv[2]);
632 if (!strcmp(argv[3], "pipe"))
634 else if (strcmp(argv[3], "logger"))
635 print_usage_and_die(argv[0]);
640 case MODE_CONTINUOUS:
643 case MODE_PRIORITY_EXACT:
645 case MODE_PID_CORRECT:
647 case MODE_TID_CORRECT:
649 case MODE_TAG_CORRECT:
651 case MODE_PREFIX_CORRECT:
652 case MODE_PREFIX_WRONG:
653 get_logs_main(t, pipe, pid);
656 sorting_main(pipe ? 4 : 1);