tests: refactor logger tests 83/271383/1 accepted/tizen/6.5/unified/20220315.132353 submit/tizen_6.5/20220314.044848
authorŁukasz Stelmach <l.stelmach@samsung.com>
Thu, 27 Jan 2022 20:01:36 +0000 (21:01 +0100)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Fri, 18 Feb 2022 11:20:23 +0000 (11:20 +0000)
Move testing scenarios to separate functions and enable looped operation
for detection of deadlocks, race conditions and other rearly observable
phenomena.

Change-Id: I213e5d10d9f541411c9301d147132ed9fd4af57d
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
(cherry picked from commit c9f2349b61a10ddeb70fc00f554963a6a5d80f96)

tests/logger/logger.c

index 0277ed6456bd04252ac4a0aa4104bf2dc061dcc4..b7c7b72b785d9234ecce56c3f1ddede47468fa11 100644 (file)
@@ -3,6 +3,7 @@
 #include <getopt.h>
 #include <linux/logger.h>
 #include <pthread.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 
 #define BIT(nr)                ((1UL) << (nr))
 
+// Note, largest singular message payload is 4076
+#define BIG_MSG_SIZE 8000
+
+#define ALL_TEST_BITS \
+       (BIT(0) | BIT(2) | BIT(3) | BIT(6) | BIT(7))
+
+struct targ {
+       int fd;
+       int iter;
+};
+
 void *tstart(void *arg)
 {
-       int *fd = arg;
-       write(*fd, "child thread msg #1\nchild thread msg #2", 39);
+       struct targ *targ = arg;
+       int fd = targ->fd;
+       int iter = targ->iter;
+       bool inf = (iter < 0);
+       int i;
+
+       fprintf(stderr,"iter: %d\n", iter);
+       for (i = 0; inf || i < iter; i++)
+               write(fd, "child thread msg #1\nchild thread msg #2", 39);
        return 0;
 }
 
-int dump_logger(const char *device)
+int clear_logger(const char *device)
+{
+       int fd;
+       int ret = 0;
+
+       fd = open(device, O_RDONLY | O_NONBLOCK);
+       if (fd < 0) {
+               perror("open");
+               exit(EXIT_FAILURE);
+       }
+
+       ret = ioctl(fd, LOGGER_FLUSH_LOG, 0);
+       if (ret < 0) {
+               perror("ioctl(FLUSH_LOG)");
+               exit(EXIT_FAILURE);
+       }
+
+       close(fd);
+
+       return ret;
+}
+
+int dump_logger(const char *device, bool clear)
 {
        int fd;
        int ret = 0;
@@ -64,12 +105,147 @@ int dump_logger(const char *device)
                }
 
                tag_len = strlen(e->msg + 1) + 2; /* 2: priority, NUL */
-               fprintf(stdout, "[%5d.%6d] %s<%u>: %s\n", e->sec, e->nsec / 1000, &e->msg[1], e->msg[0], &e->msg[tag_len]);
+               fprintf(stdout, "[%5d.%06d] %s<%u>[%u|%u]: %s\n", e->sec, e->nsec / 1000, &e->msg[1], e->msg[0], e->pid, e->tid, &e->msg[tag_len]);
        };
 
+       close(fd);
+
+       if (clear)
+               clear_logger(device);
+
        return ret;
 }
 
+
+void thread_logger(int iter, int fd)
+{
+       int s;
+       pthread_t tid;
+       struct targ targ;
+       bool inf = (iter < 0);
+       int i;
+
+       targ.fd = fd;
+       targ.iter = iter;
+
+       s = pthread_create(&tid, NULL, &tstart, &targ);
+       if (s != 0)
+               handle_error_en(s, "pthread_create");
+
+       for (i = 0; inf || i < iter; i++)
+               write(fd, "PARENT THREAD\n", 14);
+
+       s = pthread_join(tid, NULL);
+       if (s != 0)
+               handle_error_en(s, "pthread_join");
+}
+
+void fork_logger(int iter, int fd)
+{
+       bool inf = (iter < 0);
+       pid_t child;
+       int s;
+       int i;
+
+       child = fork();
+       if (child < 0) {
+               exit(EXIT_FAILURE);
+       } else if (child == 0) {
+               for (i = 0; inf || i < iter; i++) {
+                       write(fd, "child 1\n", 8);
+                       write(fd, "child 2\n", 8);
+               }
+               close(fd);
+               exit(EXIT_SUCCESS);
+       }
+       for (i = 0; inf || i < iter; i++)
+               write(fd, "PARENT\n", 7);
+       wait(&s);
+
+}
+
+void large_message_logger(int iter, int fd, unsigned long test_mask)
+{
+       bool inf = (iter < 0);
+       char *msg;
+       int i, j;
+
+       msg = malloc(BIG_MSG_SIZE);
+       if (!msg)
+               return;
+
+       for (i = 0; i < BIG_MSG_SIZE; i++)
+               msg[i] = '!' + (i % 95);
+       msg[BIG_MSG_SIZE - 4] = 'E';
+       msg[BIG_MSG_SIZE - 3] = 'O';
+       msg[BIG_MSG_SIZE - 2] = 'F';
+       msg[BIG_MSG_SIZE - 1] = '\n';
+
+       write(fd, msg, BIG_MSG_SIZE);
+
+       for (j = 0; (test_mask & BIT(4)) && (inf || j < iter); j++ )
+               for (i = 0; i < 40; i++)
+                       write(fd, msg, BIG_MSG_SIZE);
+
+       for (j = 0; (test_mask & BIT(5)) && (inf || j < iter); j++ )
+               for (i = 0; i < BIG_MSG_SIZE; i++)
+                       write(fd, &msg[i], 1);
+
+       free(msg);
+       msg = NULL;
+}
+
+void stdio_logger(int iter, int fd)
+{
+       bool inf = (iter < 0);
+       int count;
+       int i;
+
+       count = write(fd, "The Foo From STDIO\n", 19);
+       if (count != 19)
+               fprintf(stderr, "%d != 19\n", count);
+
+       for (i = 0; inf || i < iter; i++) {
+               write(fd, "LINE #1\nLINE #2", 15);
+               write(fd, " CONTINUED\nONCE", 15);
+               write(fd, " AGAIN\n", 7);
+       }
+}
+
+void iov_logger(int iter, int fd, unsigned long test_mask, unsigned char prio, char *tag, char *msg)
+{
+       bool inf = (iter < 0);
+       int i;
+       struct iovec vec[3];
+
+       for (i = 0; inf || i < iter; i++) {
+               vec[0].iov_base = &prio;
+               vec[0].iov_len = 1;
+               vec[1].iov_base = tag;
+               vec[1].iov_len = strlen(tag) + 1;
+               vec[2].iov_base = msg;
+               vec[2].iov_len = strlen(msg) + 1;
+
+               writev(fd, vec, 3);
+               if (test_mask & BIT(1)) {
+                       msg = "line #1\nline #2";
+                       vec[2].iov_base = msg;
+                       vec[2].iov_len = strlen(msg) + 1;
+
+                       writev(fd, vec, 3);
+               }
+       }
+}
+
+int count_bits(unsigned long i) {
+       int n = 0;
+       while(i) {
+               n += i & 1;
+               i >>= 1;
+       }
+       return n;
+}
+
 int main(int ac, char *av[]) {
 
        char *device = "/dev/log_main";
@@ -79,13 +255,13 @@ int main(int ac, char *av[]) {
                .len = 6,
                .ptr = (uintptr_t)tag,
        };
-       int c, fd, s, ret;
-       pid_t child;
-       int dump = 0;
-       pthread_t tid;
-       struct iovec vec[3];
+       int c, fd, ret;
+       bool dump = false;
+       bool clear = false;
+
        unsigned char prio = 4;
        unsigned long test_mask = ~0UL;
+       int iterations = 1;
 
        while (1) {
                static struct option long_options[] = {
@@ -93,10 +269,13 @@ int main(int ac, char *av[]) {
                        {"tag",       required_argument, 0, 't'},
                        {"test-mask", required_argument, 0, 'm'},
                        {"device",    required_argument, 0, 'd'},
+                       {"dump",      no_argument,       0, 'D'},
+                       {"loop",      optional_argument, 0, 'l'},
+                       {"clear",     no_argument,       0, 'C'},
                        {0,           0,                 0, 0}
                };
 
-               c = getopt_long(ac, av, "p:t:m:d:D", long_options, NULL);
+               c = getopt_long(ac, av, "p:t:m:d:Dl::C", long_options, NULL);
                if (c == -1)
                        break;
 
@@ -114,15 +293,43 @@ int main(int ac, char *av[]) {
                        device = strdup(optarg);
                        break;
                case 'D':
-                       dump = 1;
+                       dump = true;
+                       break;
+               case 'l':
+                       if (optarg != NULL)
+                               iterations = (int) strtol(optarg, NULL, 10);
+                       else
+                               iterations = -1; // a.k.a. infinity
+                       break;
+               case 'C':
+                       clear = true;
                        break;
                default:
+                       fprintf(stderr, "c: %c\n", c);
                        exit(1);
                }
        }
 
+       fprintf(stderr, "dump: %u\n", dump);
+       fprintf(stderr, "clear: %u\n", clear);
+
        if (dump)
-               return dump_logger(device);
+               return dump_logger(device, clear);
+
+       if (clear)
+               return clear_logger(device);
+
+       fprintf(stderr, "prio: %u\n", prio);
+       fprintf(stderr, "tag:  %s\n", tag);
+       fprintf(stderr, "mask: %u\n", test_mask);
+       fprintf(stderr, "cnt:  %u\n", count_bits(test_mask));
+       fprintf(stderr, "dev:  %s\n", device);
+       fprintf(stderr, "loop: %d\n", iterations);
+
+       if ((iterations < 0) && count_bits(test_mask & ALL_TEST_BITS) != 1) {
+               fprintf(stderr, "Choose one test scenario only for infinite loop testing.\n");
+               exit(EXIT_FAILURE);
+       }
 
        setlinebuf(stdout);
        fd = open(device, O_WRONLY);
@@ -132,21 +339,7 @@ int main(int ac, char *av[]) {
        }
 
        if (test_mask & BIT(0)) {
-               vec[0].iov_base = &prio;
-               vec[0].iov_len = 1;
-               vec[1].iov_base = tag;
-               vec[1].iov_len = strlen(tag) + 1;
-               vec[2].iov_base = msg;
-               vec[2].iov_len = strlen(msg) + 1;
-
-               writev(fd, vec, 3);
-               if (test_mask & BIT(1)) {
-                       msg = "line #1\nline #2";
-                       vec[2].iov_base = msg;
-                       vec[2].iov_len = strlen(msg) + 1;
-
-                       writev(fd, vec, 3);
-               }
+               iov_logger(iterations, fd, test_mask, prio, tag, msg);
        }
 
        ret = ioctl(fd, LOGGER_SET_PRIO, prio);
@@ -160,69 +353,17 @@ int main(int ac, char *av[]) {
                exit(EXIT_FAILURE);
        }
 
-       if (test_mask & BIT(2)) {
-               int count;
-               count = write(fd, "The Foo From STDIO\n", 19);
-               if (count != 19)
-                       fprintf(stderr, "%d != 19\n", count);
-
-               write(fd, "LINE #1\nLINE #2", 15);
-               write(fd, " CONTINUED\nONCE", 15);
-               write(fd, " AGAIN\n", 7);
-       }
-
-       if (test_mask & BIT(3)) {
-               msg = malloc(8000);
-               if (!msg)
-                       return 1;
+       if (test_mask & BIT(2))
+               stdio_logger(iterations, fd);
 
-               for (int i = 0; i < 8000; i++)
-                       msg[i] = '!' + (i % 95);
-               msg[7996] = 'E';
-               msg[7997] = 'O';
-               msg[7998] = 'F';
-               msg[7999] = '\n';
-               write(fd, msg, 8000);
+       if (test_mask & BIT(3))
+               large_message_logger(iterations, fd, test_mask);
 
-               for (int i = 0; (test_mask & BIT(4)) && i < 40; i++)
-                       write(fd, msg, 8000);
+       if (test_mask & BIT(6))
+               fork_logger(iterations, fd);
 
-               for (int i = 0; (test_mask & BIT(5)) && i < 8000; i++)
-                       write(fd, &msg[i], 1);
-
-               free(msg);
-               msg = NULL;
-       }
-
-       if (test_mask & BIT(6)) {
-               child = fork();
-               if (child < 0) {
-                       return -1;
-               } else if (child == 0) {
-                       sleep(1);
-                       printf("child: %d\n", getpid());
-                       write(fd, "child 1\n", 8);
-                       sleep(1);
-                       write(fd, "child 2\n", 8);
-                       close(fd);
-                       return 0;
-               }
-               write(fd, "PARENT\n", 7);
-               printf("PARENT: %d\n", getpid());
-               wait(&s);
-       }
-
-       if (test_mask & BIT(7)) {
-               s = pthread_create(&tid, NULL, &tstart, &fd);
-               if (s != 0)
-                       handle_error_en(s, "pthread_create");
-               sleep(1);
-               write(fd, "PARENT THREAD\n", 14);
-
-               s = pthread_join(tid, NULL);
-               if (s != 0)
-                       handle_error_en(s, "pthread_join");
-       }
+       if (test_mask & BIT(7))
+               thread_logger(iterations, fd);
 
        return 0;
 }