logger-test: more intensive tests
[platform/kernel/linux-rpi.git] / tools / testing / selftests / logger / logger.c
1 #include <errno.h>
2 #include <fcntl.h>
3 #include <getopt.h>
4 #include <linux/logger.h>
5 #include <pthread.h>
6 #include <stdint.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/ioctl.h>
11 #include <sys/types.h>
12 #include <sys/uio.h>
13 #include <sys/wait.h>
14 #include <unistd.h>
15
16 #define handle_error_en(en, msg)                                        \
17         do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
18
19 #define BIT(nr)         ((1UL) << (nr))
20
21 void *tstart(void *arg)
22 {
23         int *fd = arg;
24         write(*fd, "child thread msg #1\nchild thread msg #2", 39);
25         return 0;
26 }
27
28 int main(int ac, char *av[]) {
29
30         char *device = "/dev/log_main";
31         char *msg = "The Foo";
32         char *tag = "stdio";
33         struct logger_set_tag struct_tag = {
34                 .len = 6,
35                 .ptr = (uintptr_t)tag,
36         };
37         int c, fd, s;
38         pid_t child;
39         pthread_t tid;
40         struct iovec vec[3];
41         unsigned char prio = 4;
42         unsigned long test_mask = ~0UL;
43
44         while (1) {
45                 static struct option long_options[] = {
46                         {"priority",  required_argument, 0, 'p'},
47                         {"tag",       required_argument, 0, 't'},
48                         {"test-mask", required_argument, 0, 'm'},
49                         {"device",    required_argument, 0, 'd'},
50                         {0,           0,                 0, 0}
51                 };
52
53                 c = getopt_long(ac, av, "p:t:m:d:", long_options, NULL);
54                 if (c == -1)
55                         break;
56
57                 switch (c) {
58                 case 'p':
59                         prio = (unsigned char) strtol(optarg, NULL, 10);
60                         break;
61                 case 't':
62                         tag = strdup(optarg);
63                         break;
64                 case 'm':
65                         test_mask = (unsigned char) strtol(optarg, NULL, 16);
66                         break;
67                 case 'd':
68                         device = strdup(optarg);
69                         break;
70                 default:
71                         exit(1);
72                 }
73         }
74
75         setlinebuf(stdout);
76         fd = open(device, O_WRONLY);
77
78         if (test_mask & BIT(0)) {
79                 vec[0].iov_base = &prio;
80                 vec[0].iov_len = 1;
81                 vec[1].iov_base = tag;
82                 vec[1].iov_len = strlen(tag) + 1;
83                 vec[2].iov_base = msg;
84                 vec[2].iov_len = strlen(msg) + 1;
85
86                 writev(fd, vec, 3);
87                 if (test_mask & BIT(1)) {
88                         msg = "line #1\nline #2";
89                         vec[2].iov_base = msg;
90                         vec[2].iov_len = strlen(msg) + 1;
91
92                         writev(fd, vec, 3);
93                 }
94         }
95
96         ioctl(fd, LOGGER_SET_PRIO, prio);
97         ioctl(fd, LOGGER_SET_TAG, &struct_tag);
98
99         if (test_mask & BIT(2)) {
100                 int count;
101                 count = write(fd, "The Foo From STDIO\n", 19);
102                 if (count != 19)
103                         printf("count != 19\n");
104
105                 write(fd, "LINE #1\nLINE #2", 15);
106                 write(fd, " CONTINUED\nONCE", 15);
107                 write(fd, " AGAIN\n", 7);
108         }
109
110         if (test_mask & BIT(3)) {
111                 msg = malloc(8000);
112                 if (!msg)
113                         return 1;
114
115                 for (int i = 0; i < 8000; i++)
116                         msg[i] = '!' + (i % 95);
117                 msg[7999] = '\n';
118                 write(fd, msg, 8000);
119
120                 for (int i = 0; (test_mask & BIT(4)) && i < 40; i++)
121                         write(fd, msg, 8000);
122
123                 for (int i = 0; (test_mask & BIT(5)) && i < 8000; i++)
124                         write(fd, &msg[i], 1);
125
126                 free(msg);
127                 msg = NULL;
128         }
129
130         if (test_mask & BIT(6)) {
131                 child = fork();
132                 if (child < 0) {
133                         return -1;
134                 } else if (child == 0) {
135                         sleep(1);
136                         printf("child: %d\n", getpid());
137                         write(fd, "child 1\n", 8);
138                         sleep(1);
139                         write(fd, "child 2\n", 8);
140                         close(fd);
141                         return 0;
142                 }
143                 write(fd, "PARENT\n", 7);
144                 printf("PARENT: %d\n", getpid());
145                 wait(&s);
146         }
147
148         if (test_mask & BIT(7)) {
149                 s = pthread_create(&tid, NULL, &tstart, &fd);
150                 if (s != 0)
151                         handle_error_en(s, "pthread_create");
152                 sleep(1);
153                 write(fd, "PARENT THREAD\n", 14);
154
155                 s = pthread_join(tid, NULL);
156                 if (s != 0)
157                         handle_error_en(s, "pthread_join");
158         }
159
160         return 0;
161 }