Skip to content

Commit 34c513b

Browse files
eddyz87Alexei Starovoitov
authored andcommitted
selftests/bpf: __not_msg() tag for test_loader framework
This patch adds tags __not_msg(<msg>) and __not_msg_unpriv(<msg>). Test fails if <msg> is found in verifier log. If __msg_not() is situated between __msg() tags framework matches __msg() tags first, and then checks that <msg> is not present in a portion of a log between bracketing __msg() tags. __msg_not() tags bracketed by a same __msg() group are effectively unordered. The idea is borrowed from LLVM's CheckFile with its CHECK-NOT syntax. Signed-off-by: Eduard Zingerman <[email protected]> Link: https://lore.kernel.org/r/20250918-callchain-sensitive-liveness-v3-11-c3cd27bacc60@gmail.com Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 79f047c commit 34c513b

File tree

4 files changed

+302
-50
lines changed

4 files changed

+302
-50
lines changed

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

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,128 @@ void test_prog_tests_framework(void)
5454
return;
5555
clear_test_state(state);
5656
}
57+
58+
static void dummy_emit(const char *buf, bool force) {}
59+
60+
void test_prog_tests_framework_expected_msgs(void)
61+
{
62+
struct expected_msgs msgs;
63+
int i, j, error_cnt;
64+
const struct {
65+
const char *name;
66+
const char *log;
67+
const char *expected;
68+
struct expect_msg *pats;
69+
} cases[] = {
70+
{
71+
.name = "simple-ok",
72+
.log = "aaabbbccc",
73+
.pats = (struct expect_msg[]) {
74+
{ .substr = "aaa" },
75+
{ .substr = "ccc" },
76+
{}
77+
}
78+
},
79+
{
80+
.name = "simple-fail",
81+
.log = "aaabbbddd",
82+
.expected = "MATCHED SUBSTR: 'aaa'\n"
83+
"EXPECTED SUBSTR: 'ccc'\n",
84+
.pats = (struct expect_msg[]) {
85+
{ .substr = "aaa" },
86+
{ .substr = "ccc" },
87+
{}
88+
}
89+
},
90+
{
91+
.name = "negative-ok-mid",
92+
.log = "aaabbbccc",
93+
.pats = (struct expect_msg[]) {
94+
{ .substr = "aaa" },
95+
{ .substr = "foo", .negative = true },
96+
{ .substr = "bar", .negative = true },
97+
{ .substr = "ccc" },
98+
{}
99+
}
100+
},
101+
{
102+
.name = "negative-ok-tail",
103+
.log = "aaabbbccc",
104+
.pats = (struct expect_msg[]) {
105+
{ .substr = "aaa" },
106+
{ .substr = "foo", .negative = true },
107+
{}
108+
}
109+
},
110+
{
111+
.name = "negative-ok-head",
112+
.log = "aaabbbccc",
113+
.pats = (struct expect_msg[]) {
114+
{ .substr = "foo", .negative = true },
115+
{ .substr = "ccc" },
116+
{}
117+
}
118+
},
119+
{
120+
.name = "negative-fail-head",
121+
.log = "aaabbbccc",
122+
.expected = "UNEXPECTED SUBSTR: 'aaa'\n",
123+
.pats = (struct expect_msg[]) {
124+
{ .substr = "aaa", .negative = true },
125+
{ .substr = "bbb" },
126+
{}
127+
}
128+
},
129+
{
130+
.name = "negative-fail-tail",
131+
.log = "aaabbbccc",
132+
.expected = "UNEXPECTED SUBSTR: 'ccc'\n",
133+
.pats = (struct expect_msg[]) {
134+
{ .substr = "bbb" },
135+
{ .substr = "ccc", .negative = true },
136+
{}
137+
}
138+
},
139+
{
140+
.name = "negative-fail-mid-1",
141+
.log = "aaabbbccc",
142+
.expected = "UNEXPECTED SUBSTR: 'bbb'\n",
143+
.pats = (struct expect_msg[]) {
144+
{ .substr = "aaa" },
145+
{ .substr = "bbb", .negative = true },
146+
{ .substr = "ccc" },
147+
{}
148+
}
149+
},
150+
{
151+
.name = "negative-fail-mid-2",
152+
.log = "aaabbb222ccc",
153+
.expected = "UNEXPECTED SUBSTR: '222'\n",
154+
.pats = (struct expect_msg[]) {
155+
{ .substr = "aaa" },
156+
{ .substr = "222", .negative = true },
157+
{ .substr = "bbb", .negative = true },
158+
{ .substr = "ccc" },
159+
{}
160+
}
161+
}
162+
};
163+
164+
for (i = 0; i < ARRAY_SIZE(cases); i++) {
165+
if (test__start_subtest(cases[i].name)) {
166+
error_cnt = env.subtest_state->error_cnt;
167+
msgs.patterns = cases[i].pats;
168+
msgs.cnt = 0;
169+
for (j = 0; cases[i].pats[j].substr; j++)
170+
msgs.cnt++;
171+
validate_msgs(cases[i].log, &msgs, dummy_emit);
172+
fflush(stderr);
173+
env.subtest_state->error_cnt = error_cnt;
174+
if (cases[i].expected)
175+
ASSERT_HAS_SUBSTR(env.subtest_state->log_buf, cases[i].expected, "expected output");
176+
else
177+
ASSERT_STREQ(env.subtest_state->log_buf, "", "expected no output");
178+
test__end_subtest();
179+
}
180+
}
181+
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,14 @@
3333
* e.g. "foo{{[0-9]+}}" matches strings like "foo007".
3434
* Extended POSIX regular expression syntax is allowed
3535
* inside the brackets.
36+
* __not_msg Message not expected to be found in verifier log.
37+
* If __msg_not is situated between __msg tags
38+
* framework matches __msg tags first, and then
39+
* checks that __msg_not is not present in a portion of
40+
* a log between bracketing __msg tags.
41+
* Same regex syntax as for __msg is supported.
3642
* __msg_unpriv Same as __msg but for unprivileged mode.
43+
* __not_msg_unpriv Same as __not_msg but for unprivileged mode.
3744
*
3845
* __stderr Message expected to be found in bpf stderr stream. The
3946
* same regex rules apply like __msg.
@@ -121,12 +128,14 @@
121128
* __caps_unpriv Specify the capabilities that should be set when running the test.
122129
*/
123130
#define __msg(msg) __attribute__((btf_decl_tag("comment:test_expect_msg=" XSTR(__COUNTER__) "=" msg)))
131+
#define __not_msg(msg) __attribute__((btf_decl_tag("comment:test_expect_not_msg=" XSTR(__COUNTER__) "=" msg)))
124132
#define __xlated(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated=" XSTR(__COUNTER__) "=" msg)))
125133
#define __jited(msg) __attribute__((btf_decl_tag("comment:test_jited=" XSTR(__COUNTER__) "=" msg)))
126134
#define __failure __attribute__((btf_decl_tag("comment:test_expect_failure")))
127135
#define __success __attribute__((btf_decl_tag("comment:test_expect_success")))
128136
#define __description(desc) __attribute__((btf_decl_tag("comment:test_description=" desc)))
129137
#define __msg_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" XSTR(__COUNTER__) "=" msg)))
138+
#define __not_msg_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_not_msg_unpriv=" XSTR(__COUNTER__) "=" msg)))
130139
#define __xlated_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated_unpriv=" XSTR(__COUNTER__) "=" msg)))
131140
#define __jited_unpriv(msg) __attribute__((btf_decl_tag("comment:test_jited=" XSTR(__COUNTER__) "=" msg)))
132141
#define __failure_unpriv __attribute__((btf_decl_tag("comment:test_expect_failure_unpriv")))

0 commit comments

Comments
 (0)