Skip to content

Commit 682cdbd

Browse files
author
Alexei Starovoitov
committed
Merge branch 'test_progs-stdio'
Stanislav Fomichev says: ==================== I was looking into converting test_sockops* to test_progs framework and that requires using cgroup_helpers.c which rely on stdio/stderr. Let's use open_memstream to override stdout into buffer during subtests instead of custom test_{v,}printf wrappers. That lets us continue to use stdio in the subtests and dump it on failure if required. That would also fix bpf_find_map which currently uses printf to signal failure (missed during test_printf conversion). ==================== Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents 8c30396 + 16e910d commit 682cdbd

File tree

10 files changed

+84
-94
lines changed

10 files changed

+84
-94
lines changed

tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ static int libbpf_debug_print(enum libbpf_print_level level,
55
const char *format, va_list args)
66
{
77
if (level != LIBBPF_DEBUG) {
8-
test__vprintf(format, args);
8+
vprintf(format, args);
99
return 0;
1010
}
1111

1212
if (!strstr(format, "verifier log"))
1313
return 0;
14-
test__vprintf("%s", args);
14+
vprintf("%s", args);
1515
return 0;
1616
}
1717

tools/testing/selftests/bpf/prog_tests/l4lb_all.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ static void test_l4lb(const char *file)
7474
}
7575
if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
7676
error_cnt++;
77-
test__printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts);
77+
printf("test_l4lb:FAIL:stats %lld %lld\n", bytes, pkts);
7878
}
7979
out:
8080
bpf_object__close(obj);

tools/testing/selftests/bpf/prog_tests/map_lock.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@ static void *parallel_map_access(void *arg)
99
for (i = 0; i < 10000; i++) {
1010
err = bpf_map_lookup_elem_flags(map_fd, &key, vars, BPF_F_LOCK);
1111
if (err) {
12-
test__printf("lookup failed\n");
12+
printf("lookup failed\n");
1313
error_cnt++;
1414
goto out;
1515
}
1616
if (vars[0] != 0) {
17-
test__printf("lookup #%d var[0]=%d\n", i, vars[0]);
17+
printf("lookup #%d var[0]=%d\n", i, vars[0]);
1818
error_cnt++;
1919
goto out;
2020
}
2121
rnd = vars[1];
2222
for (j = 2; j < 17; j++) {
2323
if (vars[j] == rnd)
2424
continue;
25-
test__printf("lookup #%d var[1]=%d var[%d]=%d\n",
26-
i, rnd, j, vars[j]);
25+
printf("lookup #%d var[1]=%d var[%d]=%d\n",
26+
i, rnd, j, vars[j]);
2727
error_cnt++;
2828
goto out;
2929
}
@@ -43,7 +43,7 @@ void test_map_lock(void)
4343

4444
err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd);
4545
if (err) {
46-
test__printf("test_map_lock:bpf_prog_load errno %d\n", errno);
46+
printf("test_map_lock:bpf_prog_load errno %d\n", errno);
4747
goto close_prog;
4848
}
4949
map_fd[0] = bpf_find_map(__func__, obj, "hash_map");

tools/testing/selftests/bpf/prog_tests/send_signal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,8 @@ static int test_send_signal_nmi(void)
202202
-1 /* cpu */, -1 /* group_fd */, 0 /* flags */);
203203
if (pmu_fd == -1) {
204204
if (errno == ENOENT) {
205-
test__printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n",
206-
__func__);
205+
printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n",
206+
__func__);
207207
return 0;
208208
}
209209
/* Let the test fail with a more informative message */

tools/testing/selftests/bpf/prog_tests/spinlock.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ void test_spinlock(void)
1212

1313
err = bpf_prog_load(file, BPF_PROG_TYPE_CGROUP_SKB, &obj, &prog_fd);
1414
if (err) {
15-
test__printf("test_spin_lock:bpf_prog_load errno %d\n", errno);
15+
printf("test_spin_lock:bpf_prog_load errno %d\n", errno);
1616
goto close_prog;
1717
}
1818
for (i = 0; i < 4; i++)

tools/testing/selftests/bpf/prog_tests/stacktrace_build_id.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ void test_stacktrace_build_id(void)
109109
if (build_id_matches < 1 && retry--) {
110110
bpf_link__destroy(link);
111111
bpf_object__close(obj);
112-
test__printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
113-
__func__);
112+
printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
113+
__func__);
114114
goto retry;
115115
}
116116

tools/testing/selftests/bpf/prog_tests/stacktrace_build_id_nmi.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ void test_stacktrace_build_id_nmi(void)
140140
if (build_id_matches < 1 && retry--) {
141141
bpf_link__destroy(link);
142142
bpf_object__close(obj);
143-
test__printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
144-
__func__);
143+
printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
144+
__func__);
145145
goto retry;
146146
}
147147

tools/testing/selftests/bpf/prog_tests/xdp_noinline.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ void test_xdp_noinline(void)
7575
}
7676
if (bytes != MAGIC_BYTES * NUM_ITER * 2 || pkts != NUM_ITER * 2) {
7777
error_cnt++;
78-
test__printf("test_xdp_noinline:FAIL:stats %lld %lld\n",
79-
bytes, pkts);
78+
printf("test_xdp_noinline:FAIL:stats %lld %lld\n",
79+
bytes, pkts);
8080
}
8181
out:
8282
bpf_object__close(obj);

tools/testing/selftests/bpf/test_progs.c

Lines changed: 61 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,20 @@ static bool should_run(struct test_selector *sel, int num, const char *name)
4040

4141
static void dump_test_log(const struct prog_test_def *test, bool failed)
4242
{
43+
if (stdout == env.stdout)
44+
return;
45+
46+
fflush(stdout); /* exports env.log_buf & env.log_cnt */
47+
4348
if (env.verbose || test->force_log || failed) {
4449
if (env.log_cnt) {
45-
fprintf(stdout, "%s", env.log_buf);
50+
fprintf(env.stdout, "%s", env.log_buf);
4651
if (env.log_buf[env.log_cnt - 1] != '\n')
47-
fprintf(stdout, "\n");
52+
fprintf(env.stdout, "\n");
4853
}
4954
}
50-
env.log_cnt = 0;
55+
56+
fseeko(stdout, 0, SEEK_SET); /* rewind */
5157
}
5258

5359
void test__end_subtest()
@@ -62,7 +68,7 @@ void test__end_subtest()
6268

6369
dump_test_log(test, sub_error_cnt);
6470

65-
printf("#%d/%d %s:%s\n",
71+
fprintf(env.stdout, "#%d/%d %s:%s\n",
6672
test->test_num, test->subtest_num,
6773
test->subtest_name, sub_error_cnt ? "FAIL" : "OK");
6874
}
@@ -79,7 +85,8 @@ bool test__start_subtest(const char *name)
7985
test->subtest_num++;
8086

8187
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",
8390
test->subtest_num);
8491
return false;
8592
}
@@ -98,66 +105,6 @@ void test__force_log() {
98105
env.test->force_log = true;
99106
}
100107

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-
161108
struct ipv4_packet pkt_v4 = {
162109
.eth.h_proto = __bpf_constant_htons(ETH_P_IP),
163110
.iph.ihl = 5,
@@ -331,7 +278,7 @@ enum ARG_KEYS {
331278
ARG_VERIFIER_STATS = 's',
332279
ARG_VERBOSE = 'v',
333280
};
334-
281+
335282
static const struct argp_option opts[] = {
336283
{ "num", ARG_TEST_NUM, "NUM", 0,
337284
"Run test number NUM only " },
@@ -349,7 +296,7 @@ static int libbpf_print_fn(enum libbpf_print_level level,
349296
{
350297
if (!env.very_verbose && level == LIBBPF_DEBUG)
351298
return 0;
352-
test__vprintf(format, args);
299+
vprintf(format, args);
353300
return 0;
354301
}
355302

@@ -477,6 +424,48 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
477424
return 0;
478425
}
479426

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+
480469
int main(int argc, char **argv)
481470
{
482471
static const struct argp argp = {
@@ -496,6 +485,7 @@ int main(int argc, char **argv)
496485

497486
env.jit_enabled = is_jit_enabled();
498487

488+
stdio_hijack();
499489
for (i = 0; i < prog_test_cnt; i++) {
500490
struct prog_test_def *test = &prog_test_defs[i];
501491
int old_pass_cnt = pass_cnt;
@@ -523,13 +513,14 @@ int main(int argc, char **argv)
523513

524514
dump_test_log(test, test->error_cnt);
525515

526-
printf("#%d %s:%s\n", test->test_num, test->test_name,
527-
test->error_cnt ? "FAIL" : "OK");
516+
fprintf(env.stdout, "#%d %s:%s\n",
517+
test->test_num, test->test_name,
518+
test->error_cnt ? "FAIL" : "OK");
528519
}
520+
stdio_restore();
529521
printf("Summary: %d/%d PASSED, %d FAILED\n",
530522
env.succ_cnt, env.sub_succ_cnt, env.fail_cnt);
531523

532-
free(env.log_buf);
533524
free(env.test_selector.num_set);
534525
free(env.subtest_selector.num_set);
535526

tools/testing/selftests/bpf/test_progs.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,10 @@ struct test_env {
5656
bool jit_enabled;
5757

5858
struct prog_test_def *test;
59+
FILE *stdout;
60+
FILE *stderr;
5961
char *log_buf;
6062
size_t log_cnt;
61-
size_t log_cap;
6263

6364
int succ_cnt; /* successful tests */
6465
int sub_succ_cnt; /* successful sub-tests */
@@ -69,8 +70,6 @@ extern int error_cnt;
6970
extern int pass_cnt;
7071
extern struct test_env env;
7172

72-
extern void test__printf(const char *fmt, ...);
73-
extern void test__vprintf(const char *fmt, va_list args);
7473
extern void test__force_log();
7574
extern bool test__start_subtest(const char *name);
7675

@@ -96,12 +95,12 @@ extern struct ipv6_packet pkt_v6;
9695
int __ret = !!(condition); \
9796
if (__ret) { \
9897
error_cnt++; \
99-
test__printf("%s:FAIL:%s ", __func__, tag); \
100-
test__printf(format); \
98+
printf("%s:FAIL:%s ", __func__, tag); \
99+
printf(format); \
101100
} else { \
102101
pass_cnt++; \
103-
test__printf("%s:PASS:%s %d nsec\n", \
104-
__func__, tag, duration); \
102+
printf("%s:PASS:%s %d nsec\n", \
103+
__func__, tag, duration); \
105104
} \
106105
__ret; \
107106
})

0 commit comments

Comments
 (0)