selftests/bpf: test_progs: remove global fail/success counts
[muen/linux.git] / tools / testing / selftests / bpf / test_progs.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2017 Facebook
3  */
4 #include "test_progs.h"
5 #include "bpf_rlimit.h"
6 #include <argp.h>
7 #include <string.h>
8
9 /* defined in test_progs.h */
10 struct test_env env;
11
12 struct prog_test_def {
13         const char *test_name;
14         int test_num;
15         void (*run_test)(void);
16         bool force_log;
17         int error_cnt;
18         int skip_cnt;
19         bool tested;
20
21         const char *subtest_name;
22         int subtest_num;
23
24         /* store counts before subtest started */
25         int old_error_cnt;
26 };
27
28 static bool should_run(struct test_selector *sel, int num, const char *name)
29 {
30         if (sel->name && sel->name[0] && !strstr(name, sel->name))
31                 return false;
32
33         if (!sel->num_set)
34                 return true;
35
36         return num < sel->num_set_len && sel->num_set[num];
37 }
38
39 static void dump_test_log(const struct prog_test_def *test, bool failed)
40 {
41         if (stdout == env.stdout)
42                 return;
43
44         fflush(stdout); /* exports env.log_buf & env.log_cnt */
45
46         if (env.verbose || test->force_log || failed) {
47                 if (env.log_cnt) {
48                         fprintf(env.stdout, "%s", env.log_buf);
49                         if (env.log_buf[env.log_cnt - 1] != '\n')
50                                 fprintf(env.stdout, "\n");
51                 }
52         }
53
54         fseeko(stdout, 0, SEEK_SET); /* rewind */
55 }
56
57 static void skip_account(void)
58 {
59         if (env.test->skip_cnt) {
60                 env.skip_cnt++;
61                 env.test->skip_cnt = 0;
62         }
63 }
64
65 void test__end_subtest()
66 {
67         struct prog_test_def *test = env.test;
68         int sub_error_cnt = test->error_cnt - test->old_error_cnt;
69
70         if (sub_error_cnt)
71                 env.fail_cnt++;
72         else
73                 env.sub_succ_cnt++;
74         skip_account();
75
76         dump_test_log(test, sub_error_cnt);
77
78         fprintf(env.stdout, "#%d/%d %s:%s\n",
79                test->test_num, test->subtest_num,
80                test->subtest_name, sub_error_cnt ? "FAIL" : "OK");
81 }
82
83 bool test__start_subtest(const char *name)
84 {
85         struct prog_test_def *test = env.test;
86
87         if (test->subtest_name) {
88                 test__end_subtest();
89                 test->subtest_name = NULL;
90         }
91
92         test->subtest_num++;
93
94         if (!name || !name[0]) {
95                 fprintf(env.stderr,
96                         "Subtest #%d didn't provide sub-test name!\n",
97                         test->subtest_num);
98                 return false;
99         }
100
101         if (!should_run(&env.subtest_selector, test->subtest_num, name))
102                 return false;
103
104         test->subtest_name = name;
105         env.test->old_error_cnt = env.test->error_cnt;
106
107         return true;
108 }
109
110 void test__force_log() {
111         env.test->force_log = true;
112 }
113
114 void test__skip(void)
115 {
116         env.test->skip_cnt++;
117 }
118
119 void test__fail(void)
120 {
121         env.test->error_cnt++;
122 }
123
124 struct ipv4_packet pkt_v4 = {
125         .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
126         .iph.ihl = 5,
127         .iph.protocol = IPPROTO_TCP,
128         .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES),
129         .tcp.urg_ptr = 123,
130         .tcp.doff = 5,
131 };
132
133 struct ipv6_packet pkt_v6 = {
134         .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
135         .iph.nexthdr = IPPROTO_TCP,
136         .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
137         .tcp.urg_ptr = 123,
138         .tcp.doff = 5,
139 };
140
141 int bpf_find_map(const char *test, struct bpf_object *obj, const char *name)
142 {
143         struct bpf_map *map;
144
145         map = bpf_object__find_map_by_name(obj, name);
146         if (!map) {
147                 printf("%s:FAIL:map '%s' not found\n", test, name);
148                 test__fail();
149                 return -1;
150         }
151         return bpf_map__fd(map);
152 }
153
154 static bool is_jit_enabled(void)
155 {
156         const char *jit_sysctl = "/proc/sys/net/core/bpf_jit_enable";
157         bool enabled = false;
158         int sysctl_fd;
159
160         sysctl_fd = open(jit_sysctl, 0, O_RDONLY);
161         if (sysctl_fd != -1) {
162                 char tmpc;
163
164                 if (read(sysctl_fd, &tmpc, sizeof(tmpc)) == 1)
165                         enabled = (tmpc != '0');
166                 close(sysctl_fd);
167         }
168
169         return enabled;
170 }
171
172 int compare_map_keys(int map1_fd, int map2_fd)
173 {
174         __u32 key, next_key;
175         char val_buf[PERF_MAX_STACK_DEPTH *
176                      sizeof(struct bpf_stack_build_id)];
177         int err;
178
179         err = bpf_map_get_next_key(map1_fd, NULL, &key);
180         if (err)
181                 return err;
182         err = bpf_map_lookup_elem(map2_fd, &key, val_buf);
183         if (err)
184                 return err;
185
186         while (bpf_map_get_next_key(map1_fd, &key, &next_key) == 0) {
187                 err = bpf_map_lookup_elem(map2_fd, &next_key, val_buf);
188                 if (err)
189                         return err;
190
191                 key = next_key;
192         }
193         if (errno != ENOENT)
194                 return -1;
195
196         return 0;
197 }
198
199 int compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len)
200 {
201         __u32 key, next_key, *cur_key_p, *next_key_p;
202         char *val_buf1, *val_buf2;
203         int i, err = 0;
204
205         val_buf1 = malloc(stack_trace_len);
206         val_buf2 = malloc(stack_trace_len);
207         cur_key_p = NULL;
208         next_key_p = &key;
209         while (bpf_map_get_next_key(smap_fd, cur_key_p, next_key_p) == 0) {
210                 err = bpf_map_lookup_elem(smap_fd, next_key_p, val_buf1);
211                 if (err)
212                         goto out;
213                 err = bpf_map_lookup_elem(amap_fd, next_key_p, val_buf2);
214                 if (err)
215                         goto out;
216                 for (i = 0; i < stack_trace_len; i++) {
217                         if (val_buf1[i] != val_buf2[i]) {
218                                 err = -1;
219                                 goto out;
220                         }
221                 }
222                 key = *next_key_p;
223                 cur_key_p = &key;
224                 next_key_p = &next_key;
225         }
226         if (errno != ENOENT)
227                 err = -1;
228
229 out:
230         free(val_buf1);
231         free(val_buf2);
232         return err;
233 }
234
235 int extract_build_id(char *build_id, size_t size)
236 {
237         FILE *fp;
238         char *line = NULL;
239         size_t len = 0;
240
241         fp = popen("readelf -n ./urandom_read | grep 'Build ID'", "r");
242         if (fp == NULL)
243                 return -1;
244
245         if (getline(&line, &len, fp) == -1)
246                 goto err;
247         fclose(fp);
248
249         if (len > size)
250                 len = size;
251         memcpy(build_id, line, len);
252         build_id[len] = '\0';
253         return 0;
254 err:
255         fclose(fp);
256         return -1;
257 }
258
259 void *spin_lock_thread(void *arg)
260 {
261         __u32 duration, retval;
262         int err, prog_fd = *(u32 *) arg;
263
264         err = bpf_prog_test_run(prog_fd, 10000, &pkt_v4, sizeof(pkt_v4),
265                                 NULL, NULL, &retval, &duration);
266         CHECK(err || retval, "",
267               "err %d errno %d retval %d duration %d\n",
268               err, errno, retval, duration);
269         pthread_exit(arg);
270 }
271
272 /* extern declarations for test funcs */
273 #define DEFINE_TEST(name) extern void test_##name();
274 #include <prog_tests/tests.h>
275 #undef DEFINE_TEST
276
277 static struct prog_test_def prog_test_defs[] = {
278 #define DEFINE_TEST(name) {             \
279         .test_name = #name,             \
280         .run_test = &test_##name,       \
281 },
282 #include <prog_tests/tests.h>
283 #undef DEFINE_TEST
284 };
285 const int prog_test_cnt = ARRAY_SIZE(prog_test_defs);
286
287 const char *argp_program_version = "test_progs 0.1";
288 const char *argp_program_bug_address = "<bpf@vger.kernel.org>";
289 const char argp_program_doc[] = "BPF selftests test runner";
290
291 enum ARG_KEYS {
292         ARG_TEST_NUM = 'n',
293         ARG_TEST_NAME = 't',
294         ARG_VERIFIER_STATS = 's',
295         ARG_VERBOSE = 'v',
296 };
297
298 static const struct argp_option opts[] = {
299         { "num", ARG_TEST_NUM, "NUM", 0,
300           "Run test number NUM only " },
301         { "name", ARG_TEST_NAME, "NAME", 0,
302           "Run tests with names containing NAME" },
303         { "verifier-stats", ARG_VERIFIER_STATS, NULL, 0,
304           "Output verifier statistics", },
305         { "verbose", ARG_VERBOSE, "LEVEL", OPTION_ARG_OPTIONAL,
306           "Verbose output (use -vv for extra verbose output)" },
307         {},
308 };
309
310 static int libbpf_print_fn(enum libbpf_print_level level,
311                            const char *format, va_list args)
312 {
313         if (!env.very_verbose && level == LIBBPF_DEBUG)
314                 return 0;
315         vprintf(format, args);
316         return 0;
317 }
318
319 int parse_num_list(const char *s, struct test_selector *sel)
320 {
321         int i, set_len = 0, num, start = 0, end = -1;
322         bool *set = NULL, *tmp, parsing_end = false;
323         char *next;
324
325         while (s[0]) {
326                 errno = 0;
327                 num = strtol(s, &next, 10);
328                 if (errno)
329                         return -errno;
330
331                 if (parsing_end)
332                         end = num;
333                 else
334                         start = num;
335
336                 if (!parsing_end && *next == '-') {
337                         s = next + 1;
338                         parsing_end = true;
339                         continue;
340                 } else if (*next == ',') {
341                         parsing_end = false;
342                         s = next + 1;
343                         end = num;
344                 } else if (*next == '\0') {
345                         parsing_end = false;
346                         s = next;
347                         end = num;
348                 } else {
349                         return -EINVAL;
350                 }
351
352                 if (start > end)
353                         return -EINVAL;
354
355                 if (end + 1 > set_len) {
356                         set_len = end + 1;
357                         tmp = realloc(set, set_len);
358                         if (!tmp) {
359                                 free(set);
360                                 return -ENOMEM;
361                         }
362                         set = tmp;
363                 }
364                 for (i = start; i <= end; i++) {
365                         set[i] = true;
366                 }
367
368         }
369
370         if (!set)
371                 return -EINVAL;
372
373         sel->num_set = set;
374         sel->num_set_len = set_len;
375
376         return 0;
377 }
378
379 static error_t parse_arg(int key, char *arg, struct argp_state *state)
380 {
381         struct test_env *env = state->input;
382
383         switch (key) {
384         case ARG_TEST_NUM: {
385                 char *subtest_str = strchr(arg, '/');
386
387                 if (subtest_str) {
388                         *subtest_str = '\0';
389                         if (parse_num_list(subtest_str + 1,
390                                            &env->subtest_selector)) {
391                                 fprintf(stderr,
392                                         "Failed to parse subtest numbers.\n");
393                                 return -EINVAL;
394                         }
395                 }
396                 if (parse_num_list(arg, &env->test_selector)) {
397                         fprintf(stderr, "Failed to parse test numbers.\n");
398                         return -EINVAL;
399                 }
400                 break;
401         }
402         case ARG_TEST_NAME: {
403                 char *subtest_str = strchr(arg, '/');
404
405                 if (subtest_str) {
406                         *subtest_str = '\0';
407                         env->subtest_selector.name = strdup(subtest_str + 1);
408                         if (!env->subtest_selector.name)
409                                 return -ENOMEM;
410                 }
411                 env->test_selector.name = strdup(arg);
412                 if (!env->test_selector.name)
413                         return -ENOMEM;
414                 break;
415         }
416         case ARG_VERIFIER_STATS:
417                 env->verifier_stats = true;
418                 break;
419         case ARG_VERBOSE:
420                 if (arg) {
421                         if (strcmp(arg, "v") == 0) {
422                                 env->very_verbose = true;
423                         } else {
424                                 fprintf(stderr,
425                                         "Unrecognized verbosity setting ('%s'), only -v and -vv are supported\n",
426                                         arg);
427                                 return -EINVAL;
428                         }
429                 }
430                 env->verbose = true;
431                 break;
432         case ARGP_KEY_ARG:
433                 argp_usage(state);
434                 break;
435         case ARGP_KEY_END:
436                 break;
437         default:
438                 return ARGP_ERR_UNKNOWN;
439         }
440         return 0;
441 }
442
443 static void stdio_hijack(void)
444 {
445 #ifdef __GLIBC__
446         env.stdout = stdout;
447         env.stderr = stderr;
448
449         if (env.verbose) {
450                 /* nothing to do, output to stdout by default */
451                 return;
452         }
453
454         /* stdout and stderr -> buffer */
455         fflush(stdout);
456
457         stdout = open_memstream(&env.log_buf, &env.log_cnt);
458         if (!stdout) {
459                 stdout = env.stdout;
460                 perror("open_memstream");
461                 return;
462         }
463
464         stderr = stdout;
465 #endif
466 }
467
468 static void stdio_restore(void)
469 {
470 #ifdef __GLIBC__
471         if (stdout == env.stdout)
472                 return;
473
474         fclose(stdout);
475         free(env.log_buf);
476
477         env.log_buf = NULL;
478         env.log_cnt = 0;
479
480         stdout = env.stdout;
481         stderr = env.stderr;
482 #endif
483 }
484
485 int main(int argc, char **argv)
486 {
487         static const struct argp argp = {
488                 .options = opts,
489                 .parser = parse_arg,
490                 .doc = argp_program_doc,
491         };
492         int err, i;
493
494         err = argp_parse(&argp, argc, argv, 0, NULL, &env);
495         if (err)
496                 return err;
497
498         libbpf_set_print(libbpf_print_fn);
499
500         srand(time(NULL));
501
502         env.jit_enabled = is_jit_enabled();
503
504         stdio_hijack();
505         for (i = 0; i < prog_test_cnt; i++) {
506                 struct prog_test_def *test = &prog_test_defs[i];
507
508                 env.test = test;
509                 test->test_num = i + 1;
510
511                 if (!should_run(&env.test_selector,
512                                 test->test_num, test->test_name))
513                         continue;
514
515                 test->run_test();
516                 /* ensure last sub-test is finalized properly */
517                 if (test->subtest_name)
518                         test__end_subtest();
519
520                 test->tested = true;
521                 if (test->error_cnt)
522                         env.fail_cnt++;
523                 else
524                         env.succ_cnt++;
525                 skip_account();
526
527                 dump_test_log(test, test->error_cnt);
528
529                 fprintf(env.stdout, "#%d %s:%s\n",
530                         test->test_num, test->test_name,
531                         test->error_cnt ? "FAIL" : "OK");
532         }
533         stdio_restore();
534         printf("Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n",
535                env.succ_cnt, env.sub_succ_cnt, env.skip_cnt, env.fail_cnt);
536
537         free(env.test_selector.num_set);
538         free(env.subtest_selector.num_set);
539
540         return env.fail_cnt ? EXIT_FAILURE : EXIT_SUCCESS;
541 }