From: Eduard Zingerman <eddyz87@gmail.com>
To: bpf@vger.kernel.org, ast@kernel.org
Cc: andrii@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev,
kernel-team@fb.com, yonghong.song@linux.dev, memxor@gmail.com,
awerner32@gmail.com, Eduard Zingerman <eddyz87@gmail.com>
Subject: [PATCH bpf 11/12] selftests/bpf: add __not_msg annotation for test_loader based tests
Date: Thu, 16 Nov 2023 04:18:02 +0200 [thread overview]
Message-ID: <20231116021803.9982-12-eddyz87@gmail.com> (raw)
In-Reply-To: <20231116021803.9982-1-eddyz87@gmail.com>
Add an ability to specify messages that should not be found in the
test verifier log. Similar to LLVM's FileCheck tool for the following
test specification:
__success
__msg("a")
__not_msg("b")
__msg("c")
void foo(...) { ... }
- message "a" is expected to be in the log;
- message "b" is not expected after message "a"
(but could be present before "a");
- message "c" is expected to be in the log after message "a".
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
tools/testing/selftests/bpf/progs/bpf_misc.h | 9 +++
tools/testing/selftests/bpf/test_loader.c | 82 ++++++++++++++------
2 files changed, 68 insertions(+), 23 deletions(-)
diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
index 799fff4995d8..f24fcda6fc0b 100644
--- a/tools/testing/selftests/bpf/progs/bpf_misc.h
+++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
@@ -22,7 +22,13 @@
*
* __msg Message expected to be found in the verifier log.
* Multiple __msg attributes could be specified.
+ * When multiple messages are specified they are
+ * matched one after another.
+ * __not_msg Message not expected to be found in the verifier log.
+ * Matched from the end of the last checked __msg or
+ * from log start, if no __msg had been matched yet.
* __msg_unpriv Same as __msg but for unprivileged mode.
+ * __not_msg_unpriv Same as __not_msg but for unprivileged mode.
*
* __success Expect program load success in privileged mode.
* __success_unpriv Expect program load success in unprivileged mode.
@@ -59,10 +65,13 @@
* __auxiliary_unpriv Same, but load program in unprivileged mode.
*/
#define __msg(msg) __attribute__((btf_decl_tag("comment:test_expect_msg=" msg)))
+#define __not_msg(msg) __attribute__((btf_decl_tag("comment:test_dont_expect_msg=" msg)))
#define __failure __attribute__((btf_decl_tag("comment:test_expect_failure")))
#define __success __attribute__((btf_decl_tag("comment:test_expect_success")))
#define __description(desc) __attribute__((btf_decl_tag("comment:test_description=" desc)))
#define __msg_unpriv(msg) __attribute__((btf_decl_tag("comment:test_expect_msg_unpriv=" msg)))
+#define __not_msg_unpriv(msg) \
+ __attribute__((btf_decl_tag("comment:test_dont_expect_msg_unpriv=" msg)))
#define __failure_unpriv __attribute__((btf_decl_tag("comment:test_expect_failure_unpriv")))
#define __success_unpriv __attribute__((btf_decl_tag("comment:test_expect_success_unpriv")))
#define __log_level(lvl) __attribute__((btf_decl_tag("comment:test_log_level="#lvl)))
diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c
index 37ffa57f28a1..def16d9aeae2 100644
--- a/tools/testing/selftests/bpf/test_loader.c
+++ b/tools/testing/selftests/bpf/test_loader.c
@@ -17,9 +17,11 @@
#define TEST_TAG_EXPECT_FAILURE "comment:test_expect_failure"
#define TEST_TAG_EXPECT_SUCCESS "comment:test_expect_success"
#define TEST_TAG_EXPECT_MSG_PFX "comment:test_expect_msg="
+#define TEST_TAG_DONT_EXPECT_MSG_PFX "comment:test_dont_expect_msg="
#define TEST_TAG_EXPECT_FAILURE_UNPRIV "comment:test_expect_failure_unpriv"
#define TEST_TAG_EXPECT_SUCCESS_UNPRIV "comment:test_expect_success_unpriv"
#define TEST_TAG_EXPECT_MSG_PFX_UNPRIV "comment:test_expect_msg_unpriv="
+#define TEST_TAG_DONT_EXPECT_MSG_PFX_UNPRIV "comment:test_dont_expect_msg_unpriv="
#define TEST_TAG_LOG_LEVEL_PFX "comment:test_log_level="
#define TEST_TAG_PROG_FLAGS_PFX "comment:test_prog_flags="
#define TEST_TAG_DESCRIPTION_PFX "comment:test_description="
@@ -45,10 +47,15 @@ enum mode {
UNPRIV = 2
};
+struct pattern {
+ const char *str;
+ bool expected;
+};
+
struct test_subspec {
char *name;
bool expect_failure;
- const char **expect_msgs;
+ struct pattern *expect_msgs;
size_t expect_msg_cnt;
int retval;
bool execute;
@@ -98,17 +105,21 @@ static void free_test_spec(struct test_spec *spec)
spec->unpriv.expect_msgs = NULL;
}
-static int push_msg(const char *msg, struct test_subspec *subspec)
+static int push_msg(const char *msg, struct test_subspec *subspec, bool expected)
{
+ size_t cnt = subspec->expect_msg_cnt;
void *tmp;
- tmp = realloc(subspec->expect_msgs, (1 + subspec->expect_msg_cnt) * sizeof(void *));
+ tmp = realloc(subspec->expect_msgs,
+ (1 + subspec->expect_msg_cnt) * sizeof(*subspec->expect_msgs));
if (!tmp) {
ASSERT_FAIL("failed to realloc memory for messages\n");
return -ENOMEM;
}
subspec->expect_msgs = tmp;
- subspec->expect_msgs[subspec->expect_msg_cnt++] = msg;
+ subspec->expect_msgs[cnt].str = msg;
+ subspec->expect_msgs[cnt].expected = expected;
+ subspec->expect_msg_cnt++;
return 0;
}
@@ -221,13 +232,25 @@ static int parse_test_spec(struct test_loader *tester,
spec->mode_mask |= UNPRIV;
} else if (str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX)) {
msg = s + sizeof(TEST_TAG_EXPECT_MSG_PFX) - 1;
- err = push_msg(msg, &spec->priv);
+ err = push_msg(msg, &spec->priv, true);
if (err)
goto cleanup;
spec->mode_mask |= PRIV;
} else if (str_has_pfx(s, TEST_TAG_EXPECT_MSG_PFX_UNPRIV)) {
msg = s + sizeof(TEST_TAG_EXPECT_MSG_PFX_UNPRIV) - 1;
- err = push_msg(msg, &spec->unpriv);
+ err = push_msg(msg, &spec->unpriv, true);
+ if (err)
+ goto cleanup;
+ spec->mode_mask |= UNPRIV;
+ } else if (str_has_pfx(s, TEST_TAG_DONT_EXPECT_MSG_PFX)) {
+ msg = s + sizeof(TEST_TAG_DONT_EXPECT_MSG_PFX) - 1;
+ err = push_msg(msg, &spec->priv, false);
+ if (err)
+ goto cleanup;
+ spec->mode_mask |= PRIV;
+ } else if (str_has_pfx(s, TEST_TAG_DONT_EXPECT_MSG_PFX_UNPRIV)) {
+ msg = s + sizeof(TEST_TAG_DONT_EXPECT_MSG_PFX_UNPRIV) - 1;
+ err = push_msg(msg, &spec->unpriv, false);
if (err)
goto cleanup;
spec->mode_mask |= UNPRIV;
@@ -316,7 +339,7 @@ static int parse_test_spec(struct test_loader *tester,
}
if (!spec->unpriv.expect_msgs) {
- size_t sz = spec->priv.expect_msg_cnt * sizeof(void *);
+ size_t sz = spec->priv.expect_msg_cnt * sizeof(*spec->priv.expect_msgs);
spec->unpriv.expect_msgs = malloc(sz);
if (!spec->unpriv.expect_msgs) {
@@ -375,33 +398,46 @@ static void emit_verifier_log(const char *log_buf, bool force)
fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log_buf);
}
+static void show_log_and_msgs(struct test_loader *tester, struct test_subspec *subspec, int n)
+{
+ struct pattern *pat;
+ int i;
+
+ if (env.verbosity == VERBOSE_NONE)
+ emit_verifier_log(tester->log_buf, true /*force*/);
+ for (i = 0; i < n; i++) {
+ pat = &subspec->expect_msgs[i];
+ fprintf(stderr, " MATCHED MSG: %s'%s'\n", pat->expected ? "" : "!", pat->str);
+ }
+}
+
static void validate_case(struct test_loader *tester,
struct test_subspec *subspec,
struct bpf_object *obj,
struct bpf_program *prog,
int load_err)
{
- int i, j;
+ int i;
for (i = 0; i < subspec->expect_msg_cnt; i++) {
+ struct pattern *pat = &subspec->expect_msgs[i];
char *match;
- const char *expect_msg;
-
- expect_msg = subspec->expect_msgs[i];
-
- match = strstr(tester->log_buf + tester->next_match_pos, expect_msg);
- if (!ASSERT_OK_PTR(match, "expect_msg")) {
- /* if we are in verbose mode, we've already emitted log */
- if (env.verbosity == VERBOSE_NONE)
- emit_verifier_log(tester->log_buf, true /*force*/);
- for (j = 0; j < i; j++)
- fprintf(stderr,
- "MATCHED MSG: '%s'\n", subspec->expect_msgs[j]);
- fprintf(stderr, "EXPECTED MSG: '%s'\n", expect_msg);
+
+ match = strstr(tester->log_buf + tester->next_match_pos, pat->str);
+ if (pat->expected && !match) {
+ PRINT_FAIL("Expected log message not found\n");
+ show_log_and_msgs(tester, subspec, i);
+ fprintf(stderr, " EXPECTED MSG: '%s'\n", pat->str);
return;
}
-
- tester->next_match_pos = match - tester->log_buf + strlen(expect_msg);
+ if (!pat->expected && match) {
+ PRINT_FAIL("Unexpected log message found\n");
+ show_log_and_msgs(tester, subspec, i);
+ fprintf(stderr, "UNEXPECTED MSG: '%s'\n", pat->str);
+ return;
+ }
+ if (pat->expected)
+ tester->next_match_pos = match - tester->log_buf + strlen(pat->str);
}
}
--
2.42.0
next prev parent reply other threads:[~2023-11-16 2:18 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-16 2:17 [PATCH bpf 00/12] verify callbacks as if they are called unknown number of times Eduard Zingerman
2023-11-16 2:17 ` [PATCH bpf 01/12] selftests/bpf: track tcp payload offset as scalar in xdp_synproxy Eduard Zingerman
2023-11-17 16:46 ` Andrii Nakryiko
2023-11-16 2:17 ` [PATCH bpf 02/12] selftests/bpf: track string payload offset as scalar in strobemeta Eduard Zingerman
2023-11-17 16:46 ` Andrii Nakryiko
2023-11-17 18:52 ` Eduard Zingerman
2023-11-16 2:17 ` [PATCH bpf 03/12] selftests/bpf: fix bpf_loop_bench for new callback verification scheme Eduard Zingerman
2023-11-17 16:46 ` Andrii Nakryiko
2023-11-17 18:52 ` Eduard Zingerman
2023-11-17 21:38 ` Alexei Starovoitov
2023-11-17 21:43 ` Eduard Zingerman
2023-11-17 21:47 ` Alexei Starovoitov
2023-11-17 21:50 ` Eduard Zingerman
2023-11-17 21:55 ` Alexei Starovoitov
2023-11-16 2:17 ` [PATCH bpf 04/12] bpf: extract __check_reg_arg() utility function Eduard Zingerman
2023-11-17 16:46 ` Andrii Nakryiko
2023-11-16 2:17 ` [PATCH bpf 05/12] bpf: extract setup_func_entry() " Eduard Zingerman
2023-11-17 16:46 ` Andrii Nakryiko
2023-11-17 18:52 ` Eduard Zingerman
2023-11-16 2:17 ` [PATCH bpf 06/12] bpf: verify callbacks as if they are called unknown number of times Eduard Zingerman
2023-11-17 16:46 ` Andrii Nakryiko
2023-11-17 18:52 ` Eduard Zingerman
2023-11-17 20:27 ` Andrii Nakryiko
2023-11-17 21:03 ` Eduard Zingerman
2023-11-16 2:17 ` [PATCH bpf 07/12] selftests/bpf: tests for iterating callbacks Eduard Zingerman
2023-11-17 16:46 ` Andrii Nakryiko
2023-11-16 2:17 ` [PATCH bpf 08/12] bpf: widening for callback iterators Eduard Zingerman
2023-11-17 16:46 ` Andrii Nakryiko
2023-11-16 2:18 ` [PATCH bpf 09/12] selftests/bpf: test widening for iterating callbacks Eduard Zingerman
2023-11-17 16:47 ` Andrii Nakryiko
2023-11-17 18:53 ` Eduard Zingerman
2023-11-17 20:28 ` Andrii Nakryiko
2023-11-16 2:18 ` [PATCH bpf 10/12] bpf: keep track of max number of bpf_loop callback iterations Eduard Zingerman
2023-11-16 14:08 ` Andrii Nakryiko
2023-11-16 14:13 ` Eduard Zingerman
2023-11-17 16:47 ` Andrii Nakryiko
2023-11-17 18:53 ` Eduard Zingerman
2023-11-17 20:30 ` Andrii Nakryiko
2023-11-16 2:18 ` Eduard Zingerman [this message]
2023-11-17 16:45 ` [PATCH bpf 11/12] selftests/bpf: add __not_msg annotation for test_loader based tests Andrii Nakryiko
2023-11-17 18:53 ` Eduard Zingerman
2023-11-17 20:31 ` Andrii Nakryiko
2023-11-17 21:10 ` Eduard Zingerman
2023-11-17 21:33 ` Alexei Starovoitov
2023-11-16 2:18 ` [PATCH bpf 12/12] selftests/bpf: check if max number of bpf_loop iterations is tracked Eduard Zingerman
2023-11-17 16:47 ` Andrii Nakryiko
2023-11-17 18:53 ` Eduard Zingerman
2023-11-17 20:32 ` Andrii Nakryiko
2023-11-17 21:18 ` Eduard Zingerman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231116021803.9982-12-eddyz87@gmail.com \
--to=eddyz87@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=awerner32@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=kernel-team@fb.com \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.