diff options
Diffstat (limited to 'tools/testing/selftests/bpf/test_progs.c')
-rw-r--r-- | tools/testing/selftests/bpf/test_progs.c | 131 |
1 files changed, 61 insertions, 70 deletions
diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index db00196c8315..12895d03d58b 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c | |||
@@ -40,14 +40,20 @@ static bool should_run(struct test_selector *sel, int num, const char *name) | |||
40 | 40 | ||
41 | static void dump_test_log(const struct prog_test_def *test, bool failed) | 41 | static void dump_test_log(const struct prog_test_def *test, bool failed) |
42 | { | 42 | { |
43 | if (stdout == env.stdout) | ||
44 | return; | ||
45 | |||
46 | fflush(stdout); /* exports env.log_buf & env.log_cnt */ | ||
47 | |||
43 | if (env.verbose || test->force_log || failed) { | 48 | if (env.verbose || test->force_log || failed) { |
44 | if (env.log_cnt) { | 49 | if (env.log_cnt) { |
45 | fprintf(stdout, "%s", env.log_buf); | 50 | fprintf(env.stdout, "%s", env.log_buf); |
46 | if (env.log_buf[env.log_cnt - 1] != '\n') | 51 | if (env.log_buf[env.log_cnt - 1] != '\n') |
47 | fprintf(stdout, "\n"); | 52 | fprintf(env.stdout, "\n"); |
48 | } | 53 | } |
49 | } | 54 | } |
50 | env.log_cnt = 0; | 55 | |
56 | fseeko(stdout, 0, SEEK_SET); /* rewind */ | ||
51 | } | 57 | } |
52 | 58 | ||
53 | void test__end_subtest() | 59 | void test__end_subtest() |
@@ -62,7 +68,7 @@ void test__end_subtest() | |||
62 | 68 | ||
63 | dump_test_log(test, sub_error_cnt); | 69 | dump_test_log(test, sub_error_cnt); |
64 | 70 | ||
65 | printf("#%d/%d %s:%s\n", | 71 | fprintf(env.stdout, "#%d/%d %s:%s\n", |
66 | test->test_num, test->subtest_num, | 72 | test->test_num, test->subtest_num, |
67 | test->subtest_name, sub_error_cnt ? "FAIL" : "OK"); | 73 | test->subtest_name, sub_error_cnt ? "FAIL" : "OK"); |
68 | } | 74 | } |
@@ -79,7 +85,8 @@ bool test__start_subtest(const char *name) | |||
79 | test->subtest_num++; | 85 | test->subtest_num++; |
80 | 86 | ||
81 | if (!name || !name[0]) { | 87 | if (!name || !name[0]) { |
82 | fprintf(stderr, "Subtest #%d didn't provide sub-test name!\n", | 88 | fprintf(env.stderr, |
89 | "Subtest #%d didn't provide sub-test name!\n", | ||
83 | test->subtest_num); | 90 | test->subtest_num); |
84 | return false; | 91 | return false; |
85 | } | 92 | } |
@@ -98,66 +105,6 @@ void test__force_log() { | |||
98 | env.test->force_log = true; | 105 | env.test->force_log = true; |
99 | } | 106 | } |
100 | 107 | ||
101 | void test__vprintf(const char *fmt, va_list args) | ||
102 | { | ||
103 | size_t rem_sz; | ||
104 | int ret = 0; | ||
105 | |||
106 | if (env.verbose || (env.test && env.test->force_log)) { | ||
107 | vfprintf(stderr, fmt, args); | ||
108 | return; | ||
109 | } | ||
110 | |||
111 | try_again: | ||
112 | rem_sz = env.log_cap - env.log_cnt; | ||
113 | if (rem_sz) { | ||
114 | va_list ap; | ||
115 | |||
116 | va_copy(ap, args); | ||
117 | /* we reserved extra byte for \0 at the end */ | ||
118 | ret = vsnprintf(env.log_buf + env.log_cnt, rem_sz + 1, fmt, ap); | ||
119 | va_end(ap); | ||
120 | |||
121 | if (ret < 0) { | ||
122 | env.log_buf[env.log_cnt] = '\0'; | ||
123 | fprintf(stderr, "failed to log w/ fmt '%s'\n", fmt); | ||
124 | return; | ||
125 | } | ||
126 | } | ||
127 | |||
128 | if (!rem_sz || ret > rem_sz) { | ||
129 | size_t new_sz = env.log_cap * 3 / 2; | ||
130 | char *new_buf; | ||
131 | |||
132 | if (new_sz < 4096) | ||
133 | new_sz = 4096; | ||
134 | if (new_sz < ret + env.log_cnt) | ||
135 | new_sz = ret + env.log_cnt; | ||
136 | |||
137 | /* +1 for guaranteed space for terminating \0 */ | ||
138 | new_buf = realloc(env.log_buf, new_sz + 1); | ||
139 | if (!new_buf) { | ||
140 | fprintf(stderr, "failed to realloc log buffer: %d\n", | ||
141 | errno); | ||
142 | return; | ||
143 | } | ||
144 | env.log_buf = new_buf; | ||
145 | env.log_cap = new_sz; | ||
146 | goto try_again; | ||
147 | } | ||
148 | |||
149 | env.log_cnt += ret; | ||
150 | } | ||
151 | |||
152 | void test__printf(const char *fmt, ...) | ||
153 | { | ||
154 | va_list args; | ||
155 | |||
156 | va_start(args, fmt); | ||
157 | test__vprintf(fmt, args); | ||
158 | va_end(args); | ||
159 | } | ||
160 | |||
161 | struct ipv4_packet pkt_v4 = { | 108 | struct ipv4_packet pkt_v4 = { |
162 | .eth.h_proto = __bpf_constant_htons(ETH_P_IP), | 109 | .eth.h_proto = __bpf_constant_htons(ETH_P_IP), |
163 | .iph.ihl = 5, | 110 | .iph.ihl = 5, |
@@ -331,7 +278,7 @@ enum ARG_KEYS { | |||
331 | ARG_VERIFIER_STATS = 's', | 278 | ARG_VERIFIER_STATS = 's', |
332 | ARG_VERBOSE = 'v', | 279 | ARG_VERBOSE = 'v', |
333 | }; | 280 | }; |
334 | 281 | ||
335 | static const struct argp_option opts[] = { | 282 | static const struct argp_option opts[] = { |
336 | { "num", ARG_TEST_NUM, "NUM", 0, | 283 | { "num", ARG_TEST_NUM, "NUM", 0, |
337 | "Run test number NUM only " }, | 284 | "Run test number NUM only " }, |
@@ -349,7 +296,7 @@ static int libbpf_print_fn(enum libbpf_print_level level, | |||
349 | { | 296 | { |
350 | if (!env.very_verbose && level == LIBBPF_DEBUG) | 297 | if (!env.very_verbose && level == LIBBPF_DEBUG) |
351 | return 0; | 298 | return 0; |
352 | test__vprintf(format, args); | 299 | vprintf(format, args); |
353 | return 0; | 300 | return 0; |
354 | } | 301 | } |
355 | 302 | ||
@@ -477,6 +424,48 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) | |||
477 | return 0; | 424 | return 0; |
478 | } | 425 | } |
479 | 426 | ||
427 | static void stdio_hijack(void) | ||
428 | { | ||
429 | #ifdef __GLIBC__ | ||
430 | env.stdout = stdout; | ||
431 | env.stderr = stderr; | ||
432 | |||
433 | if (env.verbose) { | ||
434 | /* nothing to do, output to stdout by default */ | ||
435 | return; | ||
436 | } | ||
437 | |||
438 | /* stdout and stderr -> buffer */ | ||
439 | fflush(stdout); | ||
440 | |||
441 | stdout = open_memstream(&env.log_buf, &env.log_cnt); | ||
442 | if (!stdout) { | ||
443 | stdout = env.stdout; | ||
444 | perror("open_memstream"); | ||
445 | return; | ||
446 | } | ||
447 | |||
448 | stderr = stdout; | ||
449 | #endif | ||
450 | } | ||
451 | |||
452 | static void stdio_restore(void) | ||
453 | { | ||
454 | #ifdef __GLIBC__ | ||
455 | if (stdout == env.stdout) | ||
456 | return; | ||
457 | |||
458 | fclose(stdout); | ||
459 | free(env.log_buf); | ||
460 | |||
461 | env.log_buf = NULL; | ||
462 | env.log_cnt = 0; | ||
463 | |||
464 | stdout = env.stdout; | ||
465 | stderr = env.stderr; | ||
466 | #endif | ||
467 | } | ||
468 | |||
480 | int main(int argc, char **argv) | 469 | int main(int argc, char **argv) |
481 | { | 470 | { |
482 | static const struct argp argp = { | 471 | static const struct argp argp = { |
@@ -496,6 +485,7 @@ int main(int argc, char **argv) | |||
496 | 485 | ||
497 | env.jit_enabled = is_jit_enabled(); | 486 | env.jit_enabled = is_jit_enabled(); |
498 | 487 | ||
488 | stdio_hijack(); | ||
499 | for (i = 0; i < prog_test_cnt; i++) { | 489 | for (i = 0; i < prog_test_cnt; i++) { |
500 | struct prog_test_def *test = &prog_test_defs[i]; | 490 | struct prog_test_def *test = &prog_test_defs[i]; |
501 | int old_pass_cnt = pass_cnt; | 491 | int old_pass_cnt = pass_cnt; |
@@ -523,13 +513,14 @@ int main(int argc, char **argv) | |||
523 | 513 | ||
524 | dump_test_log(test, test->error_cnt); | 514 | dump_test_log(test, test->error_cnt); |
525 | 515 | ||
526 | printf("#%d %s:%s\n", test->test_num, test->test_name, | 516 | fprintf(env.stdout, "#%d %s:%s\n", |
527 | test->error_cnt ? "FAIL" : "OK"); | 517 | test->test_num, test->test_name, |
518 | test->error_cnt ? "FAIL" : "OK"); | ||
528 | } | 519 | } |
520 | stdio_restore(); | ||
529 | printf("Summary: %d/%d PASSED, %d FAILED\n", | 521 | printf("Summary: %d/%d PASSED, %d FAILED\n", |
530 | env.succ_cnt, env.sub_succ_cnt, env.fail_cnt); | 522 | env.succ_cnt, env.sub_succ_cnt, env.fail_cnt); |
531 | 523 | ||
532 | free(env.log_buf); | ||
533 | free(env.test_selector.num_set); | 524 | free(env.test_selector.num_set); |
534 | free(env.subtest_selector.num_set); | 525 | free(env.subtest_selector.num_set); |
535 | 526 | ||