Commit 475e31f8 authored by Alexei Starovoitov's avatar Alexei Starovoitov
Browse files

Merge branch 'revamp-test_progs'



Andrii Nakryiko says:

====================
This patch set makes a number of changes to test_progs selftest, which is
a collection of many other tests (and sometimes sub-tests as well), to provide
better testing experience and allow to start convering many individual test
programs under selftests/bpf into a single and convenient test runner.

Patch #1 fixes issue with Makefile, which makes prog_tests/test.h compiled as
a C code. This fix allows to change how test.h is generated, providing ability
to have more control on what and how tests are run.

Patch #2 changes how test.h is auto-generated, which allows to have test
definitions, instead of just running test functions. This gives ability to do
more complicated test run policies.

Patch #3 adds `-t <test-name>` and `-n <test-num>` selectors to run only
subset of tests.

Patch #4 changes libbpf_set_print() to return previously set print callback,
allowing to temporarily replace current print callback and then set it back.
This is necessary for some tests that want more control over libbpf logging.

Patch #5 sets up and takes over libbpf logging from individual tests to
test_prog runner, adding -vv verbosity to capture debug output from libbpf.
This is useful when debugging failing tests.

Patch #6 furthers test output management and buffers it by default, emitting
log output only if test fails. This give succinct and clean default test
output. It's possible to bypass this behavior with -v flag, which will turn
off test output buffering.

Patch #7 adds support for sub-tests. It also enhances -t and -n selectors to
both support ability to specify sub-test selectors, as well as enhancing
number selector to accept sets of test, instead of just individual test
number.

Patch #8 converts bpf_verif_scale.c test to use sub-test APIs.

Patch #9 converts send_signal.c tests to use sub-test APIs.

v2->v3:
  - fix buffered output rare unitialized value bug (Alexei);
  - fix buffered output va_list reuse bug (Alexei);
  - fix buffered output truncation due to interleaving zero terminators;

v1->v2:
  - drop libbpf_swap_print, instead return previous function from
    libbpf_set_print (Stanislav);
====================

Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 943e398d b207edfe
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -74,9 +74,12 @@ static int __base_pr(enum libbpf_print_level level, const char *format,

static libbpf_print_fn_t __libbpf_pr = __base_pr;

void libbpf_set_print(libbpf_print_fn_t fn)
libbpf_print_fn_t libbpf_set_print(libbpf_print_fn_t fn)
{
	libbpf_print_fn_t old_print_fn = __libbpf_pr;

	__libbpf_pr = fn;
	return old_print_fn;
}

__printf(2, 3)
+1 −1
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ enum libbpf_print_level {
typedef int (*libbpf_print_fn_t)(enum libbpf_print_level level,
				 const char *, va_list ap);

LIBBPF_API void libbpf_set_print(libbpf_print_fn_t fn);
LIBBPF_API libbpf_print_fn_t libbpf_set_print(libbpf_print_fn_t fn);

/* Hide internal to user */
struct bpf_object;
+4 −10
Original line number Diff line number Diff line
@@ -235,18 +235,12 @@ PROG_TESTS_H := $(PROG_TESTS_DIR)/tests.h
PROG_TESTS_FILES := $(wildcard prog_tests/*.c)
test_progs.c: $(PROG_TESTS_H)
$(OUTPUT)/test_progs: CFLAGS += $(TEST_PROGS_CFLAGS)
$(OUTPUT)/test_progs: test_progs.c $(PROG_TESTS_H) $(PROG_TESTS_FILES)
$(OUTPUT)/test_progs: test_progs.c $(PROG_TESTS_FILES) | $(PROG_TESTS_H)
$(PROG_TESTS_H): $(PROG_TESTS_FILES) | $(PROG_TESTS_DIR)
	$(shell ( cd prog_tests/; \
		  echo '/* Generated header, do not edit */'; \
		  echo '#ifdef DECLARE'; \
		  ls *.c 2> /dev/null | \
			sed -e 's@\([^\.]*\)\.c@extern void test_\1(void);@'; \
		  echo '#endif'; \
		  echo '#ifdef CALL'; \
		  ls *.c 2> /dev/null | \
			sed -e 's@\([^\.]*\)\.c@test_\1();@'; \
		  echo '#endif' \
			sed -e 's@\([^\.]*\)\.c@DEFINE_TEST(\1)@'; \
		 ) > $(PROG_TESTS_H))

MAP_TESTS_DIR = $(OUTPUT)/map_tests
@@ -256,7 +250,7 @@ MAP_TESTS_H := $(MAP_TESTS_DIR)/tests.h
MAP_TESTS_FILES := $(wildcard map_tests/*.c)
test_maps.c: $(MAP_TESTS_H)
$(OUTPUT)/test_maps: CFLAGS += $(TEST_MAPS_CFLAGS)
$(OUTPUT)/test_maps: test_maps.c $(MAP_TESTS_H) $(MAP_TESTS_FILES)
$(OUTPUT)/test_maps: test_maps.c $(MAP_TESTS_FILES) | $(MAP_TESTS_H)
$(MAP_TESTS_H): $(MAP_TESTS_FILES) | $(MAP_TESTS_DIR)
	$(shell ( cd map_tests/; \
		  echo '/* Generated header, do not edit */'; \
@@ -277,7 +271,7 @@ VERIFIER_TESTS_H := $(VERIFIER_TESTS_DIR)/tests.h
VERIFIER_TEST_FILES := $(wildcard verifier/*.c)
test_verifier.c: $(VERIFIER_TESTS_H)
$(OUTPUT)/test_verifier: CFLAGS += $(TEST_VERIFIER_CFLAGS)
$(OUTPUT)/test_verifier: test_verifier.c $(VERIFIER_TESTS_H)
$(OUTPUT)/test_verifier: test_verifier.c | $(VERIFIER_TEST_FILES) $(VERIFIER_TESTS_H)
$(VERIFIER_TESTS_H): $(VERIFIER_TEST_FILES) | $(VERIFIER_TESTS_DIR)
	$(shell ( cd verifier/; \
		  echo '/* Generated header, do not edit */'; \
+3 −3
Original line number Diff line number Diff line
@@ -106,8 +106,8 @@ void test_bpf_obj_id(void)
		if (CHECK(err ||
			  prog_infos[i].type != BPF_PROG_TYPE_SOCKET_FILTER ||
			  info_len != sizeof(struct bpf_prog_info) ||
			  (jit_enabled && !prog_infos[i].jited_prog_len) ||
			  (jit_enabled &&
			  (env.jit_enabled && !prog_infos[i].jited_prog_len) ||
			  (env.jit_enabled &&
			   !memcmp(jited_insns, zeros, sizeof(zeros))) ||
			  !prog_infos[i].xlated_prog_len ||
			  !memcmp(xlated_insns, zeros, sizeof(zeros)) ||
@@ -121,7 +121,7 @@ void test_bpf_obj_id(void)
			  err, errno, i,
			  prog_infos[i].type, BPF_PROG_TYPE_SOCKET_FILTER,
			  info_len, sizeof(struct bpf_prog_info),
			  jit_enabled,
			  env.jit_enabled,
			  prog_infos[i].jited_prog_len,
			  prog_infos[i].xlated_prog_len,
			  !!memcmp(jited_insns, zeros, sizeof(zeros)),
+53 −37
Original line number Diff line number Diff line
@@ -4,12 +4,15 @@
static int libbpf_debug_print(enum libbpf_print_level level,
			      const char *format, va_list args)
{
	if (level != LIBBPF_DEBUG)
		return vfprintf(stderr, format, args);
	if (level != LIBBPF_DEBUG) {
		test__vprintf(format, args);
		return 0;
	}

	if (!strstr(format, "verifier log"))
		return 0;
	return vfprintf(stderr, "%s", args);
	test__vprintf("%s", args);
	return 0;
}

static int check_load(const char *file, enum bpf_prog_type type)
@@ -30,14 +33,25 @@ static int check_load(const char *file, enum bpf_prog_type type)
	return err;
}

struct scale_test_def {
	const char *file;
	enum bpf_prog_type attach_type;
	bool fails;
};

void test_bpf_verif_scale(void)
{
	const char *sched_cls[] = {
		"./test_verif_scale1.o", "./test_verif_scale2.o", "./test_verif_scale3.o",
	};
	const char *raw_tp[] = {
	struct scale_test_def tests[] = {
		{ "loop3.o", BPF_PROG_TYPE_RAW_TRACEPOINT, true /* fails */ },

		{ "test_verif_scale1.o", BPF_PROG_TYPE_SCHED_CLS },
		{ "test_verif_scale2.o", BPF_PROG_TYPE_SCHED_CLS },
		{ "test_verif_scale3.o", BPF_PROG_TYPE_SCHED_CLS },

		/* full unroll by llvm */
		"./pyperf50.o",	"./pyperf100.o", "./pyperf180.o",
		{ "pyperf50.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
		{ "pyperf100.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
		{ "pyperf180.o", BPF_PROG_TYPE_RAW_TRACEPOINT },

		/* partial unroll. llvm will unroll loop ~150 times.
		 * C loop count -> 600.
@@ -45,7 +59,7 @@ void test_bpf_verif_scale(void)
		 * 16k insns in loop body.
		 * Total of 5 such loops. Total program size ~82k insns.
		 */
		"./pyperf600.o",
		{ "pyperf600.o", BPF_PROG_TYPE_RAW_TRACEPOINT },

		/* no unroll at all.
		 * C loop count -> 600.
@@ -53,48 +67,50 @@ void test_bpf_verif_scale(void)
		 * ~110 insns in loop body.
		 * Total of 5 such loops. Total program size ~1500 insns.
		 */
		"./pyperf600_nounroll.o",
		{ "pyperf600_nounroll.o", BPF_PROG_TYPE_RAW_TRACEPOINT },

		"./loop1.o", "./loop2.o",
		{ "loop1.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
		{ "loop2.o", BPF_PROG_TYPE_RAW_TRACEPOINT },

		/* partial unroll. 19k insn in a loop.
		 * Total program size 20.8k insn.
		 * ~350k processed_insns
		 */
		"./strobemeta.o",
		{ "strobemeta.o", BPF_PROG_TYPE_RAW_TRACEPOINT },

		/* no unroll, tiny loops */
		"./strobemeta_nounroll1.o",
		"./strobemeta_nounroll2.o",
	};
	const char *cg_sysctl[] = {
		"./test_sysctl_loop1.o", "./test_sysctl_loop2.o",
		{ "strobemeta_nounroll1.o", BPF_PROG_TYPE_RAW_TRACEPOINT },
		{ "strobemeta_nounroll2.o", BPF_PROG_TYPE_RAW_TRACEPOINT },

		{ "test_sysctl_loop1.o", BPF_PROG_TYPE_CGROUP_SYSCTL },
		{ "test_sysctl_loop2.o", BPF_PROG_TYPE_CGROUP_SYSCTL },

		{ "test_xdp_loop.o", BPF_PROG_TYPE_XDP },
		{ "test_seg6_loop.o", BPF_PROG_TYPE_LWT_SEG6LOCAL },
	};
	libbpf_print_fn_t old_print_fn = NULL;
	int err, i;

	if (verifier_stats)
		libbpf_set_print(libbpf_debug_print);
	if (env.verifier_stats) {
		test__force_log();
		old_print_fn = libbpf_set_print(libbpf_debug_print);
	}

	err = check_load("./loop3.o", BPF_PROG_TYPE_RAW_TRACEPOINT);
	printf("test_scale:loop3:%s\n", err ? (error_cnt--, "OK") : "FAIL");
	for (i = 0; i < ARRAY_SIZE(tests); i++) {
		const struct scale_test_def *test = &tests[i];

	for (i = 0; i < ARRAY_SIZE(sched_cls); i++) {
		err = check_load(sched_cls[i], BPF_PROG_TYPE_SCHED_CLS);
		printf("test_scale:%s:%s\n", sched_cls[i], err ? "FAIL" : "OK");
	}
		if (!test__start_subtest(test->file))
			continue;

	for (i = 0; i < ARRAY_SIZE(raw_tp); i++) {
		err = check_load(raw_tp[i], BPF_PROG_TYPE_RAW_TRACEPOINT);
		printf("test_scale:%s:%s\n", raw_tp[i], err ? "FAIL" : "OK");
		err = check_load(test->file, test->attach_type);
		if (test->fails) { /* expected to fail */
			if (err)
				error_cnt--;
			else
				error_cnt++;
		}

	for (i = 0; i < ARRAY_SIZE(cg_sysctl); i++) {
		err = check_load(cg_sysctl[i], BPF_PROG_TYPE_CGROUP_SYSCTL);
		printf("test_scale:%s:%s\n", cg_sysctl[i], err ? "FAIL" : "OK");
	}
	err = check_load("./test_xdp_loop.o", BPF_PROG_TYPE_XDP);
	printf("test_scale:test_xdp_loop:%s\n", err ? "FAIL" : "OK");

	err = check_load("./test_seg6_loop.o", BPF_PROG_TYPE_LWT_SEG6LOCAL);
	printf("test_scale:test_seg6_loop:%s\n", err ? "FAIL" : "OK");
	if (env.verifier_stats)
		libbpf_set_print(old_print_fn);
}
Loading