selftests/bpf: extract test_loader->expect_msgs as a data structure
Non-functional change: use a separate data structure to represented expected messages in test_loader. This would allow to use the same functionality for expected set of disassembled instructions in the follow-up commit. Acked-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://lore.kernel.org/r/20240722233844.1406874-8-eddyz87@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
This commit is contained in:
committed by
Andrii Nakryiko
parent
4ef5d6af49
commit
64f01e935d
@@ -55,11 +55,15 @@ struct expect_msg {
|
||||
regex_t regex;
|
||||
};
|
||||
|
||||
struct expected_msgs {
|
||||
struct expect_msg *patterns;
|
||||
size_t cnt;
|
||||
};
|
||||
|
||||
struct test_subspec {
|
||||
char *name;
|
||||
bool expect_failure;
|
||||
struct expect_msg *expect_msgs;
|
||||
size_t expect_msg_cnt;
|
||||
struct expected_msgs expect_msgs;
|
||||
int retval;
|
||||
bool execute;
|
||||
};
|
||||
@@ -96,44 +100,45 @@ void test_loader_fini(struct test_loader *tester)
|
||||
free(tester->log_buf);
|
||||
}
|
||||
|
||||
static void free_test_spec(struct test_spec *spec)
|
||||
static void free_msgs(struct expected_msgs *msgs)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < msgs->cnt; i++)
|
||||
if (msgs->patterns[i].regex_str)
|
||||
regfree(&msgs->patterns[i].regex);
|
||||
free(msgs->patterns);
|
||||
msgs->patterns = NULL;
|
||||
msgs->cnt = 0;
|
||||
}
|
||||
|
||||
static void free_test_spec(struct test_spec *spec)
|
||||
{
|
||||
/* Deallocate expect_msgs arrays. */
|
||||
for (i = 0; i < spec->priv.expect_msg_cnt; i++)
|
||||
if (spec->priv.expect_msgs[i].regex_str)
|
||||
regfree(&spec->priv.expect_msgs[i].regex);
|
||||
for (i = 0; i < spec->unpriv.expect_msg_cnt; i++)
|
||||
if (spec->unpriv.expect_msgs[i].regex_str)
|
||||
regfree(&spec->unpriv.expect_msgs[i].regex);
|
||||
free_msgs(&spec->priv.expect_msgs);
|
||||
free_msgs(&spec->unpriv.expect_msgs);
|
||||
|
||||
free(spec->priv.name);
|
||||
free(spec->unpriv.name);
|
||||
free(spec->priv.expect_msgs);
|
||||
free(spec->unpriv.expect_msgs);
|
||||
|
||||
spec->priv.name = NULL;
|
||||
spec->unpriv.name = NULL;
|
||||
spec->priv.expect_msgs = NULL;
|
||||
spec->unpriv.expect_msgs = NULL;
|
||||
}
|
||||
|
||||
static int push_msg(const char *substr, const char *regex_str, struct test_subspec *subspec)
|
||||
static int push_msg(const char *substr, const char *regex_str, struct expected_msgs *msgs)
|
||||
{
|
||||
void *tmp;
|
||||
int regcomp_res;
|
||||
char error_msg[100];
|
||||
struct expect_msg *msg;
|
||||
|
||||
tmp = realloc(subspec->expect_msgs,
|
||||
(1 + subspec->expect_msg_cnt) * sizeof(struct expect_msg));
|
||||
tmp = realloc(msgs->patterns,
|
||||
(1 + msgs->cnt) * sizeof(struct expect_msg));
|
||||
if (!tmp) {
|
||||
ASSERT_FAIL("failed to realloc memory for messages\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
subspec->expect_msgs = tmp;
|
||||
msg = &subspec->expect_msgs[subspec->expect_msg_cnt];
|
||||
msgs->patterns = tmp;
|
||||
msg = &msgs->patterns[msgs->cnt];
|
||||
|
||||
if (substr) {
|
||||
msg->substr = substr;
|
||||
@@ -150,7 +155,7 @@ static int push_msg(const char *substr, const char *regex_str, struct test_subsp
|
||||
}
|
||||
}
|
||||
|
||||
subspec->expect_msg_cnt += 1;
|
||||
msgs->cnt += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -272,25 +277,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, NULL, &spec->priv);
|
||||
err = push_msg(msg, NULL, &spec->priv.expect_msgs);
|
||||
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, NULL, &spec->unpriv);
|
||||
err = push_msg(msg, NULL, &spec->unpriv.expect_msgs);
|
||||
if (err)
|
||||
goto cleanup;
|
||||
spec->mode_mask |= UNPRIV;
|
||||
} else if (str_has_pfx(s, TEST_TAG_EXPECT_REGEX_PFX)) {
|
||||
msg = s + sizeof(TEST_TAG_EXPECT_REGEX_PFX) - 1;
|
||||
err = push_msg(NULL, msg, &spec->priv);
|
||||
err = push_msg(NULL, msg, &spec->priv.expect_msgs);
|
||||
if (err)
|
||||
goto cleanup;
|
||||
spec->mode_mask |= PRIV;
|
||||
} else if (str_has_pfx(s, TEST_TAG_EXPECT_REGEX_PFX_UNPRIV)) {
|
||||
msg = s + sizeof(TEST_TAG_EXPECT_REGEX_PFX_UNPRIV) - 1;
|
||||
err = push_msg(NULL, msg, &spec->unpriv);
|
||||
err = push_msg(NULL, msg, &spec->unpriv.expect_msgs);
|
||||
if (err)
|
||||
goto cleanup;
|
||||
spec->mode_mask |= UNPRIV;
|
||||
@@ -387,11 +392,12 @@ static int parse_test_spec(struct test_loader *tester,
|
||||
spec->unpriv.execute = spec->priv.execute;
|
||||
}
|
||||
|
||||
if (!spec->unpriv.expect_msgs) {
|
||||
for (i = 0; i < spec->priv.expect_msg_cnt; i++) {
|
||||
struct expect_msg *msg = &spec->priv.expect_msgs[i];
|
||||
if (spec->unpriv.expect_msgs.cnt == 0) {
|
||||
for (i = 0; i < spec->priv.expect_msgs.cnt; i++) {
|
||||
struct expect_msg *msg = &spec->priv.expect_msgs.patterns[i];
|
||||
|
||||
err = push_msg(msg->substr, msg->regex_str, &spec->unpriv);
|
||||
err = push_msg(msg->substr, msg->regex_str,
|
||||
&spec->unpriv.expect_msgs);
|
||||
if (err)
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -443,18 +449,14 @@ static void emit_verifier_log(const char *log_buf, bool force)
|
||||
fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log_buf);
|
||||
}
|
||||
|
||||
static void validate_case(struct test_loader *tester,
|
||||
struct test_subspec *subspec,
|
||||
struct bpf_object *obj,
|
||||
struct bpf_program *prog,
|
||||
int load_err)
|
||||
static void validate_msgs(char *log_buf, struct expected_msgs *msgs)
|
||||
{
|
||||
regmatch_t reg_match[1];
|
||||
const char *log = tester->log_buf;
|
||||
const char *log = log_buf;
|
||||
int i, j, err;
|
||||
|
||||
for (i = 0; i < subspec->expect_msg_cnt; i++) {
|
||||
struct expect_msg *msg = &subspec->expect_msgs[i];
|
||||
for (i = 0; i < msgs->cnt; i++) {
|
||||
struct expect_msg *msg = &msgs->patterns[i];
|
||||
const char *match = NULL;
|
||||
|
||||
if (msg->substr) {
|
||||
@@ -471,9 +473,9 @@ static void validate_case(struct test_loader *tester,
|
||||
|
||||
if (!ASSERT_OK_PTR(match, "expect_msg")) {
|
||||
if (env.verbosity == VERBOSE_NONE)
|
||||
emit_verifier_log(tester->log_buf, true /*force*/);
|
||||
emit_verifier_log(log_buf, true /*force*/);
|
||||
for (j = 0; j <= i; j++) {
|
||||
msg = &subspec->expect_msgs[j];
|
||||
msg = &msgs->patterns[j];
|
||||
fprintf(stderr, "%s %s: '%s'\n",
|
||||
j < i ? "MATCHED " : "EXPECTED",
|
||||
msg->substr ? "SUBSTR" : " REGEX",
|
||||
@@ -692,9 +694,8 @@ void run_subtest(struct test_loader *tester,
|
||||
goto tobj_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
emit_verifier_log(tester->log_buf, false /*force*/);
|
||||
validate_case(tester, subspec, tobj, tprog, err);
|
||||
validate_msgs(tester->log_buf, &subspec->expect_msgs);
|
||||
|
||||
if (should_do_test_run(spec, subspec)) {
|
||||
/* For some reason test_verifier executes programs
|
||||
|
||||
Reference in New Issue
Block a user