Commit 47a92ae0 authored by Alexei Starovoitov's avatar Alexei Starovoitov

Merge branch 'cleanup-selftests-bpf-makefile'

Andrii Nakryiko says:

====================
This patch set extensively revamps selftests/bpf's Makefile to generalize test
runner concept and apply it uniformly to test_maps and test_progs test
runners, along with test_progs' few build "flavors", exercising various ways
to build BPF programs.

As we do that, we fix dependencies between various phases of test runners, and
simplify some one-off rules and dependencies currently present in Makefile.
test_progs' flavors are now built into root $(OUTPUT) directory and can be run
without any extra steps right from there. E.g., test_progs-alu32 is built and
is supposed to be run from $(OUTPUT). It will cd into alu32/ subdirectory to
load correct set of BPF object files (which are different from the ones built
for test_progs).

Outline:
- patch #1 teaches test_progs about flavor sub-directories;
- patch #2 fixes one of CO-RE tests to not depend strictly on process name;
- patch #3 changes test_maps's usage of map_tests/tests.h to be the same as
  test_progs' one;
- patch #4 adds convenient short `make test_progs`-like targets to build only
  individual tests, if necessary;
- patch #5 is a main patch in the series; it uses a bunch of make magic
  (mainly $(call) and $(eval)) to define test runner "skeleton" and apply it
  to 4 different test runners, lots more details in corresponding commit
  description;
- patch #6 does a bit of post-clean up for test_queue_map and test_stack_map
  BPF programs;
- patch #7 cleans up test_libbpf.sh/test_libbpf_open superseded by test_progs.

v3->v4:
- remove accidentally checked in binaries;

v2->v3:
- drop test_xdp.o mixed compilation mode, remove test_libbpf.sh (Alexei);

v1->v2:
- drop test_progs-native causing compilation failures due to
  __builtin_preserve_field_access, add back test_xdp.o override, which will
  now emit rule re-definition warning.
====================
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parents 8d285a3b cb79a4e1
...@@ -7,11 +7,10 @@ FEATURE-DUMP.libbpf ...@@ -7,11 +7,10 @@ FEATURE-DUMP.libbpf
fixdep fixdep
test_align test_align
test_dev_cgroup test_dev_cgroup
test_progs /test_progs*
test_tcpbpf_user test_tcpbpf_user
test_verifier_log test_verifier_log
feature feature
test_libbpf_open
test_sock test_sock
test_sock_addr test_sock_addr
test_sock_fields test_sock_fields
...@@ -33,9 +32,10 @@ test_tcpnotify_user ...@@ -33,9 +32,10 @@ test_tcpnotify_user
test_libbpf test_libbpf
test_tcp_check_syncookie_user test_tcp_check_syncookie_user
test_sysctl test_sysctl
alu32
libbpf.pc libbpf.pc
libbpf.so.* libbpf.so.*
test_hashmap test_hashmap
test_btf_dump test_btf_dump
xdping xdping
/alu32
/bpf_gcc
This diff is collapsed.
...@@ -211,8 +211,8 @@ static struct core_reloc_test_case test_cases[] = { ...@@ -211,8 +211,8 @@ static struct core_reloc_test_case test_cases[] = {
.input_len = 0, .input_len = 0,
.output = STRUCT_TO_CHAR_PTR(core_reloc_kernel_output) { .output = STRUCT_TO_CHAR_PTR(core_reloc_kernel_output) {
.valid = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }, .valid = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
.comm = "test_progs\0\0\0\0\0", .comm = "test_progs",
.comm_len = 11, .comm_len = sizeof("test_progs"),
}, },
.output_len = sizeof(struct core_reloc_kernel_output), .output_len = sizeof(struct core_reloc_kernel_output),
}, },
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
struct core_reloc_kernel_output { struct core_reloc_kernel_output {
int valid[10]; int valid[10];
char comm[16]; char comm[sizeof("test_progs")];
int comm_len; int comm_len;
}; };
......
...@@ -15,7 +15,8 @@ static volatile struct data { ...@@ -15,7 +15,8 @@ static volatile struct data {
struct core_reloc_kernel_output { struct core_reloc_kernel_output {
int valid[10]; int valid[10];
char comm[16]; /* we have test_progs[-flavor], so cut flavor part */
char comm[sizeof("test_progs")];
int comm_len; int comm_len;
}; };
......
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
export TESTNAME=test_libbpf
# Determine selftest success via shell exit code
exit_handler()
{
if [ $? -eq 0 ]; then
echo "selftests: $TESTNAME [PASS]";
else
echo "$TESTNAME: failed at file $LAST_LOADED" 1>&2
echo "selftests: $TESTNAME [FAILED]";
fi
}
libbpf_open_file()
{
LAST_LOADED=$1
if [ -n "$VERBOSE" ]; then
./test_libbpf_open $1
else
./test_libbpf_open --quiet $1
fi
}
# Exit script immediately (well catched by trap handler) if any
# program/thing exits with a non-zero status.
set -e
# (Use 'trap -l' to list meaning of numbers)
trap exit_handler 0 2 3 6 9
libbpf_open_file test_l4lb.o
# Load a program with BPF-to-BPF calls
libbpf_open_file test_l4lb_noinline.o
# Load a program compiled without the "-target bpf" flag
libbpf_open_file test_xdp.o
# Success
exit 0
/* SPDX-License-Identifier: GPL-2.0
* Copyright (c) 2018 Jesper Dangaard Brouer, Red Hat Inc.
*/
static const char *__doc__ =
"Libbpf test program for loading BPF ELF object files";
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <bpf/libbpf.h>
#include <getopt.h>
#include "bpf_rlimit.h"
static const struct option long_options[] = {
{"help", no_argument, NULL, 'h' },
{"debug", no_argument, NULL, 'D' },
{"quiet", no_argument, NULL, 'q' },
{0, 0, NULL, 0 }
};
static void usage(char *argv[])
{
int i;
printf("\nDOCUMENTATION:\n%s\n\n", __doc__);
printf(" Usage: %s (options-see-below) BPF_FILE\n", argv[0]);
printf(" Listing options:\n");
for (i = 0; long_options[i].name != 0; i++) {
printf(" --%-12s", long_options[i].name);
printf(" short-option: -%c",
long_options[i].val);
printf("\n");
}
printf("\n");
}
static bool debug = 0;
static int libbpf_debug_print(enum libbpf_print_level level,
const char *fmt, va_list args)
{
if (level == LIBBPF_DEBUG && !debug)
return 0;
fprintf(stderr, "[%d] ", level);
return vfprintf(stderr, fmt, args);
}
#define EXIT_FAIL_LIBBPF EXIT_FAILURE
#define EXIT_FAIL_OPTION 2
int test_walk_progs(struct bpf_object *obj, bool verbose)
{
struct bpf_program *prog;
int cnt = 0;
bpf_object__for_each_program(prog, obj) {
cnt++;
if (verbose)
printf("Prog (count:%d) section_name: %s\n", cnt,
bpf_program__title(prog, false));
}
return 0;
}
int test_walk_maps(struct bpf_object *obj, bool verbose)
{
struct bpf_map *map;
int cnt = 0;
bpf_object__for_each_map(map, obj) {
cnt++;
if (verbose)
printf("Map (count:%d) name: %s\n", cnt,
bpf_map__name(map));
}
return 0;
}
int test_open_file(char *filename, bool verbose)
{
struct bpf_object *bpfobj = NULL;
long err;
if (verbose)
printf("Open BPF ELF-file with libbpf: %s\n", filename);
/* Load BPF ELF object file and check for errors */
bpfobj = bpf_object__open(filename);
err = libbpf_get_error(bpfobj);
if (err) {
char err_buf[128];
libbpf_strerror(err, err_buf, sizeof(err_buf));
if (verbose)
printf("Unable to load eBPF objects in file '%s': %s\n",
filename, err_buf);
return EXIT_FAIL_LIBBPF;
}
test_walk_progs(bpfobj, verbose);
test_walk_maps(bpfobj, verbose);
if (verbose)
printf("Close BPF ELF-file with libbpf: %s\n",
bpf_object__name(bpfobj));
bpf_object__close(bpfobj);
return 0;
}
int main(int argc, char **argv)
{
char filename[1024] = { 0 };
bool verbose = 1;
int longindex = 0;
int opt;
libbpf_set_print(libbpf_debug_print);
/* Parse commands line args */
while ((opt = getopt_long(argc, argv, "hDq",
long_options, &longindex)) != -1) {
switch (opt) {
case 'D':
debug = 1;
break;
case 'q': /* Use in scripting mode */
verbose = 0;
break;
case 'h':
default:
usage(argv);
return EXIT_FAIL_OPTION;
}
}
if (optind >= argc) {
usage(argv);
printf("ERROR: Expected BPF_FILE argument after options\n");
return EXIT_FAIL_OPTION;
}
snprintf(filename, sizeof(filename), "%s", argv[optind]);
return test_open_file(filename, verbose);
}
...@@ -1717,9 +1717,9 @@ static void run_all_tests(void) ...@@ -1717,9 +1717,9 @@ static void run_all_tests(void)
test_map_in_map(); test_map_in_map();
} }
#define DECLARE #define DEFINE_TEST(name) extern void test_##name(void);
#include <map_tests/tests.h> #include <map_tests/tests.h>
#undef DECLARE #undef DEFINE_TEST
int main(void) int main(void)
{ {
...@@ -1731,9 +1731,9 @@ int main(void) ...@@ -1731,9 +1731,9 @@ int main(void)
map_flags = BPF_F_NO_PREALLOC; map_flags = BPF_F_NO_PREALLOC;
run_all_tests(); run_all_tests();
#define CALL #define DEFINE_TEST(name) test_##name();
#include <map_tests/tests.h> #include <map_tests/tests.h>
#undef CALL #undef DEFINE_TEST
printf("test_maps: OK, %d SKIPPED\n", skips); printf("test_maps: OK, %d SKIPPED\n", skips);
return 0; return 0;
......
...@@ -306,7 +306,7 @@ void *spin_lock_thread(void *arg) ...@@ -306,7 +306,7 @@ void *spin_lock_thread(void *arg)
} }
/* extern declarations for test funcs */ /* extern declarations for test funcs */
#define DEFINE_TEST(name) extern void test_##name(); #define DEFINE_TEST(name) extern void test_##name(void);
#include <prog_tests/tests.h> #include <prog_tests/tests.h>
#undef DEFINE_TEST #undef DEFINE_TEST
...@@ -518,6 +518,33 @@ static void stdio_restore(void) ...@@ -518,6 +518,33 @@ static void stdio_restore(void)
#endif #endif
} }
/*
* Determine if test_progs is running as a "flavored" test runner and switch
* into corresponding sub-directory to load correct BPF objects.
*
* This is done by looking at executable name. If it contains "-flavor"
* suffix, then we are running as a flavored test runner.
*/
int cd_flavor_subdir(const char *exec_name)
{
/* General form of argv[0] passed here is:
* some/path/to/test_progs[-flavor], where -flavor part is optional.
* First cut out "test_progs[-flavor]" part, then extract "flavor"
* part, if it's there.
*/
const char *flavor = strrchr(exec_name, '/');
if (!flavor)
return 0;
flavor++;
flavor = strrchr(flavor, '-');
if (!flavor)
return 0;
flavor++;
printf("Switching to flavor '%s' subdirectory...\n", flavor);
return chdir(flavor);
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
static const struct argp argp = { static const struct argp argp = {
...@@ -531,6 +558,10 @@ int main(int argc, char **argv) ...@@ -531,6 +558,10 @@ int main(int argc, char **argv)
if (err) if (err)
return err; return err;
err = cd_flavor_subdir(argv[0]);
if (err)
return err;
libbpf_set_print(libbpf_print_fn); libbpf_set_print(libbpf_print_fn);
srand(time(NULL)); srand(time(NULL));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment