162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __TEST_PROGS_H
362306a36Sopenharmony_ci#define __TEST_PROGS_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <stdio.h>
662306a36Sopenharmony_ci#include <unistd.h>
762306a36Sopenharmony_ci#include <errno.h>
862306a36Sopenharmony_ci#include <string.h>
962306a36Sopenharmony_ci#include <assert.h>
1062306a36Sopenharmony_ci#include <stdlib.h>
1162306a36Sopenharmony_ci#include <stdarg.h>
1262306a36Sopenharmony_ci#include <time.h>
1362306a36Sopenharmony_ci#include <signal.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/types.h>
1662306a36Sopenharmony_citypedef __u16 __sum16;
1762306a36Sopenharmony_ci#include <arpa/inet.h>
1862306a36Sopenharmony_ci#include <linux/if_ether.h>
1962306a36Sopenharmony_ci#include <linux/if_packet.h>
2062306a36Sopenharmony_ci#include <linux/ip.h>
2162306a36Sopenharmony_ci#include <linux/ipv6.h>
2262306a36Sopenharmony_ci#include <linux/filter.h>
2362306a36Sopenharmony_ci#include <linux/perf_event.h>
2462306a36Sopenharmony_ci#include <linux/socket.h>
2562306a36Sopenharmony_ci#include <linux/unistd.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <sys/ioctl.h>
2862306a36Sopenharmony_ci#include <sys/wait.h>
2962306a36Sopenharmony_ci#include <sys/types.h>
3062306a36Sopenharmony_ci#include <sys/time.h>
3162306a36Sopenharmony_ci#include <sys/param.h>
3262306a36Sopenharmony_ci#include <fcntl.h>
3362306a36Sopenharmony_ci#include <pthread.h>
3462306a36Sopenharmony_ci#include <linux/bpf.h>
3562306a36Sopenharmony_ci#include <linux/err.h>
3662306a36Sopenharmony_ci#include <bpf/bpf.h>
3762306a36Sopenharmony_ci#include <bpf/libbpf.h>
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#include "test_iptunnel_common.h"
4062306a36Sopenharmony_ci#include "bpf_util.h"
4162306a36Sopenharmony_ci#include <bpf/bpf_endian.h>
4262306a36Sopenharmony_ci#include "trace_helpers.h"
4362306a36Sopenharmony_ci#include "testing_helpers.h"
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cienum verbosity {
4662306a36Sopenharmony_ci	VERBOSE_NONE,
4762306a36Sopenharmony_ci	VERBOSE_NORMAL,
4862306a36Sopenharmony_ci	VERBOSE_VERY,
4962306a36Sopenharmony_ci	VERBOSE_SUPER,
5062306a36Sopenharmony_ci};
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistruct test_filter {
5362306a36Sopenharmony_ci	char *name;
5462306a36Sopenharmony_ci	char **subtests;
5562306a36Sopenharmony_ci	int subtest_cnt;
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistruct test_filter_set {
5962306a36Sopenharmony_ci	struct test_filter *tests;
6062306a36Sopenharmony_ci	int cnt;
6162306a36Sopenharmony_ci};
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_cistruct test_selector {
6462306a36Sopenharmony_ci	struct test_filter_set whitelist;
6562306a36Sopenharmony_ci	struct test_filter_set blacklist;
6662306a36Sopenharmony_ci	bool *num_set;
6762306a36Sopenharmony_ci	int num_set_len;
6862306a36Sopenharmony_ci};
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistruct subtest_state {
7162306a36Sopenharmony_ci	char *name;
7262306a36Sopenharmony_ci	size_t log_cnt;
7362306a36Sopenharmony_ci	char *log_buf;
7462306a36Sopenharmony_ci	int error_cnt;
7562306a36Sopenharmony_ci	bool skipped;
7662306a36Sopenharmony_ci	bool filtered;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	FILE *stdout;
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistruct test_state {
8262306a36Sopenharmony_ci	bool tested;
8362306a36Sopenharmony_ci	bool force_log;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	int error_cnt;
8662306a36Sopenharmony_ci	int skip_cnt;
8762306a36Sopenharmony_ci	int sub_succ_cnt;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	struct subtest_state *subtest_states;
9062306a36Sopenharmony_ci	int subtest_num;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	size_t log_cnt;
9362306a36Sopenharmony_ci	char *log_buf;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	FILE *stdout;
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistruct test_env {
9962306a36Sopenharmony_ci	struct test_selector test_selector;
10062306a36Sopenharmony_ci	struct test_selector subtest_selector;
10162306a36Sopenharmony_ci	bool verifier_stats;
10262306a36Sopenharmony_ci	bool debug;
10362306a36Sopenharmony_ci	enum verbosity verbosity;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	bool jit_enabled;
10662306a36Sopenharmony_ci	bool has_testmod;
10762306a36Sopenharmony_ci	bool get_test_cnt;
10862306a36Sopenharmony_ci	bool list_test_names;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	struct prog_test_def *test; /* current running test */
11162306a36Sopenharmony_ci	struct test_state *test_state; /* current running test state */
11262306a36Sopenharmony_ci	struct subtest_state *subtest_state; /* current running subtest state */
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	FILE *stdout;
11562306a36Sopenharmony_ci	FILE *stderr;
11662306a36Sopenharmony_ci	int nr_cpus;
11762306a36Sopenharmony_ci	FILE *json;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	int succ_cnt; /* successful tests */
12062306a36Sopenharmony_ci	int sub_succ_cnt; /* successful sub-tests */
12162306a36Sopenharmony_ci	int fail_cnt; /* total failed tests + sub-tests */
12262306a36Sopenharmony_ci	int skip_cnt; /* skipped tests */
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	int saved_netns_fd;
12562306a36Sopenharmony_ci	int workers; /* number of worker process */
12662306a36Sopenharmony_ci	int worker_id; /* id number of current worker, main process is -1 */
12762306a36Sopenharmony_ci	pid_t *worker_pids; /* array of worker pids */
12862306a36Sopenharmony_ci	int *worker_socks; /* array of worker socks */
12962306a36Sopenharmony_ci	int *worker_current_test; /* array of current running test for each worker */
13062306a36Sopenharmony_ci};
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci#define MAX_LOG_TRUNK_SIZE 8192
13362306a36Sopenharmony_ci#define MAX_SUBTEST_NAME 1024
13462306a36Sopenharmony_cienum msg_type {
13562306a36Sopenharmony_ci	MSG_DO_TEST = 0,
13662306a36Sopenharmony_ci	MSG_TEST_DONE = 1,
13762306a36Sopenharmony_ci	MSG_TEST_LOG = 2,
13862306a36Sopenharmony_ci	MSG_SUBTEST_DONE = 3,
13962306a36Sopenharmony_ci	MSG_EXIT = 255,
14062306a36Sopenharmony_ci};
14162306a36Sopenharmony_cistruct msg {
14262306a36Sopenharmony_ci	enum msg_type type;
14362306a36Sopenharmony_ci	union {
14462306a36Sopenharmony_ci		struct {
14562306a36Sopenharmony_ci			int num;
14662306a36Sopenharmony_ci		} do_test;
14762306a36Sopenharmony_ci		struct {
14862306a36Sopenharmony_ci			int num;
14962306a36Sopenharmony_ci			int sub_succ_cnt;
15062306a36Sopenharmony_ci			int error_cnt;
15162306a36Sopenharmony_ci			int skip_cnt;
15262306a36Sopenharmony_ci			bool have_log;
15362306a36Sopenharmony_ci			int subtest_num;
15462306a36Sopenharmony_ci		} test_done;
15562306a36Sopenharmony_ci		struct {
15662306a36Sopenharmony_ci			char log_buf[MAX_LOG_TRUNK_SIZE + 1];
15762306a36Sopenharmony_ci			bool is_last;
15862306a36Sopenharmony_ci		} test_log;
15962306a36Sopenharmony_ci		struct {
16062306a36Sopenharmony_ci			int num;
16162306a36Sopenharmony_ci			char name[MAX_SUBTEST_NAME + 1];
16262306a36Sopenharmony_ci			int error_cnt;
16362306a36Sopenharmony_ci			bool skipped;
16462306a36Sopenharmony_ci			bool filtered;
16562306a36Sopenharmony_ci			bool have_log;
16662306a36Sopenharmony_ci		} subtest_done;
16762306a36Sopenharmony_ci	};
16862306a36Sopenharmony_ci};
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ciextern struct test_env env;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_civoid test__force_log(void);
17362306a36Sopenharmony_cibool test__start_subtest(const char *name);
17462306a36Sopenharmony_civoid test__end_subtest(void);
17562306a36Sopenharmony_civoid test__skip(void);
17662306a36Sopenharmony_civoid test__fail(void);
17762306a36Sopenharmony_ciint test__join_cgroup(const char *path);
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci#define PRINT_FAIL(format...)                                                  \
18062306a36Sopenharmony_ci	({                                                                     \
18162306a36Sopenharmony_ci		test__fail();                                                  \
18262306a36Sopenharmony_ci		fprintf(stdout, "%s:FAIL:%d ", __func__, __LINE__);            \
18362306a36Sopenharmony_ci		fprintf(stdout, ##format);                                     \
18462306a36Sopenharmony_ci	})
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci#define _CHECK(condition, tag, duration, format...) ({			\
18762306a36Sopenharmony_ci	int __ret = !!(condition);					\
18862306a36Sopenharmony_ci	int __save_errno = errno;					\
18962306a36Sopenharmony_ci	if (__ret) {							\
19062306a36Sopenharmony_ci		test__fail();						\
19162306a36Sopenharmony_ci		fprintf(stdout, "%s:FAIL:%s ", __func__, tag);		\
19262306a36Sopenharmony_ci		fprintf(stdout, ##format);				\
19362306a36Sopenharmony_ci	} else {							\
19462306a36Sopenharmony_ci		fprintf(stdout, "%s:PASS:%s %d nsec\n",			\
19562306a36Sopenharmony_ci		       __func__, tag, duration);			\
19662306a36Sopenharmony_ci	}								\
19762306a36Sopenharmony_ci	errno = __save_errno;						\
19862306a36Sopenharmony_ci	__ret;								\
19962306a36Sopenharmony_ci})
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci#define CHECK_FAIL(condition) ({					\
20262306a36Sopenharmony_ci	int __ret = !!(condition);					\
20362306a36Sopenharmony_ci	int __save_errno = errno;					\
20462306a36Sopenharmony_ci	if (__ret) {							\
20562306a36Sopenharmony_ci		test__fail();						\
20662306a36Sopenharmony_ci		fprintf(stdout, "%s:FAIL:%d\n", __func__, __LINE__);	\
20762306a36Sopenharmony_ci	}								\
20862306a36Sopenharmony_ci	errno = __save_errno;						\
20962306a36Sopenharmony_ci	__ret;								\
21062306a36Sopenharmony_ci})
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci#define CHECK(condition, tag, format...) \
21362306a36Sopenharmony_ci	_CHECK(condition, tag, duration, format)
21462306a36Sopenharmony_ci#define CHECK_ATTR(condition, tag, format...) \
21562306a36Sopenharmony_ci	_CHECK(condition, tag, tattr.duration, format)
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci#define ASSERT_FAIL(fmt, args...) ({					\
21862306a36Sopenharmony_ci	static int duration = 0;					\
21962306a36Sopenharmony_ci	CHECK(false, "", fmt"\n", ##args);				\
22062306a36Sopenharmony_ci	false;								\
22162306a36Sopenharmony_ci})
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci#define ASSERT_TRUE(actual, name) ({					\
22462306a36Sopenharmony_ci	static int duration = 0;					\
22562306a36Sopenharmony_ci	bool ___ok = (actual);						\
22662306a36Sopenharmony_ci	CHECK(!___ok, (name), "unexpected %s: got FALSE\n", (name));	\
22762306a36Sopenharmony_ci	___ok;								\
22862306a36Sopenharmony_ci})
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci#define ASSERT_FALSE(actual, name) ({					\
23162306a36Sopenharmony_ci	static int duration = 0;					\
23262306a36Sopenharmony_ci	bool ___ok = !(actual);						\
23362306a36Sopenharmony_ci	CHECK(!___ok, (name), "unexpected %s: got TRUE\n", (name));	\
23462306a36Sopenharmony_ci	___ok;								\
23562306a36Sopenharmony_ci})
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci#define ASSERT_EQ(actual, expected, name) ({				\
23862306a36Sopenharmony_ci	static int duration = 0;					\
23962306a36Sopenharmony_ci	typeof(actual) ___act = (actual);				\
24062306a36Sopenharmony_ci	typeof(expected) ___exp = (expected);				\
24162306a36Sopenharmony_ci	bool ___ok = ___act == ___exp;					\
24262306a36Sopenharmony_ci	CHECK(!___ok, (name),						\
24362306a36Sopenharmony_ci	      "unexpected %s: actual %lld != expected %lld\n",		\
24462306a36Sopenharmony_ci	      (name), (long long)(___act), (long long)(___exp));	\
24562306a36Sopenharmony_ci	___ok;								\
24662306a36Sopenharmony_ci})
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci#define ASSERT_NEQ(actual, expected, name) ({				\
24962306a36Sopenharmony_ci	static int duration = 0;					\
25062306a36Sopenharmony_ci	typeof(actual) ___act = (actual);				\
25162306a36Sopenharmony_ci	typeof(expected) ___exp = (expected);				\
25262306a36Sopenharmony_ci	bool ___ok = ___act != ___exp;					\
25362306a36Sopenharmony_ci	CHECK(!___ok, (name),						\
25462306a36Sopenharmony_ci	      "unexpected %s: actual %lld == expected %lld\n",		\
25562306a36Sopenharmony_ci	      (name), (long long)(___act), (long long)(___exp));	\
25662306a36Sopenharmony_ci	___ok;								\
25762306a36Sopenharmony_ci})
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci#define ASSERT_LT(actual, expected, name) ({				\
26062306a36Sopenharmony_ci	static int duration = 0;					\
26162306a36Sopenharmony_ci	typeof(actual) ___act = (actual);				\
26262306a36Sopenharmony_ci	typeof(expected) ___exp = (expected);				\
26362306a36Sopenharmony_ci	bool ___ok = ___act < ___exp;					\
26462306a36Sopenharmony_ci	CHECK(!___ok, (name),						\
26562306a36Sopenharmony_ci	      "unexpected %s: actual %lld >= expected %lld\n",		\
26662306a36Sopenharmony_ci	      (name), (long long)(___act), (long long)(___exp));	\
26762306a36Sopenharmony_ci	___ok;								\
26862306a36Sopenharmony_ci})
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci#define ASSERT_LE(actual, expected, name) ({				\
27162306a36Sopenharmony_ci	static int duration = 0;					\
27262306a36Sopenharmony_ci	typeof(actual) ___act = (actual);				\
27362306a36Sopenharmony_ci	typeof(expected) ___exp = (expected);				\
27462306a36Sopenharmony_ci	bool ___ok = ___act <= ___exp;					\
27562306a36Sopenharmony_ci	CHECK(!___ok, (name),						\
27662306a36Sopenharmony_ci	      "unexpected %s: actual %lld > expected %lld\n",		\
27762306a36Sopenharmony_ci	      (name), (long long)(___act), (long long)(___exp));	\
27862306a36Sopenharmony_ci	___ok;								\
27962306a36Sopenharmony_ci})
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci#define ASSERT_GT(actual, expected, name) ({				\
28262306a36Sopenharmony_ci	static int duration = 0;					\
28362306a36Sopenharmony_ci	typeof(actual) ___act = (actual);				\
28462306a36Sopenharmony_ci	typeof(expected) ___exp = (expected);				\
28562306a36Sopenharmony_ci	bool ___ok = ___act > ___exp;					\
28662306a36Sopenharmony_ci	CHECK(!___ok, (name),						\
28762306a36Sopenharmony_ci	      "unexpected %s: actual %lld <= expected %lld\n",		\
28862306a36Sopenharmony_ci	      (name), (long long)(___act), (long long)(___exp));	\
28962306a36Sopenharmony_ci	___ok;								\
29062306a36Sopenharmony_ci})
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci#define ASSERT_GE(actual, expected, name) ({				\
29362306a36Sopenharmony_ci	static int duration = 0;					\
29462306a36Sopenharmony_ci	typeof(actual) ___act = (actual);				\
29562306a36Sopenharmony_ci	typeof(expected) ___exp = (expected);				\
29662306a36Sopenharmony_ci	bool ___ok = ___act >= ___exp;					\
29762306a36Sopenharmony_ci	CHECK(!___ok, (name),						\
29862306a36Sopenharmony_ci	      "unexpected %s: actual %lld < expected %lld\n",		\
29962306a36Sopenharmony_ci	      (name), (long long)(___act), (long long)(___exp));	\
30062306a36Sopenharmony_ci	___ok;								\
30162306a36Sopenharmony_ci})
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci#define ASSERT_STREQ(actual, expected, name) ({				\
30462306a36Sopenharmony_ci	static int duration = 0;					\
30562306a36Sopenharmony_ci	const char *___act = actual;					\
30662306a36Sopenharmony_ci	const char *___exp = expected;					\
30762306a36Sopenharmony_ci	bool ___ok = strcmp(___act, ___exp) == 0;			\
30862306a36Sopenharmony_ci	CHECK(!___ok, (name),						\
30962306a36Sopenharmony_ci	      "unexpected %s: actual '%s' != expected '%s'\n",		\
31062306a36Sopenharmony_ci	      (name), ___act, ___exp);					\
31162306a36Sopenharmony_ci	___ok;								\
31262306a36Sopenharmony_ci})
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci#define ASSERT_STRNEQ(actual, expected, len, name) ({			\
31562306a36Sopenharmony_ci	static int duration = 0;					\
31662306a36Sopenharmony_ci	const char *___act = actual;					\
31762306a36Sopenharmony_ci	const char *___exp = expected;					\
31862306a36Sopenharmony_ci	int ___len = len;						\
31962306a36Sopenharmony_ci	bool ___ok = strncmp(___act, ___exp, ___len) == 0;		\
32062306a36Sopenharmony_ci	CHECK(!___ok, (name),						\
32162306a36Sopenharmony_ci	      "unexpected %s: actual '%.*s' != expected '%.*s'\n",	\
32262306a36Sopenharmony_ci	      (name), ___len, ___act, ___len, ___exp);			\
32362306a36Sopenharmony_ci	___ok;								\
32462306a36Sopenharmony_ci})
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci#define ASSERT_HAS_SUBSTR(str, substr, name) ({				\
32762306a36Sopenharmony_ci	static int duration = 0;					\
32862306a36Sopenharmony_ci	const char *___str = str;					\
32962306a36Sopenharmony_ci	const char *___substr = substr;					\
33062306a36Sopenharmony_ci	bool ___ok = strstr(___str, ___substr) != NULL;			\
33162306a36Sopenharmony_ci	CHECK(!___ok, (name),						\
33262306a36Sopenharmony_ci	      "unexpected %s: '%s' is not a substring of '%s'\n",	\
33362306a36Sopenharmony_ci	      (name), ___substr, ___str);				\
33462306a36Sopenharmony_ci	___ok;								\
33562306a36Sopenharmony_ci})
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci#define ASSERT_OK(res, name) ({						\
33862306a36Sopenharmony_ci	static int duration = 0;					\
33962306a36Sopenharmony_ci	long long ___res = (res);					\
34062306a36Sopenharmony_ci	bool ___ok = ___res == 0;					\
34162306a36Sopenharmony_ci	CHECK(!___ok, (name), "unexpected error: %lld (errno %d)\n",	\
34262306a36Sopenharmony_ci	      ___res, errno);						\
34362306a36Sopenharmony_ci	___ok;								\
34462306a36Sopenharmony_ci})
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci#define ASSERT_ERR(res, name) ({					\
34762306a36Sopenharmony_ci	static int duration = 0;					\
34862306a36Sopenharmony_ci	long long ___res = (res);					\
34962306a36Sopenharmony_ci	bool ___ok = ___res < 0;					\
35062306a36Sopenharmony_ci	CHECK(!___ok, (name), "unexpected success: %lld\n", ___res);	\
35162306a36Sopenharmony_ci	___ok;								\
35262306a36Sopenharmony_ci})
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci#define ASSERT_NULL(ptr, name) ({					\
35562306a36Sopenharmony_ci	static int duration = 0;					\
35662306a36Sopenharmony_ci	const void *___res = (ptr);					\
35762306a36Sopenharmony_ci	bool ___ok = !___res;						\
35862306a36Sopenharmony_ci	CHECK(!___ok, (name), "unexpected pointer: %p\n", ___res);	\
35962306a36Sopenharmony_ci	___ok;								\
36062306a36Sopenharmony_ci})
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci#define ASSERT_OK_PTR(ptr, name) ({					\
36362306a36Sopenharmony_ci	static int duration = 0;					\
36462306a36Sopenharmony_ci	const void *___res = (ptr);					\
36562306a36Sopenharmony_ci	int ___err = libbpf_get_error(___res);				\
36662306a36Sopenharmony_ci	bool ___ok = ___err == 0;					\
36762306a36Sopenharmony_ci	CHECK(!___ok, (name), "unexpected error: %d\n", ___err);	\
36862306a36Sopenharmony_ci	___ok;								\
36962306a36Sopenharmony_ci})
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci#define ASSERT_ERR_PTR(ptr, name) ({					\
37262306a36Sopenharmony_ci	static int duration = 0;					\
37362306a36Sopenharmony_ci	const void *___res = (ptr);					\
37462306a36Sopenharmony_ci	int ___err = libbpf_get_error(___res);				\
37562306a36Sopenharmony_ci	bool ___ok = ___err != 0;					\
37662306a36Sopenharmony_ci	CHECK(!___ok, (name), "unexpected pointer: %p\n", ___res);	\
37762306a36Sopenharmony_ci	___ok;								\
37862306a36Sopenharmony_ci})
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci#define SYS(goto_label, fmt, ...)					\
38162306a36Sopenharmony_ci	({								\
38262306a36Sopenharmony_ci		char cmd[1024];						\
38362306a36Sopenharmony_ci		snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__);		\
38462306a36Sopenharmony_ci		if (!ASSERT_OK(system(cmd), cmd))			\
38562306a36Sopenharmony_ci			goto goto_label;				\
38662306a36Sopenharmony_ci	})
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci#define SYS_NOFAIL(fmt, ...)						\
38962306a36Sopenharmony_ci	({								\
39062306a36Sopenharmony_ci		char cmd[1024];						\
39162306a36Sopenharmony_ci		snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__);		\
39262306a36Sopenharmony_ci		system(cmd);						\
39362306a36Sopenharmony_ci	})
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_cistatic inline __u64 ptr_to_u64(const void *ptr)
39662306a36Sopenharmony_ci{
39762306a36Sopenharmony_ci	return (__u64) (unsigned long) ptr;
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_cistatic inline void *u64_to_ptr(__u64 ptr)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	return (void *) (unsigned long) ptr;
40362306a36Sopenharmony_ci}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ciint bpf_find_map(const char *test, struct bpf_object *obj, const char *name);
40662306a36Sopenharmony_ciint compare_map_keys(int map1_fd, int map2_fd);
40762306a36Sopenharmony_ciint compare_stack_ips(int smap_fd, int amap_fd, int stack_trace_len);
40862306a36Sopenharmony_ciint trigger_module_test_read(int read_sz);
40962306a36Sopenharmony_ciint trigger_module_test_write(int write_sz);
41062306a36Sopenharmony_ciint write_sysctl(const char *sysctl, const char *value);
41162306a36Sopenharmony_ciint get_bpf_max_tramp_links_from(struct btf *btf);
41262306a36Sopenharmony_ciint get_bpf_max_tramp_links(void);
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci#ifdef __x86_64__
41562306a36Sopenharmony_ci#define SYS_NANOSLEEP_KPROBE_NAME "__x64_sys_nanosleep"
41662306a36Sopenharmony_ci#elif defined(__s390x__)
41762306a36Sopenharmony_ci#define SYS_NANOSLEEP_KPROBE_NAME "__s390x_sys_nanosleep"
41862306a36Sopenharmony_ci#elif defined(__aarch64__)
41962306a36Sopenharmony_ci#define SYS_NANOSLEEP_KPROBE_NAME "__arm64_sys_nanosleep"
42062306a36Sopenharmony_ci#elif defined(__riscv)
42162306a36Sopenharmony_ci#define SYS_NANOSLEEP_KPROBE_NAME "__riscv_sys_nanosleep"
42262306a36Sopenharmony_ci#else
42362306a36Sopenharmony_ci#define SYS_NANOSLEEP_KPROBE_NAME "sys_nanosleep"
42462306a36Sopenharmony_ci#endif
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci#define BPF_TESTMOD_TEST_FILE "/sys/kernel/bpf_testmod"
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_citypedef int (*pre_execution_cb)(struct bpf_object *obj);
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_cistruct test_loader {
43162306a36Sopenharmony_ci	char *log_buf;
43262306a36Sopenharmony_ci	size_t log_buf_sz;
43362306a36Sopenharmony_ci	size_t next_match_pos;
43462306a36Sopenharmony_ci	pre_execution_cb pre_execution_cb;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	struct bpf_object *obj;
43762306a36Sopenharmony_ci};
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic inline void test_loader__set_pre_execution_cb(struct test_loader *tester,
44062306a36Sopenharmony_ci						     pre_execution_cb cb)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	tester->pre_execution_cb = cb;
44362306a36Sopenharmony_ci}
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_citypedef const void *(*skel_elf_bytes_fn)(size_t *sz);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ciextern void test_loader__run_subtests(struct test_loader *tester,
44862306a36Sopenharmony_ci				      const char *skel_name,
44962306a36Sopenharmony_ci				      skel_elf_bytes_fn elf_bytes_factory);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ciextern void test_loader_fini(struct test_loader *tester);
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci#define RUN_TESTS(skel) ({						       \
45462306a36Sopenharmony_ci	struct test_loader tester = {};					       \
45562306a36Sopenharmony_ci									       \
45662306a36Sopenharmony_ci	test_loader__run_subtests(&tester, #skel, skel##__elf_bytes);	       \
45762306a36Sopenharmony_ci	test_loader_fini(&tester);					       \
45862306a36Sopenharmony_ci})
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci#endif /* __TEST_PROGS_H */
461