Skip to content

Commit ca78b3e

Browse files
mykola-lysenkoNobody
authored and
Nobody
committed
selftests/bpf: Improve by-name subtest selection logic in prog_tests
Improve subtest selection logic when using -t/-a/-d parameters. In particular, more than one subtest can be specified or a combination of tests / subtests. -a send_signal -d send_signal/send_signal_nmi* - runs send_signal test without nmi tests -a send_signal/send_signal_nmi*,find_vma - runs two send_signal subtests and find_vma test This will allow us to have granular control over which subtests to disable in the CI system instead of disabling whole tests. Also, add new selftest to avoid possible regression when changing prog_test test name selection logic. Signed-off-by: Mykola Lysenko <[email protected]>
1 parent aa671ab commit ca78b3e

File tree

5 files changed

+266
-88
lines changed

5 files changed

+266
-88
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2+
3+
#include "test_progs.h"
4+
#include "testing_helpers.h"
5+
6+
static int duration;
7+
8+
static void init_test_set(struct test_set *test_set)
9+
{
10+
test_set->cnt = 0;
11+
test_set->tests = NULL;
12+
}
13+
14+
static void free_test_set(struct test_set *test_set)
15+
{
16+
int i, j;
17+
18+
for (i = 0; i < test_set->cnt; i++) {
19+
for (j = 0; j < test_set->tests[i].subtest_cnt; j++)
20+
free((void *)test_set->tests[i].subtests[j]);
21+
free(test_set->tests[i].subtests);
22+
free(test_set->tests[i].name);
23+
}
24+
25+
free(test_set->tests);
26+
init_test_set(test_set);
27+
}
28+
29+
static void test_parse_test_list(void)
30+
{
31+
struct test_set test_set;
32+
33+
init_test_set(&test_set);
34+
35+
parse_test_list("arg_parsing", &test_set, true);
36+
if (CHECK(test_set.cnt != 1, "parse_test_list subtest argument", "Unexpected number of tests in num table %d\n", test_set.cnt))
37+
goto error;
38+
if (!ASSERT_OK_PTR(test_set.tests, "tests__initialized"))
39+
goto error;
40+
if (CHECK(!test_set.tests[0].whole_test, "parse_test_list subtest argument", "Expected test 0 to be initialized"))
41+
goto error;
42+
if (CHECK(strcmp("arg_parsing", test_set.tests[0].name), "parse_test_list subtest argument", "Expected test 0 to be initialized"))
43+
goto error;
44+
free_test_set(&test_set);
45+
46+
parse_test_list("arg_parsing,bpf_cookie", &test_set, true);
47+
if (CHECK(test_set.cnt != 2, "parse_test_list subtest argument", "Unexpected number of tests in num table %d\n", test_set.cnt))
48+
goto error;
49+
if (!ASSERT_OK_PTR(test_set.tests, "tests__initialized"))
50+
goto error;
51+
if (CHECK(!test_set.tests[0].whole_test, "parse_test_list subtest argument", "Expected test 0 to be fully runnable"))
52+
goto error;
53+
if (CHECK(!test_set.tests[1].whole_test, "parse_test_list subtest argument", "Expected test 1 to be fully runnable"))
54+
goto error;
55+
if (CHECK(strcmp("arg_parsing", test_set.tests[0].name), "parse_test_list subtest argument", "Expected test 0 to be arg_parsing"))
56+
goto error;
57+
if (CHECK(strcmp("bpf_cookie", test_set.tests[1].name), "parse_test_list subtest argument", "Expected test 1 to be bpf_cookie"))
58+
goto error;
59+
free_test_set(&test_set);
60+
61+
parse_test_list("arg_parsing/test_parse_test_list,bpf_cookie", &test_set, true);
62+
if (CHECK(test_set.cnt != 2, "parse_test_list subtest argument", "Unexpected number of tests in num table %d\n", test_set.cnt))
63+
goto error;
64+
if (!ASSERT_OK_PTR(test_set.tests, "tests__initialized"))
65+
goto error;
66+
if (CHECK(test_set.tests[0].whole_test, "parse_test_list no subtest argument", "Expected test 0 to be fully runnable"))
67+
goto error;
68+
if (CHECK(!test_set.tests[1].whole_test, "parse_test_list no subtest argument", "Expected test 0 to be fully runnable"))
69+
goto error;
70+
if (CHECK(strcmp("arg_parsing", test_set.tests[0].name), "parse_test_list subtest argument", "Expected test 0 to be arg_parsing"))
71+
goto error;
72+
if (CHECK(test_set.tests[0].subtest_cnt != 1, "parse_test_list subtest number", "Unexpected number of subtests for arg_parsing %d\n", test_set.tests[0].subtest_cnt))
73+
goto error;
74+
if (CHECK(strcmp("test_parse_test_list", test_set.tests[0].subtests[0]), "parse_test_list subtest name", "Expected test 0 first subtest to be to be test_parse_test_list"))
75+
goto error;
76+
if (CHECK(test_set.tests[1].subtest_cnt != 0, "parse_test_list subtest number", "Unexpected number of subtests for bpf_cookie %d\n", test_set.tests[1].subtest_cnt))
77+
goto error;
78+
if (CHECK(strcmp("bpf_cookie", test_set.tests[1].name), "parse_test_list subtest argument", "Expected test 1 to be bpf_cookie"))
79+
goto error;
80+
error:
81+
free_test_set(&test_set);
82+
}
83+
84+
void test_arg_parsing(void)
85+
{
86+
if (test__start_subtest("test_parse_test_list"))
87+
test_parse_test_list();
88+
}

tools/testing/selftests/bpf/test_progs.c

Lines changed: 74 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44
#define _GNU_SOURCE
55
#include "test_progs.h"
6+
#include "testing_helpers.h"
67
#include "cgroup_helpers.h"
78
#include <argp.h>
89
#include <pthread.h>
@@ -82,14 +83,14 @@ int usleep(useconds_t usec)
8283
static bool should_run(struct test_selector *sel, int num, const char *name)
8384
{
8485
int i;
85-
8686
for (i = 0; i < sel->blacklist.cnt; i++) {
87-
if (glob_match(name, sel->blacklist.strs[i]))
87+
if (glob_match(name, sel->blacklist.tests[i].name) &&
88+
sel->blacklist.tests[i].whole_test)
8889
return false;
8990
}
9091

9192
for (i = 0; i < sel->whitelist.cnt; i++) {
92-
if (glob_match(name, sel->whitelist.strs[i]))
93+
if (glob_match(name, sel->whitelist.tests[i].name))
9394
return true;
9495
}
9596

@@ -99,6 +100,46 @@ static bool should_run(struct test_selector *sel, int num, const char *name)
99100
return num < sel->num_set_len && sel->num_set[num];
100101
}
101102

103+
static bool should_run_subtest(struct test_selector *sel,
104+
struct test_selector *subtest_sel,
105+
int subtest_num,
106+
const char *test_name,
107+
const char *subtest_name)
108+
{
109+
int i, j;
110+
111+
for (i = 0; i < sel->blacklist.cnt; i++) {
112+
if (glob_match(test_name, sel->blacklist.tests[i].name)) {
113+
if (!sel->blacklist.tests[i].subtest_cnt)
114+
return false;
115+
116+
for (j = 0; j < sel->blacklist.tests[i].subtest_cnt; j++) {
117+
if (glob_match(subtest_name,
118+
sel->blacklist.tests[i].subtests[j]))
119+
return false;
120+
}
121+
}
122+
}
123+
124+
for (i = 0; i < sel->whitelist.cnt; i++) {
125+
if (glob_match(test_name, sel->whitelist.tests[i].name)) {
126+
if (!sel->whitelist.tests[i].subtest_cnt)
127+
return true;
128+
129+
for (j = 0; j < sel->whitelist.tests[i].subtest_cnt; j++) {
130+
if (glob_match(subtest_name,
131+
sel->whitelist.tests[i].subtests[j]))
132+
return true;
133+
}
134+
}
135+
}
136+
137+
if (!sel->whitelist.cnt && !subtest_sel->num_set)
138+
return true;
139+
140+
return subtest_num < subtest_sel->num_set_len && subtest_sel->num_set[subtest_num];
141+
}
142+
102143
static void dump_test_log(const struct prog_test_def *test, bool failed)
103144
{
104145
if (stdout == env.stdout)
@@ -196,7 +237,7 @@ void test__end_subtest(void)
196237
test->subtest_name = NULL;
197238
}
198239

199-
bool test__start_subtest(const char *name)
240+
bool test__start_subtest(const char *subtest_name)
200241
{
201242
struct prog_test_def *test = env.test;
202243

@@ -205,17 +246,21 @@ bool test__start_subtest(const char *name)
205246

206247
test->subtest_num++;
207248

208-
if (!name || !name[0]) {
249+
if (!subtest_name || !subtest_name[0]) {
209250
fprintf(env.stderr,
210251
"Subtest #%d didn't provide sub-test name!\n",
211252
test->subtest_num);
212253
return false;
213254
}
214255

215-
if (!should_run(&env.subtest_selector, test->subtest_num, name))
256+
if (!should_run_subtest(&env.test_selector,
257+
&env.subtest_selector,
258+
test->subtest_num,
259+
test->test_name,
260+
subtest_name))
216261
return false;
217262

218-
test->subtest_name = strdup(name);
263+
test->subtest_name = strdup(subtest_name);
219264
if (!test->subtest_name) {
220265
fprintf(env.stderr,
221266
"Subtest #%d: failed to copy subtest name!\n",
@@ -527,63 +572,29 @@ static int libbpf_print_fn(enum libbpf_print_level level,
527572
return 0;
528573
}
529574

530-
static void free_str_set(const struct str_set *set)
575+
static void free_test_set(const struct test_set *set)
531576
{
532-
int i;
577+
int i, j;
533578

534579
if (!set)
535580
return;
536581

537-
for (i = 0; i < set->cnt; i++)
538-
free((void *)set->strs[i]);
539-
free(set->strs);
540-
}
541-
542-
static int parse_str_list(const char *s, struct str_set *set, bool is_glob_pattern)
543-
{
544-
char *input, *state = NULL, *next, **tmp, **strs = NULL;
545-
int i, cnt = 0;
582+
for (i = 0; i < set->cnt; i++) {
583+
free((void *)set->tests[i].name);
584+
for (j = 0; j < set->tests[i].subtest_cnt; j++)
585+
free((void *)set->tests[i].subtests[j]);
546586

547-
input = strdup(s);
548-
if (!input)
549-
return -ENOMEM;
550-
551-
while ((next = strtok_r(state ? NULL : input, ",", &state))) {
552-
tmp = realloc(strs, sizeof(*strs) * (cnt + 1));
553-
if (!tmp)
554-
goto err;
555-
strs = tmp;
556-
557-
if (is_glob_pattern) {
558-
strs[cnt] = strdup(next);
559-
if (!strs[cnt])
560-
goto err;
561-
} else {
562-
strs[cnt] = malloc(strlen(next) + 2 + 1);
563-
if (!strs[cnt])
564-
goto err;
565-
sprintf(strs[cnt], "*%s*", next);
566-
}
567-
568-
cnt++;
587+
free((void *)set->tests[i].subtests);
569588
}
570589

571-
tmp = realloc(set->strs, sizeof(*strs) * (cnt + set->cnt));
572-
if (!tmp)
573-
goto err;
574-
memcpy(tmp + set->cnt, strs, sizeof(*strs) * cnt);
575-
set->strs = (const char **)tmp;
576-
set->cnt += cnt;
590+
free((void *)set->tests);
591+
}
577592

578-
free(input);
579-
free(strs);
580-
return 0;
581-
err:
582-
for (i = 0; i < cnt; i++)
583-
free(strs[i]);
584-
free(strs);
585-
free(input);
586-
return -ENOMEM;
593+
static void free_test_selector(struct test_selector *test_selector)
594+
{
595+
free_test_set(&test_selector->blacklist);
596+
free_test_set(&test_selector->whitelist);
597+
free(test_selector->num_set);
587598
}
588599

589600
extern int extra_prog_load_log_flags;
@@ -615,33 +626,17 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
615626
}
616627
case ARG_TEST_NAME_GLOB_ALLOWLIST:
617628
case ARG_TEST_NAME: {
618-
char *subtest_str = strchr(arg, '/');
619-
620-
if (subtest_str) {
621-
*subtest_str = '\0';
622-
if (parse_str_list(subtest_str + 1,
623-
&env->subtest_selector.whitelist,
624-
key == ARG_TEST_NAME_GLOB_ALLOWLIST))
625-
return -ENOMEM;
626-
}
627-
if (parse_str_list(arg, &env->test_selector.whitelist,
628-
key == ARG_TEST_NAME_GLOB_ALLOWLIST))
629+
if (parse_test_list(arg,
630+
&env->test_selector.whitelist,
631+
key == ARG_TEST_NAME_GLOB_ALLOWLIST))
629632
return -ENOMEM;
630633
break;
631634
}
632635
case ARG_TEST_NAME_GLOB_DENYLIST:
633636
case ARG_TEST_NAME_BLACKLIST: {
634-
char *subtest_str = strchr(arg, '/');
635-
636-
if (subtest_str) {
637-
*subtest_str = '\0';
638-
if (parse_str_list(subtest_str + 1,
639-
&env->subtest_selector.blacklist,
640-
key == ARG_TEST_NAME_GLOB_DENYLIST))
641-
return -ENOMEM;
642-
}
643-
if (parse_str_list(arg, &env->test_selector.blacklist,
644-
key == ARG_TEST_NAME_GLOB_DENYLIST))
637+
if (parse_test_list(arg,
638+
&env->test_selector.blacklist,
639+
key == ARG_TEST_NAME_GLOB_DENYLIST))
645640
return -ENOMEM;
646641
break;
647642
}
@@ -1493,12 +1488,8 @@ int main(int argc, char **argv)
14931488
out:
14941489
if (!env.list_test_names && env.has_testmod)
14951490
unload_bpf_testmod();
1496-
free_str_set(&env.test_selector.blacklist);
1497-
free_str_set(&env.test_selector.whitelist);
1498-
free(env.test_selector.num_set);
1499-
free_str_set(&env.subtest_selector.blacklist);
1500-
free_str_set(&env.subtest_selector.whitelist);
1501-
free(env.subtest_selector.num_set);
1491+
1492+
free_test_selector(&env.test_selector);
15021493

15031494
if (env.succ_cnt + env.fail_cnt + env.skip_cnt == 0)
15041495
return EXIT_NO_TEST;

tools/testing/selftests/bpf/test_progs.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ typedef __u16 __sum16;
3737
#include <bpf/bpf_endian.h>
3838
#include "trace_helpers.h"
3939
#include "testing_helpers.h"
40-
#include "flow_dissector_load.h"
4140

4241
enum verbosity {
4342
VERBOSE_NONE,
@@ -46,14 +45,21 @@ enum verbosity {
4645
VERBOSE_SUPER,
4746
};
4847

49-
struct str_set {
50-
const char **strs;
48+
struct prog_test {
49+
char *name;
50+
char **subtests;
51+
int subtest_cnt;
52+
bool whole_test;
53+
};
54+
55+
struct test_set {
56+
struct prog_test *tests;
5157
int cnt;
5258
};
5359

5460
struct test_selector {
55-
struct str_set whitelist;
56-
struct str_set blacklist;
61+
struct test_set whitelist;
62+
struct test_set blacklist;
5763
bool *num_set;
5864
int num_set_len;
5965
};

0 commit comments

Comments
 (0)