Skip to content

Commit 744eeb2

Browse files
puranjaymohanAlexei Starovoitov
authored andcommitted
selftests: bpf: introduce __stderr and __stdout
Add __stderr and __stdout to validate the output of BPF streams for bpf selftests. Similar to __xlated, __jited, etc., __stderr/out can be used in the BPF progs to compare a string (regex supported) to the output in the bpf streams. Signed-off-by: Puranjay Mohan <[email protected]> Acked-by: Eduard Zingerman <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 5c5240d commit 744eeb2

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

tools/testing/selftests/bpf/progs/bpf_misc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@
3535
* inside the brackets.
3636
* __msg_unpriv Same as __msg but for unprivileged mode.
3737
*
38+
* __stderr Message expected to be found in bpf stderr stream. The
39+
* same regex rules apply like __msg.
40+
* __stderr_unpriv Same as __stderr but for unpriveleged mode.
41+
* __stdout Same as __stderr but for stdout stream.
42+
* __stdout_unpriv Same as __stdout but for unpriveleged mode.
43+
*
3844
* __xlated Expect a line in a disassembly log after verifier applies rewrites.
3945
* Multiple __xlated attributes could be specified.
4046
* Regular expressions could be specified same way as in __msg.
@@ -140,6 +146,10 @@
140146
#define __caps_unpriv(caps) __attribute__((btf_decl_tag("comment:test_caps_unpriv=" EXPAND_QUOTE(caps))))
141147
#define __load_if_JITed() __attribute__((btf_decl_tag("comment:load_mode=jited")))
142148
#define __load_if_no_JITed() __attribute__((btf_decl_tag("comment:load_mode=no_jited")))
149+
#define __stderr(msg) __attribute__((btf_decl_tag("comment:test_expect_stderr=" XSTR(__COUNTER__) "=" msg)))
150+
#define __stderr_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_stderr_unpriv=" XSTR(__COUNTER__) "=" msg)))
151+
#define __stdout(msg) __attribute__((btf_decl_tag("comment:test_expect_stdout=" XSTR(__COUNTER__) "=" msg)))
152+
#define __stdout_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_stdout_unpriv=" XSTR(__COUNTER__) "=" msg)))
143153

144154
/* Define common capabilities tested using __caps_unpriv */
145155
#define CAP_NET_ADMIN 12

tools/testing/selftests/bpf/test_loader.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@
3838
#define TEST_TAG_JITED_PFX_UNPRIV "comment:test_jited_unpriv="
3939
#define TEST_TAG_CAPS_UNPRIV "comment:test_caps_unpriv="
4040
#define TEST_TAG_LOAD_MODE_PFX "comment:load_mode="
41+
#define TEST_TAG_EXPECT_STDERR_PFX "comment:test_expect_stderr="
42+
#define TEST_TAG_EXPECT_STDERR_PFX_UNPRIV "comment:test_expect_stderr_unpriv="
43+
#define TEST_TAG_EXPECT_STDOUT_PFX "comment:test_expect_stdout="
44+
#define TEST_TAG_EXPECT_STDOUT_PFX_UNPRIV "comment:test_expect_stdout_unpriv="
4145

4246
/* Warning: duplicated in bpf_misc.h */
4347
#define POINTER_VALUE 0xbadcafe
@@ -79,6 +83,8 @@ struct test_subspec {
7983
struct expected_msgs expect_msgs;
8084
struct expected_msgs expect_xlated;
8185
struct expected_msgs jited;
86+
struct expected_msgs stderr;
87+
struct expected_msgs stdout;
8288
int retval;
8389
bool execute;
8490
__u64 caps;
@@ -139,6 +145,10 @@ static void free_test_spec(struct test_spec *spec)
139145
free_msgs(&spec->unpriv.expect_xlated);
140146
free_msgs(&spec->priv.jited);
141147
free_msgs(&spec->unpriv.jited);
148+
free_msgs(&spec->unpriv.stderr);
149+
free_msgs(&spec->priv.stderr);
150+
free_msgs(&spec->unpriv.stdout);
151+
free_msgs(&spec->priv.stdout);
142152

143153
free(spec->priv.name);
144154
free(spec->unpriv.name);
@@ -407,6 +417,10 @@ static int parse_test_spec(struct test_loader *tester,
407417
bool xlated_on_next_line = true;
408418
bool unpriv_jit_on_next_line;
409419
bool jit_on_next_line;
420+
bool stderr_on_next_line = true;
421+
bool unpriv_stderr_on_next_line = true;
422+
bool stdout_on_next_line = true;
423+
bool unpriv_stdout_on_next_line = true;
410424
bool collect_jit = false;
411425
int func_id, i, err = 0;
412426
u32 arch_mask = 0;
@@ -598,6 +612,26 @@ static int parse_test_spec(struct test_loader *tester,
598612
err = -EINVAL;
599613
goto cleanup;
600614
}
615+
} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_STDERR_PFX))) {
616+
err = push_disasm_msg(msg, &stderr_on_next_line,
617+
&spec->priv.stderr);
618+
if (err)
619+
goto cleanup;
620+
} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_STDERR_PFX_UNPRIV))) {
621+
err = push_disasm_msg(msg, &unpriv_stderr_on_next_line,
622+
&spec->unpriv.stderr);
623+
if (err)
624+
goto cleanup;
625+
} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_STDOUT_PFX))) {
626+
err = push_disasm_msg(msg, &stdout_on_next_line,
627+
&spec->priv.stdout);
628+
if (err)
629+
goto cleanup;
630+
} else if ((msg = skip_dynamic_pfx(s, TEST_TAG_EXPECT_STDOUT_PFX_UNPRIV))) {
631+
err = push_disasm_msg(msg, &unpriv_stdout_on_next_line,
632+
&spec->unpriv.stdout);
633+
if (err)
634+
goto cleanup;
601635
}
602636
}
603637

@@ -651,6 +685,10 @@ static int parse_test_spec(struct test_loader *tester,
651685
clone_msgs(&spec->priv.expect_xlated, &spec->unpriv.expect_xlated);
652686
if (spec->unpriv.jited.cnt == 0)
653687
clone_msgs(&spec->priv.jited, &spec->unpriv.jited);
688+
if (spec->unpriv.stderr.cnt == 0)
689+
clone_msgs(&spec->priv.stderr, &spec->unpriv.stderr);
690+
if (spec->unpriv.stdout.cnt == 0)
691+
clone_msgs(&spec->priv.stdout, &spec->unpriv.stdout);
654692
}
655693

656694
spec->valid = true;
@@ -712,6 +750,20 @@ static void emit_jited(const char *jited, bool force)
712750
fprintf(stdout, "JITED:\n=============\n%s=============\n", jited);
713751
}
714752

753+
static void emit_stderr(const char *stderr, bool force)
754+
{
755+
if (!force && env.verbosity == VERBOSE_NONE)
756+
return;
757+
fprintf(stdout, "STDERR:\n=============\n%s=============\n", stderr);
758+
}
759+
760+
static void emit_stdout(const char *bpf_stdout, bool force)
761+
{
762+
if (!force && env.verbosity == VERBOSE_NONE)
763+
return;
764+
fprintf(stdout, "STDOUT:\n=============\n%s=============\n", bpf_stdout);
765+
}
766+
715767
static void validate_msgs(char *log_buf, struct expected_msgs *msgs,
716768
void (*emit_fn)(const char *buf, bool force))
717769
{
@@ -934,6 +986,19 @@ static int get_xlated_program_text(int prog_fd, char *text, size_t text_sz)
934986
return err;
935987
}
936988

989+
/* Read the bpf stream corresponding to the stream_id */
990+
static int get_stream(int stream_id, int prog_fd, char *text, size_t text_sz)
991+
{
992+
LIBBPF_OPTS(bpf_prog_stream_read_opts, ropts);
993+
int ret;
994+
995+
ret = bpf_prog_stream_read(prog_fd, stream_id, text, text_sz, &ropts);
996+
ASSERT_GT(ret, 0, "stream read");
997+
text[ret] = '\0';
998+
999+
return ret;
1000+
}
1001+
9371002
/* this function is forced noinline and has short generic name to look better
9381003
* in test_progs output (in case of a failure)
9391004
*/
@@ -1108,6 +1173,31 @@ void run_subtest(struct test_loader *tester,
11081173
PRINT_FAIL("Unexpected retval: %d != %d\n", retval, subspec->retval);
11091174
goto tobj_cleanup;
11101175
}
1176+
1177+
if (subspec->stderr.cnt) {
1178+
err = get_stream(2, bpf_program__fd(tprog),
1179+
tester->log_buf, tester->log_buf_sz);
1180+
if (err <= 0) {
1181+
PRINT_FAIL("Unexpected retval from get_stream(): %d, errno = %d\n",
1182+
err, errno);
1183+
goto tobj_cleanup;
1184+
}
1185+
emit_stderr(tester->log_buf, false /*force*/);
1186+
validate_msgs(tester->log_buf, &subspec->stderr, emit_stderr);
1187+
}
1188+
1189+
if (subspec->stdout.cnt) {
1190+
err = get_stream(1, bpf_program__fd(tprog),
1191+
tester->log_buf, tester->log_buf_sz);
1192+
if (err <= 0) {
1193+
PRINT_FAIL("Unexpected retval from get_stream(): %d, errno = %d\n",
1194+
err, errno);
1195+
goto tobj_cleanup;
1196+
}
1197+
emit_stdout(tester->log_buf, false /*force*/);
1198+
validate_msgs(tester->log_buf, &subspec->stdout, emit_stdout);
1199+
}
1200+
11111201
/* redo bpf_map__attach_struct_ops for each test */
11121202
while (links_cnt > 0)
11131203
bpf_link__destroy(links[--links_cnt]);

0 commit comments

Comments
 (0)