diff options
author | Ingo Molnar <mingo@kernel.org> | 2019-12-25 10:41:37 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2019-12-25 10:41:37 +0100 |
commit | 1e5f8a308551b9816588e12bb795aeadebe37c4a (patch) | |
tree | bd71fc796fed24a3b7cc99df4a1d1bdaecc2b387 /tools/testing | |
parent | stop_machine: remove try_stop_cpus helper (diff) | |
parent | Linux 5.5-rc3 (diff) | |
download | linux-1e5f8a308551b9816588e12bb795aeadebe37c4a.tar.xz linux-1e5f8a308551b9816588e12bb795aeadebe37c4a.zip |
Merge tag 'v5.5-rc3' into sched/core, to pick up fixes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/testing')
47 files changed, 3910 insertions, 306 deletions
diff --git a/tools/testing/kunit/kunit_tool_test.py b/tools/testing/kunit/kunit_tool_test.py index 4a12baa0cd4e..a2a8ea6beae3 100755 --- a/tools/testing/kunit/kunit_tool_test.py +++ b/tools/testing/kunit/kunit_tool_test.py @@ -199,7 +199,7 @@ class KUnitMainTest(unittest.TestCase): timeout = 3453 kunit.main(['run', '--timeout', str(timeout)], self.linux_source_mock) assert self.linux_source_mock.build_reconfig.call_count == 1 - self.linux_source_mock.run_kernel.assert_called_once_with(timeout=timeout) + self.linux_source_mock.run_kernel.assert_called_once_with(build_dir=None, timeout=timeout) self.print_mock.assert_any_call(StrContains('Testing complete.')) if __name__ == '__main__': diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild index c4a9196d794c..6aca8d5be159 100644 --- a/tools/testing/nvdimm/Kbuild +++ b/tools/testing/nvdimm/Kbuild @@ -5,6 +5,7 @@ ldflags-y += --wrap=devm_ioremap_nocache ldflags-y += --wrap=devm_memremap ldflags-y += --wrap=devm_memunmap ldflags-y += --wrap=ioremap_nocache +ldflags-y += --wrap=ioremap ldflags-y += --wrap=iounmap ldflags-y += --wrap=memunmap ldflags-y += --wrap=__devm_request_region diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c index 3f55f2f99112..6271ac757a4b 100644 --- a/tools/testing/nvdimm/test/iomap.c +++ b/tools/testing/nvdimm/test/iomap.c @@ -193,6 +193,12 @@ void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size) } EXPORT_SYMBOL(__wrap_ioremap_nocache); +void __iomem *__wrap_ioremap(resource_size_t offset, unsigned long size) +{ + return __nfit_test_ioremap(offset, size, ioremap); +} +EXPORT_SYMBOL(__wrap_ioremap); + void __iomem *__wrap_ioremap_wc(resource_size_t offset, unsigned long size) { return __nfit_test_ioremap(offset, size, ioremap_wc); diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile index d67f968eac21..b001c602414b 100644 --- a/tools/testing/selftests/Makefile +++ b/tools/testing/selftests/Makefile @@ -13,6 +13,7 @@ TARGETS += efivarfs TARGETS += exec TARGETS += filesystems TARGETS += filesystems/binderfs +TARGETS += filesystems/epoll TARGETS += firmware TARGETS += ftrace TARGETS += futex diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore index 4865116b96c7..419652458da4 100644 --- a/tools/testing/selftests/bpf/.gitignore +++ b/tools/testing/selftests/bpf/.gitignore @@ -37,5 +37,6 @@ libbpf.so.* test_hashmap test_btf_dump xdping +test_cpp /no_alu32 /bpf_gcc diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 085678d88ef8..e0fe01d9ec33 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -71,7 +71,7 @@ TEST_PROGS_EXTENDED := with_addr.sh \ # Compile but not part of 'make run_tests' TEST_GEN_PROGS_EXTENDED = test_sock_addr test_skb_cgroup_id_user \ flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user \ - test_lirc_mode2_user xdping + test_lirc_mode2_user xdping test_cpp TEST_CUSTOM_PROGS = urandom_read @@ -317,6 +317,10 @@ verifier/tests.h: verifier/*.c $(OUTPUT)/test_verifier: test_verifier.c verifier/tests.h $(BPFOBJ) | $(OUTPUT) $(CC) $(CFLAGS) $(filter %.a %.o %.c,$^) $(LDLIBS) -o $@ +# Make sure we are able to include and link libbpf against c++. +$(OUTPUT)/test_cpp: test_cpp.cpp $(BPFOBJ) + $(CXX) $(CFLAGS) $^ $(LDLIBS) -o $@ + EXTRA_CLEAN := $(TEST_CUSTOM_PROGS) \ prog_tests/tests.h map_tests/tests.h verifier/tests.h \ feature $(OUTPUT)/*.o $(OUTPUT)/no_alu32 $(OUTPUT)/bpf_gcc diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c index 15c7378362dd..b426bf2f97e4 100644 --- a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c +++ b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c @@ -2,25 +2,21 @@ /* Copyright (c) 2019 Facebook */ #include <test_progs.h> -#define PROG_CNT 3 - -void test_fexit_bpf2bpf(void) +static void test_fexit_bpf2bpf_common(const char *obj_file, + const char *target_obj_file, + int prog_cnt, + const char **prog_name) { - const char *prog_name[PROG_CNT] = { - "fexit/test_pkt_access", - "fexit/test_pkt_access_subprog1", - "fexit/test_pkt_access_subprog2", - }; struct bpf_object *obj = NULL, *pkt_obj; int err, pkt_fd, i; - struct bpf_link *link[PROG_CNT] = {}; - struct bpf_program *prog[PROG_CNT]; + struct bpf_link **link = NULL; + struct bpf_program **prog = NULL; __u32 duration, retval; struct bpf_map *data_map; const int zero = 0; - u64 result[PROG_CNT]; + u64 *result = NULL; - err = bpf_prog_load("./test_pkt_access.o", BPF_PROG_TYPE_UNSPEC, + err = bpf_prog_load(target_obj_file, BPF_PROG_TYPE_UNSPEC, &pkt_obj, &pkt_fd); if (CHECK(err, "prog_load sched cls", "err %d errno %d\n", err, errno)) return; @@ -28,7 +24,14 @@ void test_fexit_bpf2bpf(void) .attach_prog_fd = pkt_fd, ); - obj = bpf_object__open_file("./fexit_bpf2bpf.o", &opts); + link = calloc(sizeof(struct bpf_link *), prog_cnt); + prog = calloc(sizeof(struct bpf_program *), prog_cnt); + result = malloc(prog_cnt * sizeof(u64)); + if (CHECK(!link || !prog || !result, "alloc_memory", + "failed to alloc memory")) + goto close_prog; + + obj = bpf_object__open_file(obj_file, &opts); if (CHECK(IS_ERR_OR_NULL(obj), "obj_open", "failed to open fexit_bpf2bpf: %ld\n", PTR_ERR(obj))) @@ -38,7 +41,7 @@ void test_fexit_bpf2bpf(void) if (CHECK(err, "obj_load", "err %d\n", err)) goto close_prog; - for (i = 0; i < PROG_CNT; i++) { + for (i = 0; i < prog_cnt; i++) { prog[i] = bpf_object__find_program_by_title(obj, prog_name[i]); if (CHECK(!prog[i], "find_prog", "prog %s not found\n", prog_name[i])) goto close_prog; @@ -56,21 +59,54 @@ void test_fexit_bpf2bpf(void) "err %d errno %d retval %d duration %d\n", err, errno, retval, duration); - err = bpf_map_lookup_elem(bpf_map__fd(data_map), &zero, &result); + err = bpf_map_lookup_elem(bpf_map__fd(data_map), &zero, result); if (CHECK(err, "get_result", "failed to get output data: %d\n", err)) goto close_prog; - for (i = 0; i < PROG_CNT; i++) + for (i = 0; i < prog_cnt; i++) if (CHECK(result[i] != 1, "result", "fexit_bpf2bpf failed err %ld\n", result[i])) goto close_prog; close_prog: - for (i = 0; i < PROG_CNT; i++) + for (i = 0; i < prog_cnt; i++) if (!IS_ERR_OR_NULL(link[i])) bpf_link__destroy(link[i]); if (!IS_ERR_OR_NULL(obj)) bpf_object__close(obj); bpf_object__close(pkt_obj); + free(link); + free(prog); + free(result); +} + +static void test_target_no_callees(void) +{ + const char *prog_name[] = { + "fexit/test_pkt_md_access", + }; + test_fexit_bpf2bpf_common("./fexit_bpf2bpf_simple.o", + "./test_pkt_md_access.o", + ARRAY_SIZE(prog_name), + prog_name); +} + +static void test_target_yes_callees(void) +{ + const char *prog_name[] = { + "fexit/test_pkt_access", + "fexit/test_pkt_access_subprog1", + "fexit/test_pkt_access_subprog2", + }; + test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o", + "./test_pkt_access.o", + ARRAY_SIZE(prog_name), + prog_name); +} + +void test_fexit_bpf2bpf(void) +{ + test_target_no_callees(); + test_target_yes_callees(); } diff --git a/tools/testing/selftests/bpf/progs/fentry_test.c b/tools/testing/selftests/bpf/progs/fentry_test.c index d2af9f039df5..615f7c6bca77 100644 --- a/tools/testing/selftests/bpf/progs/fentry_test.c +++ b/tools/testing/selftests/bpf/progs/fentry_test.c @@ -6,28 +6,28 @@ char _license[] SEC("license") = "GPL"; -static volatile __u64 test1_result; +__u64 test1_result = 0; BPF_TRACE_1("fentry/bpf_fentry_test1", test1, int, a) { test1_result = a == 1; return 0; } -static volatile __u64 test2_result; +__u64 test2_result = 0; BPF_TRACE_2("fentry/bpf_fentry_test2", test2, int, a, __u64, b) { test2_result = a == 2 && b == 3; return 0; } -static volatile __u64 test3_result; +__u64 test3_result = 0; BPF_TRACE_3("fentry/bpf_fentry_test3", test3, char, a, int, b, __u64, c) { test3_result = a == 4 && b == 5 && c == 6; return 0; } -static volatile __u64 test4_result; +__u64 test4_result = 0; BPF_TRACE_4("fentry/bpf_fentry_test4", test4, void *, a, char, b, int, c, __u64, d) { @@ -35,7 +35,7 @@ BPF_TRACE_4("fentry/bpf_fentry_test4", test4, return 0; } -static volatile __u64 test5_result; +__u64 test5_result = 0; BPF_TRACE_5("fentry/bpf_fentry_test5", test5, __u64, a, void *, b, short, c, int, d, __u64, e) { @@ -44,7 +44,7 @@ BPF_TRACE_5("fentry/bpf_fentry_test5", test5, return 0; } -static volatile __u64 test6_result; +__u64 test6_result = 0; BPF_TRACE_6("fentry/bpf_fentry_test6", test6, __u64, a, void *, b, short, c, int, d, void *, e, __u64, f) { diff --git a/tools/testing/selftests/bpf/progs/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/progs/fexit_bpf2bpf.c index 525d47d7b589..2d211ee98a1c 100644 --- a/tools/testing/selftests/bpf/progs/fexit_bpf2bpf.c +++ b/tools/testing/selftests/bpf/progs/fexit_bpf2bpf.c @@ -8,7 +8,7 @@ struct sk_buff { unsigned int len; }; -static volatile __u64 test_result; +__u64 test_result = 0; BPF_TRACE_2("fexit/test_pkt_access", test_main, struct sk_buff *, skb, int, ret) { @@ -23,7 +23,7 @@ BPF_TRACE_2("fexit/test_pkt_access", test_main, return 0; } -static volatile __u64 test_result_subprog1; +__u64 test_result_subprog1 = 0; BPF_TRACE_2("fexit/test_pkt_access_subprog1", test_subprog1, struct sk_buff *, skb, int, ret) { @@ -56,7 +56,7 @@ struct args_subprog2 { __u64 args[5]; __u64 ret; }; -static volatile __u64 test_result_subprog2; +__u64 test_result_subprog2 = 0; SEC("fexit/test_pkt_access_subprog2") int test_subprog2(struct args_subprog2 *ctx) { diff --git a/tools/testing/selftests/bpf/progs/fexit_bpf2bpf_simple.c b/tools/testing/selftests/bpf/progs/fexit_bpf2bpf_simple.c new file mode 100644 index 000000000000..ebc0ab7f0f5c --- /dev/null +++ b/tools/testing/selftests/bpf/progs/fexit_bpf2bpf_simple.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019 Facebook */ +#include <linux/bpf.h> +#include "bpf_helpers.h" +#include "bpf_trace_helpers.h" + +struct sk_buff { + unsigned int len; +}; + +__u64 test_result = 0; +BPF_TRACE_2("fexit/test_pkt_md_access", test_main2, + struct sk_buff *, skb, int, ret) +{ + int len; + + __builtin_preserve_access_index(({ + len = skb->len; + })); + if (len != 74 || ret != 0) + return 0; + + test_result = 1; + return 0; +} +char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/progs/fexit_test.c b/tools/testing/selftests/bpf/progs/fexit_test.c index 2487e98edb34..86db0d60fb6e 100644 --- a/tools/testing/selftests/bpf/progs/fexit_test.c +++ b/tools/testing/selftests/bpf/progs/fexit_test.c @@ -6,28 +6,28 @@ char _license[] SEC("license") = "GPL"; -static volatile __u64 test1_result; +__u64 test1_result = 0; BPF_TRACE_2("fexit/bpf_fentry_test1", test1, int, a, int, ret) { test1_result = a == 1 && ret == 2; return 0; } -static volatile __u64 test2_result; +__u64 test2_result = 0; BPF_TRACE_3("fexit/bpf_fentry_test2", test2, int, a, __u64, b, int, ret) { test2_result = a == 2 && b == 3 && ret == 5; return 0; } -static volatile __u64 test3_result; +__u64 test3_result = 0; BPF_TRACE_4("fexit/bpf_fentry_test3", test3, char, a, int, b, __u64, c, int, ret) { test3_result = a == 4 && b == 5 && c == 6 && ret == 15; return 0; } -static volatile __u64 test4_result; +__u64 test4_result = 0; BPF_TRACE_5("fexit/bpf_fentry_test4", test4, void *, a, char, b, int, c, __u64, d, int, ret) { @@ -37,7 +37,7 @@ BPF_TRACE_5("fexit/bpf_fentry_test4", test4, return 0; } -static volatile __u64 test5_result; +__u64 test5_result = 0; BPF_TRACE_6("fexit/bpf_fentry_test5", test5, __u64, a, void *, b, short, c, int, d, __u64, e, int, ret) { @@ -46,7 +46,7 @@ BPF_TRACE_6("fexit/bpf_fentry_test5", test5, return 0; } -static volatile __u64 test6_result; +__u64 test6_result = 0; BPF_TRACE_7("fexit/bpf_fentry_test6", test6, __u64, a, void *, b, short, c, int, d, void *, e, __u64, f, int, ret) diff --git a/tools/testing/selftests/bpf/progs/test_mmap.c b/tools/testing/selftests/bpf/progs/test_mmap.c index 0d2ec9fbcf61..e808791b7047 100644 --- a/tools/testing/selftests/bpf/progs/test_mmap.c +++ b/tools/testing/selftests/bpf/progs/test_mmap.c @@ -15,8 +15,8 @@ struct { __type(value, __u64); } data_map SEC(".maps"); -static volatile __u64 in_val; -static volatile __u64 out_val; +__u64 in_val = 0; +__u64 out_val = 0; SEC("raw_tracepoint/sys_enter") int test_mmap(void *ctx) diff --git a/tools/testing/selftests/bpf/progs/test_pkt_md_access.c b/tools/testing/selftests/bpf/progs/test_pkt_md_access.c index 3d039e18bf82..1db2623021ad 100644 --- a/tools/testing/selftests/bpf/progs/test_pkt_md_access.c +++ b/tools/testing/selftests/bpf/progs/test_pkt_md_access.c @@ -27,8 +27,8 @@ int _version SEC("version") = 1; } #endif -SEC("test1") -int process(struct __sk_buff *skb) +SEC("classifier/test_pkt_md_access") +int test_pkt_md_access(struct __sk_buff *skb) { TEST_FIELD(__u8, len, 0xFF); TEST_FIELD(__u16, len, 0xFFFF); diff --git a/tools/testing/selftests/bpf/progs/test_tcpbpf_kern.c b/tools/testing/selftests/bpf/progs/test_tcpbpf_kern.c index 2e233613d1fc..7fa4595d2b66 100644 --- a/tools/testing/selftests/bpf/progs/test_tcpbpf_kern.c +++ b/tools/testing/selftests/bpf/progs/test_tcpbpf_kern.c @@ -131,6 +131,7 @@ int bpf_testcb(struct bpf_sock_ops *skops) g.bytes_received = skops->bytes_received; g.bytes_acked = skops->bytes_acked; } + g.num_close_events++; bpf_map_update_elem(&global_map, &key, &g, BPF_ANY); } diff --git a/tools/testing/selftests/bpf/test_cpp.cpp b/tools/testing/selftests/bpf/test_cpp.cpp new file mode 100644 index 000000000000..f0eb2727b766 --- /dev/null +++ b/tools/testing/selftests/bpf/test_cpp.cpp @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +#include "libbpf.h" +#include "bpf.h" +#include "btf.h" + +/* do nothing, just make sure we can link successfully */ + +int main(int argc, char *argv[]) +{ + /* libbpf.h */ + libbpf_set_print(NULL); + + /* bpf.h */ + bpf_prog_get_fd_by_id(0); + + /* btf.h */ + btf__new(NULL, 0); + + return 0; +} diff --git a/tools/testing/selftests/bpf/test_ftrace.sh b/tools/testing/selftests/bpf/test_ftrace.sh new file mode 100755 index 000000000000..20de7bb873bc --- /dev/null +++ b/tools/testing/selftests/bpf/test_ftrace.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +TR=/sys/kernel/debug/tracing/ +clear_trace() { # reset trace output + echo > $TR/trace +} + +disable_tracing() { # stop trace recording + echo 0 > $TR/tracing_on +} + +enable_tracing() { # start trace recording + echo 1 > $TR/tracing_on +} + +reset_tracer() { # reset the current tracer + echo nop > $TR/current_tracer +} + +disable_tracing +clear_trace + +echo "" > $TR/set_ftrace_filter +echo '*printk* *console* *wake* *serial* *lock*' > $TR/set_ftrace_notrace + +echo "bpf_prog_test*" > $TR/set_graph_function +echo "" > $TR/set_graph_notrace + +echo function_graph > $TR/current_tracer + +enable_tracing +./test_progs -t fentry +./test_progs -t fexit +disable_tracing +clear_trace + +reset_tracer + +exit 0 diff --git a/tools/testing/selftests/bpf/test_skb_cgroup_id_user.c b/tools/testing/selftests/bpf/test_skb_cgroup_id_user.c index 9220747c069d..356351c0ac28 100644 --- a/tools/testing/selftests/bpf/test_skb_cgroup_id_user.c +++ b/tools/testing/selftests/bpf/test_skb_cgroup_id_user.c @@ -120,7 +120,7 @@ int check_ancestor_cgroup_ids(int prog_id) int err = 0; int map_fd; - expected_ids[0] = 0x100000001; /* root cgroup */ + expected_ids[0] = get_cgroup_id("/.."); /* root cgroup */ expected_ids[1] = get_cgroup_id(""); expected_ids[2] = get_cgroup_id(CGROUP_PATH); expected_ids[3] = 0; /* non-existent cgroup */ diff --git a/tools/testing/selftests/bpf/test_tcpbpf.h b/tools/testing/selftests/bpf/test_tcpbpf.h index 7bcfa6207005..6220b95cbd02 100644 --- a/tools/testing/selftests/bpf/test_tcpbpf.h +++ b/tools/testing/selftests/bpf/test_tcpbpf.h @@ -13,5 +13,6 @@ struct tcpbpf_globals { __u64 bytes_received; __u64 bytes_acked; __u32 num_listen; + __u32 num_close_events; }; #endif diff --git a/tools/testing/selftests/bpf/test_tcpbpf_user.c b/tools/testing/selftests/bpf/test_tcpbpf_user.c index 716b4e3be581..3ae127620463 100644 --- a/tools/testing/selftests/bpf/test_tcpbpf_user.c +++ b/tools/testing/selftests/bpf/test_tcpbpf_user.c @@ -16,6 +16,9 @@ #include "test_tcpbpf.h" +/* 3 comes from one listening socket + both ends of the connection */ +#define EXPECTED_CLOSE_EVENTS 3 + #define EXPECT_EQ(expected, actual, fmt) \ do { \ if ((expected) != (actual)) { \ @@ -23,13 +26,14 @@ " Actual: %" fmt "\n" \ " Expected: %" fmt "\n", \ (actual), (expected)); \ - goto err; \ + ret--; \ } \ } while (0) int verify_result(const struct tcpbpf_globals *result) { __u32 expected_events; + int ret = 0; expected_events = ((1 << BPF_SOCK_OPS_TIMEOUT_INIT) | (1 << BPF_SOCK_OPS_RWND_INIT) | @@ -48,15 +52,15 @@ int verify_result(const struct tcpbpf_globals *result) EXPECT_EQ(0x80, result->bad_cb_test_rv, PRIu32); EXPECT_EQ(0, result->good_cb_test_rv, PRIu32); EXPECT_EQ(1, result->num_listen, PRIu32); + EXPECT_EQ(EXPECTED_CLOSE_EVENTS, result->num_close_events, PRIu32); - return 0; -err: - return -1; + return ret; } int verify_sockopt_result(int sock_map_fd) { __u32 key = 0; + int ret = 0; int res; int rv; @@ -69,9 +73,7 @@ int verify_sockopt_result(int sock_map_fd) rv = bpf_map_lookup_elem(sock_map_fd, &key, &res); EXPECT_EQ(0, rv, "d"); EXPECT_EQ(1, res, "d"); - return 0; -err: - return -1; + return ret; } static int bpf_find_map(const char *test, struct bpf_object *obj, @@ -96,6 +98,7 @@ int main(int argc, char **argv) int error = EXIT_FAILURE; struct bpf_object *obj; int cg_fd = -1; + int retry = 10; __u32 key = 0; int rv; @@ -134,12 +137,20 @@ int main(int argc, char **argv) if (sock_map_fd < 0) goto err; +retry_lookup: rv = bpf_map_lookup_elem(map_fd, &key, &g); if (rv != 0) { printf("FAILED: bpf_map_lookup_elem returns %d\n", rv); goto err; } + if (g.num_close_events != EXPECTED_CLOSE_EVENTS && retry--) { + printf("Unexpected number of close events (%d), retrying!\n", + g.num_close_events); + usleep(100); + goto retry_lookup; + } + if (verify_result(&g)) { printf("FAILED: Wrong stats\n"); goto err; diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index d27fd929abb9..87eaa49609a0 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c @@ -408,10 +408,10 @@ static void update_map(int fd, int index) assert(!bpf_map_update_elem(fd, &index, &value, 0)); } -static int create_prog_dummy1(enum bpf_prog_type prog_type) +static int create_prog_dummy_simple(enum bpf_prog_type prog_type, int ret) { struct bpf_insn prog[] = { - BPF_MOV64_IMM(BPF_REG_0, 42), + BPF_MOV64_IMM(BPF_REG_0, ret), BPF_EXIT_INSN(), }; @@ -419,14 +419,15 @@ static int create_prog_dummy1(enum bpf_prog_type prog_type) ARRAY_SIZE(prog), "GPL", 0, NULL, 0); } -static int create_prog_dummy2(enum bpf_prog_type prog_type, int mfd, int idx) +static int create_prog_dummy_loop(enum bpf_prog_type prog_type, int mfd, + int idx, int ret) { struct bpf_insn prog[] = { BPF_MOV64_IMM(BPF_REG_3, idx), BPF_LD_MAP_FD(BPF_REG_2, mfd), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), - BPF_MOV64_IMM(BPF_REG_0, 41), + BPF_MOV64_IMM(BPF_REG_0, ret), BPF_EXIT_INSN(), }; @@ -435,10 +436,9 @@ static int create_prog_dummy2(enum bpf_prog_type prog_type, int mfd, int idx) } static int create_prog_array(enum bpf_prog_type prog_type, uint32_t max_elem, - int p1key) + int p1key, int p2key, int p3key) { - int p2key = 1; - int mfd, p1fd, p2fd; + int mfd, p1fd, p2fd, p3fd; mfd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int), sizeof(int), max_elem, 0); @@ -449,23 +449,24 @@ static int create_prog_array(enum bpf_prog_type prog_type, uint32_t max_elem, return -1; } - p1fd = create_prog_dummy1(prog_type); - p2fd = create_prog_dummy2(prog_type, mfd, p2key); - if (p1fd < 0 || p2fd < 0) - goto out; + p1fd = create_prog_dummy_simple(prog_type, 42); + p2fd = create_prog_dummy_loop(prog_type, mfd, p2key, 41); + p3fd = create_prog_dummy_simple(prog_type, 24); + if (p1fd < 0 || p2fd < 0 || p3fd < 0) + goto err; if (bpf_map_update_elem(mfd, &p1key, &p1fd, BPF_ANY) < 0) - goto out; + goto err; if (bpf_map_update_elem(mfd, &p2key, &p2fd, BPF_ANY) < 0) - goto out; + goto err; + if (bpf_map_update_elem(mfd, &p3key, &p3fd, BPF_ANY) < 0) { +err: + close(mfd); + mfd = -1; + } + close(p3fd); close(p2fd); close(p1fd); - return mfd; -out: - close(p2fd); - close(p1fd); - close(mfd); - return -1; } static int create_map_in_map(void) @@ -684,7 +685,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type, } if (*fixup_prog1) { - map_fds[4] = create_prog_array(prog_type, 4, 0); + map_fds[4] = create_prog_array(prog_type, 4, 0, 1, 2); do { prog[*fixup_prog1].imm = map_fds[4]; fixup_prog1++; @@ -692,7 +693,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type, } if (*fixup_prog2) { - map_fds[5] = create_prog_array(prog_type, 8, 7); + map_fds[5] = create_prog_array(prog_type, 8, 7, 1, 2); do { prog[*fixup_prog2].imm = map_fds[5]; fixup_prog2++; diff --git a/tools/testing/selftests/bpf/verifier/ref_tracking.c b/tools/testing/selftests/bpf/verifier/ref_tracking.c index ebcbf154c460..604b46151736 100644 --- a/tools/testing/selftests/bpf/verifier/ref_tracking.c +++ b/tools/testing/selftests/bpf/verifier/ref_tracking.c @@ -455,7 +455,7 @@ BPF_MOV64_REG(BPF_REG_1, BPF_REG_0), BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 7), /* bpf_tail_call() */ - BPF_MOV64_IMM(BPF_REG_3, 2), + BPF_MOV64_IMM(BPF_REG_3, 3), BPF_LD_MAP_FD(BPF_REG_2, 0), BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), @@ -478,7 +478,7 @@ BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1), BPF_EMIT_CALL(BPF_FUNC_sk_release), /* bpf_tail_call() */ - BPF_MOV64_IMM(BPF_REG_3, 2), + BPF_MOV64_IMM(BPF_REG_3, 3), BPF_LD_MAP_FD(BPF_REG_2, 0), BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), @@ -497,7 +497,7 @@ BPF_SK_LOOKUP(sk_lookup_tcp), /* bpf_tail_call() */ BPF_MOV64_REG(BPF_REG_6, BPF_REG_0), - BPF_MOV64_IMM(BPF_REG_3, 2), + BPF_MOV64_IMM(BPF_REG_3, 3), BPF_LD_MAP_FD(BPF_REG_2, 0), BPF_MOV64_REG(BPF_REG_1, BPF_REG_7), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), diff --git a/tools/testing/selftests/bpf/verifier/runtime_jit.c b/tools/testing/selftests/bpf/verifier/runtime_jit.c index a9a8f620e71c..94c399d1faca 100644 --- a/tools/testing/selftests/bpf/verifier/runtime_jit.c +++ b/tools/testing/selftests/bpf/verifier/runtime_jit.c @@ -27,6 +27,19 @@ { "runtime/jit: tail_call within bounds, no prog", .insns = { + BPF_MOV64_IMM(BPF_REG_3, 3), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .fixup_prog1 = { 1 }, + .result = ACCEPT, + .retval = 1, +}, +{ + "runtime/jit: tail_call within bounds, key 2", + .insns = { BPF_MOV64_IMM(BPF_REG_3, 2), BPF_LD_MAP_FD(BPF_REG_2, 0), BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), @@ -35,9 +48,147 @@ }, .fixup_prog1 = { 1 }, .result = ACCEPT, + .retval = 24, +}, +{ + "runtime/jit: tail_call within bounds, key 2 / key 2, first branch", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 13), + BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, + offsetof(struct __sk_buff, cb[0])), + BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, + offsetof(struct __sk_buff, cb[0])), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4), + BPF_MOV64_IMM(BPF_REG_3, 2), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_JMP_IMM(BPF_JA, 0, 0, 3), + BPF_MOV64_IMM(BPF_REG_3, 2), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .fixup_prog1 = { 5, 9 }, + .result = ACCEPT, + .retval = 24, +}, +{ + "runtime/jit: tail_call within bounds, key 2 / key 2, second branch", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 14), + BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, + offsetof(struct __sk_buff, cb[0])), + BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, + offsetof(struct __sk_buff, cb[0])), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4), + BPF_MOV64_IMM(BPF_REG_3, 2), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_JMP_IMM(BPF_JA, 0, 0, 3), + BPF_MOV64_IMM(BPF_REG_3, 2), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .fixup_prog1 = { 5, 9 }, + .result = ACCEPT, + .retval = 24, +}, +{ + "runtime/jit: tail_call within bounds, key 0 / key 2, first branch", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 13), + BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, + offsetof(struct __sk_buff, cb[0])), + BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, + offsetof(struct __sk_buff, cb[0])), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4), + BPF_MOV64_IMM(BPF_REG_3, 0), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_JMP_IMM(BPF_JA, 0, 0, 3), + BPF_MOV64_IMM(BPF_REG_3, 2), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .fixup_prog1 = { 5, 9 }, + .result = ACCEPT, + .retval = 24, +}, +{ + "runtime/jit: tail_call within bounds, key 0 / key 2, second branch", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 14), + BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, + offsetof(struct __sk_buff, cb[0])), + BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, + offsetof(struct __sk_buff, cb[0])), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4), + BPF_MOV64_IMM(BPF_REG_3, 0), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_JMP_IMM(BPF_JA, 0, 0, 3), + BPF_MOV64_IMM(BPF_REG_3, 2), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .fixup_prog1 = { 5, 9 }, + .result = ACCEPT, + .retval = 42, +}, +{ + "runtime/jit: tail_call within bounds, different maps, first branch", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 13), + BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, + offsetof(struct __sk_buff, cb[0])), + BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, + offsetof(struct __sk_buff, cb[0])), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4), + BPF_MOV64_IMM(BPF_REG_3, 0), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_JMP_IMM(BPF_JA, 0, 0, 3), + BPF_MOV64_IMM(BPF_REG_3, 0), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .fixup_prog1 = { 5 }, + .fixup_prog2 = { 9 }, + .result_unpriv = REJECT, + .errstr_unpriv = "tail_call abusing map_ptr", + .result = ACCEPT, .retval = 1, }, { + "runtime/jit: tail_call within bounds, different maps, second branch", + .insns = { + BPF_MOV64_IMM(BPF_REG_0, 14), + BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, + offsetof(struct __sk_buff, cb[0])), + BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, + offsetof(struct __sk_buff, cb[0])), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4), + BPF_MOV64_IMM(BPF_REG_3, 0), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_JMP_IMM(BPF_JA, 0, 0, 3), + BPF_MOV64_IMM(BPF_REG_3, 0), + BPF_LD_MAP_FD(BPF_REG_2, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call), + BPF_MOV64_IMM(BPF_REG_0, 1), + BPF_EXIT_INSN(), + }, + .fixup_prog1 = { 5 }, + .fixup_prog2 = { 9 }, + .result_unpriv = REJECT, + .errstr_unpriv = "tail_call abusing map_ptr", + .result = ACCEPT, + .retval = 42, +}, +{ "runtime/jit: tail_call out of bounds", .insns = { BPF_MOV64_IMM(BPF_REG_3, 256), diff --git a/tools/testing/selftests/filesystems/epoll/.gitignore b/tools/testing/selftests/filesystems/epoll/.gitignore new file mode 100644 index 000000000000..9ae8db44ec14 --- /dev/null +++ b/tools/testing/selftests/filesystems/epoll/.gitignore @@ -0,0 +1 @@ +epoll_wakeup_test diff --git a/tools/testing/selftests/filesystems/epoll/Makefile b/tools/testing/selftests/filesystems/epoll/Makefile new file mode 100644 index 000000000000..e62f3d4f68da --- /dev/null +++ b/tools/testing/selftests/filesystems/epoll/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 + +CFLAGS += -I../../../../../usr/include/ +LDFLAGS += -lpthread +TEST_GEN_PROGS := epoll_wakeup_test + +include ../../lib.mk diff --git a/tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c b/tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c new file mode 100644 index 000000000000..37a04dab56f0 --- /dev/null +++ b/tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c @@ -0,0 +1,3074 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define _GNU_SOURCE +#include <poll.h> +#include <unistd.h> +#include <signal.h> +#include <pthread.h> +#include <sys/epoll.h> +#include <sys/socket.h> +#include "../../kselftest_harness.h" + +struct epoll_mtcontext +{ + int efd[3]; + int sfd[4]; + int count; + + pthread_t main; + pthread_t waiter; +}; + +static void signal_handler(int signum) +{ +} + +static void kill_timeout(struct epoll_mtcontext *ctx) +{ + usleep(1000000); + pthread_kill(ctx->main, SIGUSR1); + pthread_kill(ctx->waiter, SIGUSR1); +} + +static void *waiter_entry1a(void *data) +{ + struct epoll_event e; + struct epoll_mtcontext *ctx = data; + + if (epoll_wait(ctx->efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx->count, 1); + + return NULL; +} + +static void *waiter_entry1ap(void *data) +{ + struct pollfd pfd; + struct epoll_event e; + struct epoll_mtcontext *ctx = data; + + pfd.fd = ctx->efd[0]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx->efd[0], &e, 1, 0) > 0) + __sync_fetch_and_add(&ctx->count, 1); + } + + return NULL; +} + +static void *waiter_entry1o(void *data) +{ + struct epoll_event e; + struct epoll_mtcontext *ctx = data; + + if (epoll_wait(ctx->efd[0], &e, 1, -1) > 0) + __sync_fetch_and_or(&ctx->count, 1); + + return NULL; +} + +static void *waiter_entry1op(void *data) +{ + struct pollfd pfd; + struct epoll_event e; + struct epoll_mtcontext *ctx = data; + + pfd.fd = ctx->efd[0]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx->efd[0], &e, 1, 0) > 0) + __sync_fetch_and_or(&ctx->count, 1); + } + + return NULL; +} + +static void *waiter_entry2a(void *data) +{ + struct epoll_event events[2]; + struct epoll_mtcontext *ctx = data; + + if (epoll_wait(ctx->efd[0], events, 2, -1) > 0) + __sync_fetch_and_add(&ctx->count, 1); + + return NULL; +} + +static void *waiter_entry2ap(void *data) +{ + struct pollfd pfd; + struct epoll_event events[2]; + struct epoll_mtcontext *ctx = data; + + pfd.fd = ctx->efd[0]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx->efd[0], events, 2, 0) > 0) + __sync_fetch_and_add(&ctx->count, 1); + } + + return NULL; +} + +static void *emitter_entry1(void *data) +{ + struct epoll_mtcontext *ctx = data; + + usleep(100000); + write(ctx->sfd[1], "w", 1); + + kill_timeout(ctx); + + return NULL; +} + +static void *emitter_entry2(void *data) +{ + struct epoll_mtcontext *ctx = data; + + usleep(100000); + write(ctx->sfd[1], "w", 1); + write(ctx->sfd[3], "w", 1); + + kill_timeout(ctx); + + return NULL; +} + +/* + * t0 + * | (ew) + * e0 + * | (lt) + * s0 + */ +TEST(epoll1) +{ + int efd; + int sfd[2]; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0); + + efd = epoll_create(1); + ASSERT_GE(efd, 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + EXPECT_EQ(epoll_wait(efd, &e, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd, &e, 1, 0), 1); + + close(efd); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (ew) + * e0 + * | (et) + * s0 + */ +TEST(epoll2) +{ + int efd; + int sfd[2]; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0); + + efd = epoll_create(1); + ASSERT_GE(efd, 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + EXPECT_EQ(epoll_wait(efd, &e, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd, &e, 1, 0), 0); + + close(efd); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (ew) + * e0 + * (lt) / \ (lt) + * s0 s2 + */ +TEST(epoll3) +{ + int efd; + int sfd[4]; + struct epoll_event events[2]; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0); + + efd = epoll_create(1); + ASSERT_GE(efd, 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[2], events), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + ASSERT_EQ(write(sfd[3], "w", 1), 1); + + EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2); + EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2); + + close(efd); + close(sfd[0]); + close(sfd[1]); + close(sfd[2]); + close(sfd[3]); +} + +/* + * t0 + * | (ew) + * e0 + * (et) / \ (et) + * s0 s2 + */ +TEST(epoll4) +{ + int efd; + int sfd[4]; + struct epoll_event events[2]; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0); + + efd = epoll_create(1); + ASSERT_GE(efd, 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], events), 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[2], events), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + ASSERT_EQ(write(sfd[3], "w", 1), 1); + + EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2); + EXPECT_EQ(epoll_wait(efd, events, 2, 0), 0); + + close(efd); + close(sfd[0]); + close(sfd[1]); + close(sfd[2]); + close(sfd[3]); +} + +/* + * t0 + * | (p) + * e0 + * | (lt) + * s0 + */ +TEST(epoll5) +{ + int efd; + int sfd[2]; + struct pollfd pfd; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0); + + efd = epoll_create(1); + ASSERT_GE(efd, 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + pfd.fd = efd; + pfd.events = POLLIN; + ASSERT_EQ(poll(&pfd, 1, 0), 1); + ASSERT_EQ(epoll_wait(efd, &e, 1, 0), 1); + + pfd.fd = efd; + pfd.events = POLLIN; + ASSERT_EQ(poll(&pfd, 1, 0), 1); + ASSERT_EQ(epoll_wait(efd, &e, 1, 0), 1); + + close(efd); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (p) + * e0 + * | (et) + * s0 + */ +TEST(epoll6) +{ + int efd; + int sfd[2]; + struct pollfd pfd; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0); + + efd = epoll_create(1); + ASSERT_GE(efd, 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + pfd.fd = efd; + pfd.events = POLLIN; + ASSERT_EQ(poll(&pfd, 1, 0), 1); + ASSERT_EQ(epoll_wait(efd, &e, 1, 0), 1); + + pfd.fd = efd; + pfd.events = POLLIN; + ASSERT_EQ(poll(&pfd, 1, 0), 0); + ASSERT_EQ(epoll_wait(efd, &e, 1, 0), 0); + + close(efd); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (p) + * e0 + * (lt) / \ (lt) + * s0 s2 + */ + +TEST(epoll7) +{ + int efd; + int sfd[4]; + struct pollfd pfd; + struct epoll_event events[2]; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0); + + efd = epoll_create(1); + ASSERT_GE(efd, 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[2], events), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + ASSERT_EQ(write(sfd[3], "w", 1), 1); + + pfd.fd = efd; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2); + + pfd.fd = efd; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2); + + close(efd); + close(sfd[0]); + close(sfd[1]); + close(sfd[2]); + close(sfd[3]); +} + +/* + * t0 + * | (p) + * e0 + * (et) / \ (et) + * s0 s2 + */ +TEST(epoll8) +{ + int efd; + int sfd[4]; + struct pollfd pfd; + struct epoll_event events[2]; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0); + + efd = epoll_create(1); + ASSERT_GE(efd, 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[0], events), 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd, EPOLL_CTL_ADD, sfd[2], events), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + ASSERT_EQ(write(sfd[3], "w", 1), 1); + + pfd.fd = efd; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd, events, 2, 0), 2); + + pfd.fd = efd; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 0); + EXPECT_EQ(epoll_wait(efd, events, 2, 0), 0); + + close(efd); + close(sfd[0]); + close(sfd[1]); + close(sfd[2]); + close(sfd[3]); +} + +/* + * t0 t1 + * (ew) \ / (ew) + * e0 + * | (lt) + * s0 + */ +TEST(epoll9) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (ew) + * e0 + * | (et) + * s0 + */ +TEST(epoll10) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 1); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (ew) + * e0 + * (lt) / \ (lt) + * s0 s2 + */ +TEST(epoll11) +{ + pthread_t emitter; + struct epoll_event events[2]; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[2], events), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry2a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0); + + if (epoll_wait(ctx.efd[0], events, 2, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); + close(ctx.sfd[2]); + close(ctx.sfd[3]); +} + +/* + * t0 t1 + * (ew) \ / (ew) + * e0 + * (et) / \ (et) + * s0 s2 + */ +TEST(epoll12) +{ + pthread_t emitter; + struct epoll_event events[2]; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], events), 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[2], events), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0); + + if (epoll_wait(ctx.efd[0], events, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); + close(ctx.sfd[2]); + close(ctx.sfd[3]); +} + +/* + * t0 t1 + * (ew) \ / (p) + * e0 + * | (lt) + * s0 + */ +TEST(epoll13) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (p) + * e0 + * | (et) + * s0 + */ +TEST(epoll14) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 1); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (p) + * e0 + * (lt) / \ (lt) + * s0 s2 + */ +TEST(epoll15) +{ + pthread_t emitter; + struct epoll_event events[2]; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[2], events), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry2ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0); + + if (epoll_wait(ctx.efd[0], events, 2, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); + close(ctx.sfd[2]); + close(ctx.sfd[3]); +} + +/* + * t0 t1 + * (ew) \ / (p) + * e0 + * (et) / \ (et) + * s0 s2 + */ +TEST(epoll16) +{ + pthread_t emitter; + struct epoll_event events[2]; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[0], events), 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.sfd[2], events), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0); + + if (epoll_wait(ctx.efd[0], events, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); + close(ctx.sfd[2]); + close(ctx.sfd[3]); +} + +/* + * t0 + * | (ew) + * e0 + * | (lt) + * e1 + * | (lt) + * s0 + */ +TEST(epoll17) +{ + int efd[2]; + int sfd[2]; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + + close(efd[0]); + close(efd[1]); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (ew) + * e0 + * | (lt) + * e1 + * | (et) + * s0 + */ +TEST(epoll18) +{ + int efd[2]; + int sfd[2]; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + + close(efd[0]); + close(efd[1]); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (ew) + * e0 + * | (et) + * e1 + * | (lt) + * s0 + */ +TEST(epoll19) +{ + int efd[2]; + int sfd[2]; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 0); + + close(efd[0]); + close(efd[1]); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (ew) + * e0 + * | (et) + * e1 + * | (et) + * s0 + */ +TEST(epoll20) +{ + int efd[2]; + int sfd[2]; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 0); + + close(efd[0]); + close(efd[1]); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (p) + * e0 + * | (lt) + * e1 + * | (lt) + * s0 + */ +TEST(epoll21) +{ + int efd[2]; + int sfd[2]; + struct pollfd pfd; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + + close(efd[0]); + close(efd[1]); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (p) + * e0 + * | (lt) + * e1 + * | (et) + * s0 + */ +TEST(epoll22) +{ + int efd[2]; + int sfd[2]; + struct pollfd pfd; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + + close(efd[0]); + close(efd[1]); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (p) + * e0 + * | (et) + * e1 + * | (lt) + * s0 + */ +TEST(epoll23) +{ + int efd[2]; + int sfd[2]; + struct pollfd pfd; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 0); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 0); + + close(efd[0]); + close(efd[1]); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 + * | (p) + * e0 + * | (et) + * e1 + * | (et) + * s0 + */ +TEST(epoll24) +{ + int efd[2]; + int sfd[2]; + struct pollfd pfd; + struct epoll_event e; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sfd), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], &e), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 1); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 0); + EXPECT_EQ(epoll_wait(efd[0], &e, 1, 0), 0); + + close(efd[0]); + close(efd[1]); + close(sfd[0]); + close(sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (ew) + * e0 + * | (lt) + * e1 + * | (lt) + * s0 + */ +TEST(epoll25) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (ew) + * e0 + * | (lt) + * e1 + * | (et) + * s0 + */ +TEST(epoll26) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (ew) + * e0 + * | (et) + * e1 + * | (lt) + * s0 + */ +TEST(epoll27) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 1); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (ew) + * e0 + * | (et) + * e1 + * | (et) + * s0 + */ +TEST(epoll28) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 1); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (p) + * e0 + * | (lt) + * e1 + * | (lt) + * s0 + */ +TEST(epoll29) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (p) + * e0 + * | (lt) + * e1 + * | (et) + * s0 + */ +TEST(epoll30) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (p) + * e0 + * | (et) + * e1 + * | (lt) + * s0 + */ +TEST(epoll31) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 1); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) \ / (p) + * e0 + * | (et) + * e1 + * | (et) + * s0 + */ +TEST(epoll32) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 1); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) | | (ew) + * | e0 + * \ / (lt) + * e1 + * | (lt) + * s0 + */ +TEST(epoll33) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) | | (ew) + * | e0 + * \ / (lt) + * e1 + * | (et) + * s0 + */ +TEST(epoll34) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1o, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0) + __sync_fetch_and_or(&ctx.count, 2); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3)); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) | | (ew) + * | e0 + * \ / (et) + * e1 + * | (lt) + * s0 + */ +TEST(epoll35) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) | | (ew) + * | e0 + * \ / (et) + * e1 + * | (et) + * s0 + */ +TEST(epoll36) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1o, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0) + __sync_fetch_and_or(&ctx.count, 2); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3)); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (p) | | (ew) + * | e0 + * \ / (lt) + * e1 + * | (lt) + * s0 + */ +TEST(epoll37) +{ + pthread_t emitter; + struct pollfd pfd; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + pfd.fd = ctx.efd[1]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0) + __sync_fetch_and_add(&ctx.count, 1); + } + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (p) | | (ew) + * | e0 + * \ / (lt) + * e1 + * | (et) + * s0 + */ +TEST(epoll38) +{ + pthread_t emitter; + struct pollfd pfd; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1o, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + pfd.fd = ctx.efd[1]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0) + __sync_fetch_and_or(&ctx.count, 2); + } + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3)); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (p) | | (ew) + * | e0 + * \ / (et) + * e1 + * | (lt) + * s0 + */ +TEST(epoll39) +{ + pthread_t emitter; + struct pollfd pfd; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + pfd.fd = ctx.efd[1]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0) + __sync_fetch_and_add(&ctx.count, 1); + } + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (p) | | (ew) + * | e0 + * \ / (et) + * e1 + * | (et) + * s0 + */ +TEST(epoll40) +{ + pthread_t emitter; + struct pollfd pfd; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1o, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + pfd.fd = ctx.efd[1]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0) + __sync_fetch_and_or(&ctx.count, 2); + } + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3)); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) | | (p) + * | e0 + * \ / (lt) + * e1 + * | (lt) + * s0 + */ +TEST(epoll41) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) | | (p) + * | e0 + * \ / (lt) + * e1 + * | (et) + * s0 + */ +TEST(epoll42) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1op, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0) + __sync_fetch_and_or(&ctx.count, 2); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3)); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) | | (p) + * | e0 + * \ / (et) + * e1 + * | (lt) + * s0 + */ +TEST(epoll43) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (ew) | | (p) + * | e0 + * \ / (et) + * e1 + * | (et) + * s0 + */ +TEST(epoll44) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1op, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0) + __sync_fetch_and_or(&ctx.count, 2); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3)); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (p) | | (p) + * | e0 + * \ / (lt) + * e1 + * | (lt) + * s0 + */ +TEST(epoll45) +{ + pthread_t emitter; + struct pollfd pfd; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + pfd.fd = ctx.efd[1]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0) + __sync_fetch_and_add(&ctx.count, 1); + } + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (p) | | (p) + * | e0 + * \ / (lt) + * e1 + * | (et) + * s0 + */ +TEST(epoll46) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1op, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0) + __sync_fetch_and_or(&ctx.count, 2); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3)); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (p) | | (p) + * | e0 + * \ / (et) + * e1 + * | (lt) + * s0 + */ +TEST(epoll47) +{ + pthread_t emitter; + struct pollfd pfd; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + pfd.fd = ctx.efd[1]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx.efd[1], &e, 1, 0) > 0) + __sync_fetch_and_add(&ctx.count, 1); + } + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 t1 + * (p) | | (p) + * | e0 + * \ / (et) + * e1 + * | (et) + * s0 + */ +TEST(epoll48) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx.sfd), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1op, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry1, &ctx), 0); + + if (epoll_wait(ctx.efd[1], &e, 1, -1) > 0) + __sync_fetch_and_or(&ctx.count, 2); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_TRUE((ctx.count == 2) || (ctx.count == 3)); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); +} + +/* + * t0 + * | (ew) + * e0 + * (lt) / \ (lt) + * e1 e2 + * (lt) | | (lt) + * s0 s2 + */ +TEST(epoll49) +{ + int efd[3]; + int sfd[4]; + struct epoll_event events[2]; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + efd[2] = epoll_create(1); + ASSERT_GE(efd[2], 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[2], EPOLL_CTL_ADD, sfd[2], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[2], events), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + ASSERT_EQ(write(sfd[3], "w", 1), 1); + + EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2); + EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2); + + close(efd[0]); + close(efd[1]); + close(efd[2]); + close(sfd[0]); + close(sfd[1]); + close(sfd[2]); + close(sfd[3]); +} + +/* + * t0 + * | (ew) + * e0 + * (et) / \ (et) + * e1 e2 + * (lt) | | (lt) + * s0 s2 + */ +TEST(epoll50) +{ + int efd[3]; + int sfd[4]; + struct epoll_event events[2]; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + efd[2] = epoll_create(1); + ASSERT_GE(efd[2], 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[2], EPOLL_CTL_ADD, sfd[2], events), 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], events), 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[2], events), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + ASSERT_EQ(write(sfd[3], "w", 1), 1); + + EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2); + EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 0); + + close(efd[0]); + close(efd[1]); + close(efd[2]); + close(sfd[0]); + close(sfd[1]); + close(sfd[2]); + close(sfd[3]); +} + +/* + * t0 + * | (p) + * e0 + * (lt) / \ (lt) + * e1 e2 + * (lt) | | (lt) + * s0 s2 + */ +TEST(epoll51) +{ + int efd[3]; + int sfd[4]; + struct pollfd pfd; + struct epoll_event events[2]; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + efd[2] = epoll_create(1); + ASSERT_GE(efd[2], 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[2], EPOLL_CTL_ADD, sfd[2], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[2], events), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + ASSERT_EQ(write(sfd[3], "w", 1), 1); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2); + + close(efd[0]); + close(efd[1]); + close(efd[2]); + close(sfd[0]); + close(sfd[1]); + close(sfd[2]); + close(sfd[3]); +} + +/* + * t0 + * | (p) + * e0 + * (et) / \ (et) + * e1 e2 + * (lt) | | (lt) + * s0 s2 + */ +TEST(epoll52) +{ + int efd[3]; + int sfd[4]; + struct pollfd pfd; + struct epoll_event events[2]; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &sfd[2]), 0); + + efd[0] = epoll_create(1); + ASSERT_GE(efd[0], 0); + + efd[1] = epoll_create(1); + ASSERT_GE(efd[1], 0); + + efd[2] = epoll_create(1); + ASSERT_GE(efd[2], 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[1], EPOLL_CTL_ADD, sfd[0], events), 0); + + events[0].events = EPOLLIN; + ASSERT_EQ(epoll_ctl(efd[2], EPOLL_CTL_ADD, sfd[2], events), 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[1], events), 0); + + events[0].events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(efd[0], EPOLL_CTL_ADD, efd[2], events), 0); + + ASSERT_EQ(write(sfd[1], "w", 1), 1); + ASSERT_EQ(write(sfd[3], "w", 1), 1); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 1); + EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 2); + + pfd.fd = efd[0]; + pfd.events = POLLIN; + EXPECT_EQ(poll(&pfd, 1, 0), 0); + EXPECT_EQ(epoll_wait(efd[0], events, 2, 0), 0); + + close(efd[0]); + close(efd[1]); + close(efd[2]); + close(sfd[0]); + close(sfd[1]); + close(sfd[2]); + close(sfd[3]); +} + +/* + * t0 t1 + * (ew) \ / (ew) + * e0 + * (lt) / \ (lt) + * e1 e2 + * (lt) | | (lt) + * s0 s2 + */ +TEST(epoll53) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + ctx.efd[2] = epoll_create(1); + ASSERT_GE(ctx.efd[2], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.efd[2]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); + close(ctx.sfd[2]); + close(ctx.sfd[3]); +} + +/* + * t0 t1 + * (ew) \ / (ew) + * e0 + * (et) / \ (et) + * e1 e2 + * (lt) | | (lt) + * s0 s2 + */ +TEST(epoll54) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + ctx.efd[2] = epoll_create(1); + ASSERT_GE(ctx.efd[2], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1a, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.efd[2]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); + close(ctx.sfd[2]); + close(ctx.sfd[3]); +} + +/* + * t0 t1 + * (ew) \ / (p) + * e0 + * (lt) / \ (lt) + * e1 e2 + * (lt) | | (lt) + * s0 s2 + */ +TEST(epoll55) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + ctx.efd[2] = epoll_create(1); + ASSERT_GE(ctx.efd[2], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.efd[2]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); + close(ctx.sfd[2]); + close(ctx.sfd[3]); +} + +/* + * t0 t1 + * (ew) \ / (p) + * e0 + * (et) / \ (et) + * e1 e2 + * (lt) | | (lt) + * s0 s2 + */ +TEST(epoll56) +{ + pthread_t emitter; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + ctx.efd[2] = epoll_create(1); + ASSERT_GE(ctx.efd[2], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0); + + if (epoll_wait(ctx.efd[0], &e, 1, -1) > 0) + __sync_fetch_and_add(&ctx.count, 1); + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.efd[2]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); + close(ctx.sfd[2]); + close(ctx.sfd[3]); +} + +/* + * t0 t1 + * (p) \ / (p) + * e0 + * (lt) / \ (lt) + * e1 e2 + * (lt) | | (lt) + * s0 s2 + */ +TEST(epoll57) +{ + pthread_t emitter; + struct pollfd pfd; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + ctx.efd[2] = epoll_create(1); + ASSERT_GE(ctx.efd[2], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0); + + pfd.fd = ctx.efd[0]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx.efd[0], &e, 1, 0) > 0) + __sync_fetch_and_add(&ctx.count, 1); + } + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.efd[2]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); + close(ctx.sfd[2]); + close(ctx.sfd[3]); +} + +/* + * t0 t1 + * (p) \ / (p) + * e0 + * (et) / \ (et) + * e1 e2 + * (lt) | | (lt) + * s0 s2 + */ +TEST(epoll58) +{ + pthread_t emitter; + struct pollfd pfd; + struct epoll_event e; + struct epoll_mtcontext ctx = { 0 }; + + signal(SIGUSR1, signal_handler); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[0]), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, &ctx.sfd[2]), 0); + + ctx.efd[0] = epoll_create(1); + ASSERT_GE(ctx.efd[0], 0); + + ctx.efd[1] = epoll_create(1); + ASSERT_GE(ctx.efd[1], 0); + + ctx.efd[2] = epoll_create(1); + ASSERT_GE(ctx.efd[2], 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[1], EPOLL_CTL_ADD, ctx.sfd[0], &e), 0); + + e.events = EPOLLIN; + ASSERT_EQ(epoll_ctl(ctx.efd[2], EPOLL_CTL_ADD, ctx.sfd[2], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &e), 0); + + e.events = EPOLLIN | EPOLLET; + ASSERT_EQ(epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[2], &e), 0); + + ctx.main = pthread_self(); + ASSERT_EQ(pthread_create(&ctx.waiter, NULL, waiter_entry1ap, &ctx), 0); + ASSERT_EQ(pthread_create(&emitter, NULL, emitter_entry2, &ctx), 0); + + pfd.fd = ctx.efd[0]; + pfd.events = POLLIN; + if (poll(&pfd, 1, -1) > 0) { + if (epoll_wait(ctx.efd[0], &e, 1, 0) > 0) + __sync_fetch_and_add(&ctx.count, 1); + } + + ASSERT_EQ(pthread_join(ctx.waiter, NULL), 0); + EXPECT_EQ(ctx.count, 2); + + if (pthread_tryjoin_np(emitter, NULL) < 0) { + pthread_kill(emitter, SIGUSR1); + pthread_join(emitter, NULL); + } + + close(ctx.efd[0]); + close(ctx.efd[1]); + close(ctx.efd[2]); + close(ctx.sfd[0]); + close(ctx.sfd[1]); + close(ctx.sfd[2]); + close(ctx.sfd[3]); +} + +TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-stacktrace.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-stacktrace.tc index 36fb59f886ea..1a52f2883fe0 100644 --- a/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-stacktrace.tc +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func-filter-stacktrace.tc @@ -3,6 +3,8 @@ # description: ftrace - stacktrace filter command # flags: instance +[ ! -f set_ftrace_filter ] && exit_unsupported + echo _do_fork:stacktrace >> set_ftrace_filter grep -q "_do_fork:stacktrace:unlimited" set_ftrace_filter diff --git a/tools/testing/selftests/ftrace/test.d/ftrace/func_cpumask.tc b/tools/testing/selftests/ftrace/test.d/ftrace/func_cpumask.tc index 86a1f07ef2ca..71fa3f49e35e 100644 --- a/tools/testing/selftests/ftrace/test.d/ftrace/func_cpumask.tc +++ b/tools/testing/selftests/ftrace/test.d/ftrace/func_cpumask.tc @@ -15,6 +15,11 @@ if [ $NP -eq 1 ] ;then exit_unresolved fi +if ! grep -q "function" available_tracers ; then + echo "Function trace is not enabled" + exit_unsupported +fi + ORIG_CPUMASK=`cat tracing_cpumask` do_reset() { diff --git a/tools/testing/selftests/ftrace/test.d/functions b/tools/testing/selftests/ftrace/test.d/functions index 86986c4bba54..5d4550591ff9 100644 --- a/tools/testing/selftests/ftrace/test.d/functions +++ b/tools/testing/selftests/ftrace/test.d/functions @@ -46,6 +46,9 @@ reset_events_filter() { # reset all current setting filters } reset_ftrace_filter() { # reset all triggers in set_ftrace_filter + if [ ! -f set_ftrace_filter ]; then + return 0 + fi echo > set_ftrace_filter grep -v '^#' set_ftrace_filter | while read t; do tr=`echo $t | cut -d: -f2` @@ -93,7 +96,7 @@ initialize_ftrace() { # Reset ftrace to initial-state disable_events [ -f set_event_pid ] && echo > set_event_pid [ -f set_ftrace_pid ] && echo > set_ftrace_pid - [ -f set_ftrace_filter ] && echo | tee set_ftrace_* + [ -f set_ftrace_notrace ] && echo > set_ftrace_notrace [ -f set_graph_function ] && echo | tee set_graph_* [ -f stack_trace_filter ] && echo > stack_trace_filter [ -f kprobe_events ] && echo > kprobe_events diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc index 5862eee91e1d..6e3dbe5f96b7 100644 --- a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc +++ b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc @@ -20,9 +20,9 @@ while read i; do test $N -eq 256 && break done -L=`wc -l kprobe_events` -if [ $L -ne $N ]; then - echo "The number of kprobes events ($L) is not $N" +L=`cat kprobe_events | wc -l` +if [ $L -ne 256 ]; then + echo "The number of kprobes events ($L) is not 256" exit_fail fi diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-action-hist-xfail.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-action-hist-xfail.tc index 1221240f8cf6..3f2aee115f6e 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-action-hist-xfail.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-action-hist-xfail.tc @@ -21,10 +21,10 @@ grep -q "snapshot()" README || exit_unsupported # version issue echo "Test expected snapshot action failure" -echo 'hist:keys=comm:onmatch(sched.sched_wakeup).snapshot()' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger && exit_fail +echo 'hist:keys=comm:onmatch(sched.sched_wakeup).snapshot()' >> events/sched/sched_waking/trigger && exit_fail echo "Test expected save action failure" -echo 'hist:keys=comm:onmatch(sched.sched_wakeup).save(comm,prio)' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger && exit_fail +echo 'hist:keys=comm:onmatch(sched.sched_wakeup).save(comm,prio)' >> events/sched/sched_waking/trigger && exit_fail exit_xfail diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc index 064a284e4e75..c80007aa9f86 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc @@ -16,7 +16,7 @@ grep -q "onchange(var)" README || exit_unsupported # version issue echo "Test onchange action" -echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio) if comm=="ping"' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger +echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio) if comm=="ping"' >> events/sched/sched_waking/trigger ping $LOCALHOST -c 3 nice -n 1 ping $LOCALHOST -c 3 diff --git a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc index 18fff69fc433..f546c1b66a9b 100644 --- a/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc +++ b/tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc @@ -23,9 +23,9 @@ grep -q "snapshot()" README || exit_unsupported # version issue echo "Test snapshot action" -echo 1 > /sys/kernel/debug/tracing/events/sched/enable +echo 1 > events/sched/enable -echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio):onchange($newprio).snapshot() if comm=="ping"' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger +echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio):onchange($newprio).snapshot() if comm=="ping"' >> events/sched/sched_waking/trigger ping $LOCALHOST -c 3 nice -n 1 ping $LOCALHOST -c 3 diff --git a/tools/testing/selftests/kselftest/module.sh b/tools/testing/selftests/kselftest/module.sh index 18e1c7992d30..fb4733faff12 100755 --- a/tools/testing/selftests/kselftest/module.sh +++ b/tools/testing/selftests/kselftest/module.sh @@ -9,7 +9,7 @@ # # #!/bin/sh # SPDX-License-Identifier: GPL-2.0+ -# $(dirname $0)/../kselftest_module.sh "description" module_name +# $(dirname $0)/../kselftest/module.sh "description" module_name # # Example: tools/testing/selftests/lib/printf.sh diff --git a/tools/testing/selftests/kselftest/prefix.pl b/tools/testing/selftests/kselftest/prefix.pl index ec7e48118183..31f7c2a0a8bd 100755 --- a/tools/testing/selftests/kselftest/prefix.pl +++ b/tools/testing/selftests/kselftest/prefix.pl @@ -3,6 +3,7 @@ # Prefix all lines with "# ", unbuffered. Command being piped in may need # to have unbuffering forced with "stdbuf -i0 -o0 -e0 $cmd". use strict; +use IO::Handle; binmode STDIN; binmode STDOUT; diff --git a/tools/testing/selftests/kselftest/runner.sh b/tools/testing/selftests/kselftest/runner.sh index 84de7bc74f2c..a8d20cbb711c 100644 --- a/tools/testing/selftests/kselftest/runner.sh +++ b/tools/testing/selftests/kselftest/runner.sh @@ -79,6 +79,7 @@ run_one() if [ $rc -eq $skip_rc ]; then \ echo "not ok $test_num $TEST_HDR_MSG # SKIP" elif [ $rc -eq $timeout_rc ]; then \ + echo "#" echo "not ok $test_num $TEST_HDR_MSG # TIMEOUT" else echo "not ok $test_num $TEST_HDR_MSG # exit=$rc" diff --git a/tools/testing/selftests/net/forwarding/router_bridge_vlan.sh b/tools/testing/selftests/net/forwarding/router_bridge_vlan.sh index fef88eb4b873..fa6a88c50750 100755 --- a/tools/testing/selftests/net/forwarding/router_bridge_vlan.sh +++ b/tools/testing/selftests/net/forwarding/router_bridge_vlan.sh @@ -36,7 +36,7 @@ h2_destroy() { ip -6 route del 2001:db8:1::/64 vrf v$h2 ip -4 route del 192.0.2.0/28 vrf v$h2 - simple_if_fini $h2 192.0.2.130/28 + simple_if_fini $h2 192.0.2.130/28 2001:db8:2::2/64 } router_create() diff --git a/tools/testing/selftests/net/pmtu.sh b/tools/testing/selftests/net/pmtu.sh index d697815d2785..71a62e7e35b1 100755 --- a/tools/testing/selftests/net/pmtu.sh +++ b/tools/testing/selftests/net/pmtu.sh @@ -11,9 +11,9 @@ # R1 and R2 (also implemented with namespaces), with different MTUs: # # segment a_r1 segment b_r1 a_r1: 2000 -# .--------------R1--------------. a_r2: 1500 -# A B a_r3: 2000 -# '--------------R2--------------' a_r4: 1400 +# .--------------R1--------------. b_r1: 1400 +# A B a_r2: 2000 +# '--------------R2--------------' b_r2: 1500 # segment a_r2 segment b_r2 # # Check that PMTU exceptions with the correct PMTU are created. Then diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c index 46abcae47dee..0ea44d975b6c 100644 --- a/tools/testing/selftests/net/tls.c +++ b/tools/testing/selftests/net/tls.c @@ -25,10 +25,6 @@ #define TLS_PAYLOAD_MAX_LEN 16384 #define SOL_TLS 282 -#ifndef ENOTSUPP -#define ENOTSUPP 524 -#endif - FIXTURE(tls_basic) { int fd, cfd; @@ -726,34 +722,6 @@ TEST_F(tls, recv_lowat) EXPECT_EQ(memcmp(send_mem, recv_mem + 10, 5), 0); } -TEST_F(tls, recv_rcvbuf) -{ - char send_mem[4096]; - char recv_mem[4096]; - int rcv_buf = 1024; - - memset(send_mem, 0x1c, sizeof(send_mem)); - - EXPECT_EQ(setsockopt(self->cfd, SOL_SOCKET, SO_RCVBUF, - &rcv_buf, sizeof(rcv_buf)), 0); - - EXPECT_EQ(send(self->fd, send_mem, 512, 0), 512); - memset(recv_mem, 0, sizeof(recv_mem)); - EXPECT_EQ(recv(self->cfd, recv_mem, sizeof(recv_mem), 0), 512); - EXPECT_EQ(memcmp(send_mem, recv_mem, 512), 0); - - if (self->notls) - return; - - EXPECT_EQ(send(self->fd, send_mem, 4096, 0), 4096); - memset(recv_mem, 0, sizeof(recv_mem)); - EXPECT_EQ(recv(self->cfd, recv_mem, sizeof(recv_mem), 0), -1); - EXPECT_EQ(errno, EMSGSIZE); - - EXPECT_EQ(recv(self->cfd, recv_mem, sizeof(recv_mem), 0), -1); - EXPECT_EQ(errno, EMSGSIZE); -} - TEST_F(tls, bidir) { char const *test_str = "test_read"; @@ -1205,11 +1173,11 @@ TEST(non_established) { /* TLS ULP not supported */ if (errno == ENOENT) return; - EXPECT_EQ(errno, ENOTSUPP); + EXPECT_EQ(errno, ENOTCONN); ret = setsockopt(sfd, IPPROTO_TCP, TCP_ULP, "tls", sizeof("tls")); EXPECT_EQ(ret, -1); - EXPECT_EQ(errno, ENOTSUPP); + EXPECT_EQ(errno, ENOTCONN); ret = getsockname(sfd, &addr, &len); ASSERT_EQ(ret, 0); diff --git a/tools/testing/selftests/netfilter/nft_nat.sh b/tools/testing/selftests/netfilter/nft_nat.sh index 1be55e705780..d7e07f4c3d7f 100755 --- a/tools/testing/selftests/netfilter/nft_nat.sh +++ b/tools/testing/selftests/netfilter/nft_nat.sh @@ -8,9 +8,14 @@ ksft_skip=4 ret=0 test_inet_nat=true +sfx=$(mktemp -u "XXXXXXXX") +ns0="ns0-$sfx" +ns1="ns1-$sfx" +ns2="ns2-$sfx" + cleanup() { - for i in 0 1 2; do ip netns del ns$i;done + for i in 0 1 2; do ip netns del ns$i-"$sfx";done } nft --version > /dev/null 2>&1 @@ -25,40 +30,49 @@ if [ $? -ne 0 ];then exit $ksft_skip fi -ip netns add ns0 +ip netns add "$ns0" if [ $? -ne 0 ];then - echo "SKIP: Could not create net namespace" + echo "SKIP: Could not create net namespace $ns0" exit $ksft_skip fi trap cleanup EXIT -ip netns add ns1 -ip netns add ns2 +ip netns add "$ns1" +if [ $? -ne 0 ];then + echo "SKIP: Could not create net namespace $ns1" + exit $ksft_skip +fi + +ip netns add "$ns2" +if [ $? -ne 0 ];then + echo "SKIP: Could not create net namespace $ns2" + exit $ksft_skip +fi -ip link add veth0 netns ns0 type veth peer name eth0 netns ns1 > /dev/null 2>&1 +ip link add veth0 netns "$ns0" type veth peer name eth0 netns "$ns1" > /dev/null 2>&1 if [ $? -ne 0 ];then echo "SKIP: No virtual ethernet pair device support in kernel" exit $ksft_skip fi -ip link add veth1 netns ns0 type veth peer name eth0 netns ns2 +ip link add veth1 netns "$ns0" type veth peer name eth0 netns "$ns2" -ip -net ns0 link set lo up -ip -net ns0 link set veth0 up -ip -net ns0 addr add 10.0.1.1/24 dev veth0 -ip -net ns0 addr add dead:1::1/64 dev veth0 +ip -net "$ns0" link set lo up +ip -net "$ns0" link set veth0 up +ip -net "$ns0" addr add 10.0.1.1/24 dev veth0 +ip -net "$ns0" addr add dead:1::1/64 dev veth0 -ip -net ns0 link set veth1 up -ip -net ns0 addr add 10.0.2.1/24 dev veth1 -ip -net ns0 addr add dead:2::1/64 dev veth1 +ip -net "$ns0" link set veth1 up +ip -net "$ns0" addr add 10.0.2.1/24 dev veth1 +ip -net "$ns0" addr add dead:2::1/64 dev veth1 for i in 1 2; do - ip -net ns$i link set lo up - ip -net ns$i link set eth0 up - ip -net ns$i addr add 10.0.$i.99/24 dev eth0 - ip -net ns$i route add default via 10.0.$i.1 - ip -net ns$i addr add dead:$i::99/64 dev eth0 - ip -net ns$i route add default via dead:$i::1 + ip -net ns$i-$sfx link set lo up + ip -net ns$i-$sfx link set eth0 up + ip -net ns$i-$sfx addr add 10.0.$i.99/24 dev eth0 + ip -net ns$i-$sfx route add default via 10.0.$i.1 + ip -net ns$i-$sfx addr add dead:$i::99/64 dev eth0 + ip -net ns$i-$sfx route add default via dead:$i::1 done bad_counter() @@ -66,8 +80,9 @@ bad_counter() local ns=$1 local counter=$2 local expect=$3 + local tag=$4 - echo "ERROR: $counter counter in $ns has unexpected value (expected $expect)" 1>&2 + echo "ERROR: $counter counter in $ns has unexpected value (expected $expect) at $tag" 1>&2 ip netns exec $ns nft list counter inet filter $counter 1>&2 } @@ -78,24 +93,24 @@ check_counters() cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84") if [ $? -ne 0 ]; then - bad_counter $ns ns0in "packets 1 bytes 84" + bad_counter $ns ns0in "packets 1 bytes 84" "check_counters 1" lret=1 fi cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84") if [ $? -ne 0 ]; then - bad_counter $ns ns0out "packets 1 bytes 84" + bad_counter $ns ns0out "packets 1 bytes 84" "check_counters 2" lret=1 fi expect="packets 1 bytes 104" cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter $ns ns0in6 "$expect" + bad_counter $ns ns0in6 "$expect" "check_counters 3" lret=1 fi cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter $ns ns0out6 "$expect" + bad_counter $ns ns0out6 "$expect" "check_counters 4" lret=1 fi @@ -107,41 +122,41 @@ check_ns0_counters() local ns=$1 local lret=0 - cnt=$(ip netns exec ns0 nft list counter inet filter ns0in | grep -q "packets 0 bytes 0") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0in | grep -q "packets 0 bytes 0") if [ $? -ne 0 ]; then - bad_counter ns0 ns0in "packets 0 bytes 0" + bad_counter "$ns0" ns0in "packets 0 bytes 0" "check_ns0_counters 1" lret=1 fi - cnt=$(ip netns exec ns0 nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0") if [ $? -ne 0 ]; then - bad_counter ns0 ns0in6 "packets 0 bytes 0" + bad_counter "$ns0" ns0in6 "packets 0 bytes 0" lret=1 fi - cnt=$(ip netns exec ns0 nft list counter inet filter ns0out | grep -q "packets 0 bytes 0") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0out | grep -q "packets 0 bytes 0") if [ $? -ne 0 ]; then - bad_counter ns0 ns0out "packets 0 bytes 0" + bad_counter "$ns0" ns0out "packets 0 bytes 0" "check_ns0_counters 2" lret=1 fi - cnt=$(ip netns exec ns0 nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0") if [ $? -ne 0 ]; then - bad_counter ns0 ns0out6 "packets 0 bytes 0" + bad_counter "$ns0" ns0out6 "packets 0 bytes 0" "check_ns0_counters3 " lret=1 fi for dir in "in" "out" ; do expect="packets 1 bytes 84" - cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ${ns}${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns0 $ns$dir "$expect" + bad_counter "$ns0" $ns$dir "$expect" "check_ns0_counters 4" lret=1 fi expect="packets 1 bytes 104" - cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir}6 | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ${ns}${dir}6 | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns0 $ns$dir6 "$expect" + bad_counter "$ns0" $ns$dir6 "$expect" "check_ns0_counters 5" lret=1 fi done @@ -152,7 +167,7 @@ check_ns0_counters() reset_counters() { for i in 0 1 2;do - ip netns exec ns$i nft reset counters inet > /dev/null + ip netns exec ns$i-$sfx nft reset counters inet > /dev/null done } @@ -166,7 +181,7 @@ test_local_dnat6() IPF="ip6" fi -ip netns exec ns0 nft -f - <<EOF +ip netns exec "$ns0" nft -f /dev/stdin <<EOF table $family nat { chain output { type nat hook output priority 0; policy accept; @@ -180,7 +195,7 @@ EOF fi # ping netns1, expect rewrite to netns2 - ip netns exec ns0 ping -q -c 1 dead:1::99 > /dev/null + ip netns exec "$ns0" ping -q -c 1 dead:1::99 > /dev/null if [ $? -ne 0 ]; then lret=1 echo "ERROR: ping6 failed" @@ -189,18 +204,18 @@ EOF expect="packets 0 bytes 0" for dir in "in6" "out6" ; do - cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns0 ns1$dir "$expect" + bad_counter "$ns0" ns1$dir "$expect" "test_local_dnat6 1" lret=1 fi done expect="packets 1 bytes 104" for dir in "in6" "out6" ; do - cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns0 ns2$dir "$expect" + bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat6 2" lret=1 fi done @@ -208,9 +223,9 @@ EOF # expect 0 count in ns1 expect="packets 0 bytes 0" for dir in "in6" "out6" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns0$dir "$expect" + bad_counter "$ns1" ns0$dir "$expect" "test_local_dnat6 3" lret=1 fi done @@ -218,15 +233,15 @@ EOF # expect 1 packet in ns2 expect="packets 1 bytes 104" for dir in "in6" "out6" ; do - cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns0$dir "$expect" + bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat6 4" lret=1 fi done - test $lret -eq 0 && echo "PASS: ipv6 ping to ns1 was $family NATted to ns2" - ip netns exec ns0 nft flush chain ip6 nat output + test $lret -eq 0 && echo "PASS: ipv6 ping to $ns1 was $family NATted to $ns2" + ip netns exec "$ns0" nft flush chain ip6 nat output return $lret } @@ -241,7 +256,7 @@ test_local_dnat() IPF="ip" fi -ip netns exec ns0 nft -f - <<EOF 2>/dev/null +ip netns exec "$ns0" nft -f /dev/stdin <<EOF 2>/dev/null table $family nat { chain output { type nat hook output priority 0; policy accept; @@ -260,7 +275,7 @@ EOF fi # ping netns1, expect rewrite to netns2 - ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null + ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null if [ $? -ne 0 ]; then lret=1 echo "ERROR: ping failed" @@ -269,18 +284,18 @@ EOF expect="packets 0 bytes 0" for dir in "in" "out" ; do - cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns0 ns1$dir "$expect" + bad_counter "$ns0" ns1$dir "$expect" "test_local_dnat 1" lret=1 fi done expect="packets 1 bytes 84" for dir in "in" "out" ; do - cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns0 ns2$dir "$expect" + bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat 2" lret=1 fi done @@ -288,9 +303,9 @@ EOF # expect 0 count in ns1 expect="packets 0 bytes 0" for dir in "in" "out" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns0$dir "$expect" + bad_counter "$ns1" ns0$dir "$expect" "test_local_dnat 3" lret=1 fi done @@ -298,19 +313,19 @@ EOF # expect 1 packet in ns2 expect="packets 1 bytes 84" for dir in "in" "out" ; do - cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns0$dir "$expect" + bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat 4" lret=1 fi done - test $lret -eq 0 && echo "PASS: ping to ns1 was $family NATted to ns2" + test $lret -eq 0 && echo "PASS: ping to $ns1 was $family NATted to $ns2" - ip netns exec ns0 nft flush chain $family nat output + ip netns exec "$ns0" nft flush chain $family nat output reset_counters - ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null + ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null if [ $? -ne 0 ]; then lret=1 echo "ERROR: ping failed" @@ -319,17 +334,17 @@ EOF expect="packets 1 bytes 84" for dir in "in" "out" ; do - cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns1$dir "$expect" + bad_counter "$ns1" ns1$dir "$expect" "test_local_dnat 5" lret=1 fi done expect="packets 0 bytes 0" for dir in "in" "out" ; do - cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns0 ns2$dir "$expect" + bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat 6" lret=1 fi done @@ -337,9 +352,9 @@ EOF # expect 1 count in ns1 expect="packets 1 bytes 84" for dir in "in" "out" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns0 ns0$dir "$expect" + bad_counter "$ns0" ns0$dir "$expect" "test_local_dnat 7" lret=1 fi done @@ -347,14 +362,14 @@ EOF # expect 0 packet in ns2 expect="packets 0 bytes 0" for dir in "in" "out" ; do - cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns2$dir "$expect" + bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat 8" lret=1 fi done - test $lret -eq 0 && echo "PASS: ping to ns1 OK after $family nat output chain flush" + test $lret -eq 0 && echo "PASS: ping to $ns1 OK after $family nat output chain flush" return $lret } @@ -366,26 +381,26 @@ test_masquerade6() local natflags=$2 local lret=0 - ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null + ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null - ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 + ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping ns1 from ns2 via ipv6" + echo "ERROR: cannot ping $ns1 from $ns2 via ipv6" return 1 lret=1 fi expect="packets 1 bytes 104" for dir in "in6" "out6" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns2$dir "$expect" + bad_counter "$ns1" ns2$dir "$expect" "test_masquerade6 1" lret=1 fi - cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns1$dir "$expect" + bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 2" lret=1 fi done @@ -393,7 +408,7 @@ test_masquerade6() reset_counters # add masquerading rule -ip netns exec ns0 nft -f - <<EOF +ip netns exec "$ns0" nft -f /dev/stdin <<EOF table $family nat { chain postrouting { type nat hook postrouting priority 0; policy accept; @@ -406,24 +421,24 @@ EOF return $ksft_skip fi - ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 + ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping ns1 from ns2 with active $family masquerade $natflags" + echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags" lret=1 fi # ns1 should have seen packets from ns0, due to masquerade expect="packets 1 bytes 104" for dir in "in6" "out6" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns0$dir "$expect" + bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 3" lret=1 fi - cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns1$dir "$expect" + bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 4" lret=1 fi done @@ -431,32 +446,32 @@ EOF # ns1 should not have seen packets from ns2, due to masquerade expect="packets 0 bytes 0" for dir in "in6" "out6" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns0$dir "$expect" + bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 5" lret=1 fi - cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns1$dir "$expect" + bad_counter "$ns0" ns1$dir "$expect" "test_masquerade6 6" lret=1 fi done - ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 + ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerade $natflags (attempt 2)" + echo "ERROR: cannot ping $ns1 from $ns2 with active ipv6 masquerade $natflags (attempt 2)" lret=1 fi - ip netns exec ns0 nft flush chain $family nat postrouting + ip netns exec "$ns0" nft flush chain $family nat postrouting if [ $? -ne 0 ]; then echo "ERROR: Could not flush $family nat postrouting" 1>&2 lret=1 fi - test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for ns2" + test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for $ns2" return $lret } @@ -467,26 +482,26 @@ test_masquerade() local natflags=$2 local lret=0 - ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null - ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null + ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null + ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null - ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 + ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping ns1 from ns2 $natflags" + echo "ERROR: cannot ping $ns1 from "$ns2" $natflags" lret=1 fi expect="packets 1 bytes 84" for dir in "in" "out" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns2$dir "$expect" + bad_counter "$ns1" ns2$dir "$expect" "test_masquerade 1" lret=1 fi - cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns1$dir "$expect" + bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 2" lret=1 fi done @@ -494,7 +509,7 @@ test_masquerade() reset_counters # add masquerading rule -ip netns exec ns0 nft -f - <<EOF +ip netns exec "$ns0" nft -f /dev/stdin <<EOF table $family nat { chain postrouting { type nat hook postrouting priority 0; policy accept; @@ -507,24 +522,24 @@ EOF return $ksft_skip fi - ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 + ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping ns1 from ns2 with active $family masquerade $natflags" + echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags" lret=1 fi # ns1 should have seen packets from ns0, due to masquerade expect="packets 1 bytes 84" for dir in "in" "out" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns0$dir "$expect" + bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 3" lret=1 fi - cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns1$dir "$expect" + bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 4" lret=1 fi done @@ -532,32 +547,32 @@ EOF # ns1 should not have seen packets from ns2, due to masquerade expect="packets 0 bytes 0" for dir in "in" "out" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns0$dir "$expect" + bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 5" lret=1 fi - cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns1$dir "$expect" + bad_counter "$ns0" ns1$dir "$expect" "test_masquerade 6" lret=1 fi done - ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 + ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping ns1 from ns2 with active ip masquerade $natflags (attempt 2)" + echo "ERROR: cannot ping $ns1 from $ns2 with active ip masquerade $natflags (attempt 2)" lret=1 fi - ip netns exec ns0 nft flush chain $family nat postrouting + ip netns exec "$ns0" nft flush chain $family nat postrouting if [ $? -ne 0 ]; then echo "ERROR: Could not flush $family nat postrouting" 1>&2 lret=1 fi - test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for ns2" + test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for $ns2" return $lret } @@ -567,25 +582,25 @@ test_redirect6() local family=$1 local lret=0 - ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null + ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null - ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 + ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 if [ $? -ne 0 ] ; then - echo "ERROR: cannnot ping ns1 from ns2 via ipv6" + echo "ERROR: cannnot ping $ns1 from $ns2 via ipv6" lret=1 fi expect="packets 1 bytes 104" for dir in "in6" "out6" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns2$dir "$expect" + bad_counter "$ns1" ns2$dir "$expect" "test_redirect6 1" lret=1 fi - cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns1$dir "$expect" + bad_counter "$ns2" ns1$dir "$expect" "test_redirect6 2" lret=1 fi done @@ -593,7 +608,7 @@ test_redirect6() reset_counters # add redirect rule -ip netns exec ns0 nft -f - <<EOF +ip netns exec "$ns0" nft -f /dev/stdin <<EOF table $family nat { chain prerouting { type nat hook prerouting priority 0; policy accept; @@ -606,18 +621,18 @@ EOF return $ksft_skip fi - ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 + ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1 if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping ns1 from ns2 via ipv6 with active $family redirect" + echo "ERROR: cannot ping $ns1 from $ns2 via ipv6 with active $family redirect" lret=1 fi # ns1 should have seen no packets from ns2, due to redirection expect="packets 0 bytes 0" for dir in "in6" "out6" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns0$dir "$expect" + bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 3" lret=1 fi done @@ -625,20 +640,20 @@ EOF # ns0 should have seen packets from ns2, due to masquerade expect="packets 1 bytes 104" for dir in "in6" "out6" ; do - cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns0$dir "$expect" + bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 4" lret=1 fi done - ip netns exec ns0 nft delete table $family nat + ip netns exec "$ns0" nft delete table $family nat if [ $? -ne 0 ]; then echo "ERROR: Could not delete $family nat table" 1>&2 lret=1 fi - test $lret -eq 0 && echo "PASS: $family IPv6 redirection for ns2" + test $lret -eq 0 && echo "PASS: $family IPv6 redirection for $ns2" return $lret } @@ -648,26 +663,26 @@ test_redirect() local family=$1 local lret=0 - ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null - ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null + ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null + ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null - ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 + ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping ns1 from ns2" + echo "ERROR: cannot ping $ns1 from $ns2" lret=1 fi expect="packets 1 bytes 84" for dir in "in" "out" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns2$dir "$expect" + bad_counter "$ns1" $ns2$dir "$expect" "test_redirect 1" lret=1 fi - cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns2 ns1$dir "$expect" + bad_counter "$ns2" ns1$dir "$expect" "test_redirect 2" lret=1 fi done @@ -675,7 +690,7 @@ test_redirect() reset_counters # add redirect rule -ip netns exec ns0 nft -f - <<EOF +ip netns exec "$ns0" nft -f /dev/stdin <<EOF table $family nat { chain prerouting { type nat hook prerouting priority 0; policy accept; @@ -688,9 +703,9 @@ EOF return $ksft_skip fi - ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 + ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1 if [ $? -ne 0 ] ; then - echo "ERROR: cannot ping ns1 from ns2 with active $family ip redirect" + echo "ERROR: cannot ping $ns1 from $ns2 with active $family ip redirect" lret=1 fi @@ -698,9 +713,9 @@ EOF expect="packets 0 bytes 0" for dir in "in" "out" ; do - cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns0$dir "$expect" + bad_counter "$ns1" ns0$dir "$expect" "test_redirect 3" lret=1 fi done @@ -708,28 +723,28 @@ EOF # ns0 should have seen packets from ns2, due to masquerade expect="packets 1 bytes 84" for dir in "in" "out" ; do - cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect") + cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect") if [ $? -ne 0 ]; then - bad_counter ns1 ns0$dir "$expect" + bad_counter "$ns0" ns0$dir "$expect" "test_redirect 4" lret=1 fi done - ip netns exec ns0 nft delete table $family nat + ip netns exec "$ns0" nft delete table $family nat if [ $? -ne 0 ]; then echo "ERROR: Could not delete $family nat table" 1>&2 lret=1 fi - test $lret -eq 0 && echo "PASS: $family IP redirection for ns2" + test $lret -eq 0 && echo "PASS: $family IP redirection for $ns2" return $lret } -# ip netns exec ns0 ping -c 1 -q 10.0.$i.99 +# ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99 for i in 0 1 2; do -ip netns exec ns$i nft -f - <<EOF +ip netns exec ns$i-$sfx nft -f /dev/stdin <<EOF table inet filter { counter ns0in {} counter ns1in {} @@ -796,18 +811,18 @@ done sleep 3 # test basic connectivity for i in 1 2; do - ip netns exec ns0 ping -c 1 -q 10.0.$i.99 > /dev/null + ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99 > /dev/null if [ $? -ne 0 ];then echo "ERROR: Could not reach other namespace(s)" 1>&2 ret=1 fi - ip netns exec ns0 ping -c 1 -q dead:$i::99 > /dev/null + ip netns exec "$ns0" ping -c 1 -q dead:$i::99 > /dev/null if [ $? -ne 0 ];then echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2 ret=1 fi - check_counters ns$i + check_counters ns$i-$sfx if [ $? -ne 0 ]; then ret=1 fi @@ -820,7 +835,7 @@ for i in 1 2; do done if [ $ret -eq 0 ];then - echo "PASS: netns routing/connectivity: ns0 can reach ns1 and ns2" + echo "PASS: netns routing/connectivity: $ns0 can reach $ns1 and $ns2" fi reset_counters @@ -846,4 +861,9 @@ reset_counters $test_inet_nat && test_redirect inet $test_inet_nat && test_redirect6 inet +if [ $ret -ne 0 ];then + echo -n "FAIL: " + nft --version +fi + exit $ret diff --git a/tools/testing/selftests/safesetid/Makefile b/tools/testing/selftests/safesetid/Makefile index 98da7a504737..fa02c4d5ec13 100644 --- a/tools/testing/selftests/safesetid/Makefile +++ b/tools/testing/selftests/safesetid/Makefile @@ -1,8 +1,9 @@ # SPDX-License-Identifier: GPL-2.0 # Makefile for mount selftests. -CFLAGS = -Wall -lcap -O2 +CFLAGS = -Wall -O2 +LDLIBS = -lcap -TEST_PROGS := run_tests.sh +TEST_PROGS := safesetid-test.sh TEST_GEN_FILES := safesetid-test include ../lib.mk diff --git a/tools/testing/selftests/safesetid/safesetid-test.c b/tools/testing/selftests/safesetid/safesetid-test.c index 8f40c6ecdad1..0c4d50644c13 100644 --- a/tools/testing/selftests/safesetid/safesetid-test.c +++ b/tools/testing/selftests/safesetid/safesetid-test.c @@ -213,7 +213,8 @@ static void test_setuid(uid_t child_uid, bool expect_success) } if (cpid == 0) { /* Code executed by child */ - setuid(child_uid); + if (setuid(child_uid) < 0) + exit(EXIT_FAILURE); if (getuid() == child_uid) exit(EXIT_SUCCESS); else @@ -291,8 +292,10 @@ int main(int argc, char **argv) // First test to make sure we can write userns mappings from a user // that doesn't have any restrictions (as long as it has CAP_SETUID); - setuid(NO_POLICY_USER); - setgid(NO_POLICY_USER); + if (setuid(NO_POLICY_USER) < 0) + die("Error with set uid(%d)\n", NO_POLICY_USER); + if (setgid(NO_POLICY_USER) < 0) + die("Error with set gid(%d)\n", NO_POLICY_USER); // Take away all but setid caps drop_caps(true); @@ -306,8 +309,10 @@ int main(int argc, char **argv) die("test_userns failed when it should work\n"); } - setuid(RESTRICTED_PARENT); - setgid(RESTRICTED_PARENT); + if (setuid(RESTRICTED_PARENT) < 0) + die("Error with set uid(%d)\n", RESTRICTED_PARENT); + if (setgid(RESTRICTED_PARENT) < 0) + die("Error with set gid(%d)\n", RESTRICTED_PARENT); test_setuid(ROOT_USER, false); test_setuid(ALLOWED_CHILD1, true); diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/basic.json b/tools/testing/selftests/tc-testing/tc-tests/filters/basic.json index 76ae03a64506..2e361cea63bc 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/filters/basic.json +++ b/tools/testing/selftests/tc-testing/tc-tests/filters/basic.json @@ -152,7 +152,7 @@ ] }, { - "id": "6f5e", + "id": "b99c", "name": "Add basic filter with cmp ematch u8/transport layer and default action", "category": [ "filter", diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json index 0f89cd50a94b..8877f7b2b809 100644 --- a/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json +++ b/tools/testing/selftests/tc-testing/tc-tests/filters/tests.json @@ -1,27 +1,5 @@ [ { - "id": "e9a3", - "name": "Add u32 with source match", - "category": [ - "filter", - "u32" - ], - "plugins": { - "requires": "nsPlugin" - }, - "setup": [ - "$TC qdisc add dev $DEV1 ingress" - ], - "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: protocol ip prio 1 u32 match ip src 127.0.0.1/32 flowid 1:1 action ok", - "expExitCode": "0", - "verifyCmd": "$TC filter show dev $DEV1 parent ffff:", - "matchPattern": "match 7f000001/ffffffff at 12", - "matchCount": "1", - "teardown": [ - "$TC qdisc del dev $DEV1 ingress" - ] - }, - { "id": "2638", "name": "Add matchall and try to get it", "category": [ diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/u32.json b/tools/testing/selftests/tc-testing/tc-tests/filters/u32.json new file mode 100644 index 000000000000..e09d3c0e307f --- /dev/null +++ b/tools/testing/selftests/tc-testing/tc-tests/filters/u32.json @@ -0,0 +1,205 @@ +[ + { + "id": "afa9", + "name": "Add u32 with source match", + "category": [ + "filter", + "u32" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.1/32 flowid 1:1 action ok", + "expExitCode": "0", + "verifyCmd": "$TC filter show dev $DEV1 ingress", + "matchPattern": "filter protocol ip pref 1 u32 chain (0[ ]+$|0 fh 800: ht divisor 1|0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1.*match 7f000001/ffffffff at 12)", + "matchCount": "3", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" + ] + }, + { + "id": "6aa7", + "name": "Add/Replace u32 with source match and invalid indev", + "category": [ + "filter", + "u32" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.1/32 indev notexist20 flowid 1:1 action ok", + "expExitCode": "2", + "verifyCmd": "$TC filter show dev $DEV1 ingress", + "matchPattern": "filter protocol ip pref 1 u32 chain 0", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" + ] + }, + { + "id": "bc4d", + "name": "Replace valid u32 with source match and invalid indev", + "category": [ + "filter", + "u32" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$TC qdisc add dev $DEV1 ingress", + "$TC filter add dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.3/32 flowid 1:3 action ok" + ], + "cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.2/32 indev notexist20 flowid 1:2 action ok", + "expExitCode": "2", + "verifyCmd": "$TC filter show dev $DEV1 ingress", + "matchPattern": "filter protocol ip pref 1 u32 chain (0[ ]+$|0 fh 800: ht divisor 1|0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:3.*match 7f000003/ffffffff at 12)", + "matchCount": "3", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" + ] + }, + { + "id": "648b", + "name": "Add u32 with custom hash table", + "category": [ + "filter", + "u32" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 ingress prio 99 handle 42: u32 divisor 256", + "expExitCode": "0", + "verifyCmd": "$TC filter show dev $DEV1 ingress", + "matchPattern": "pref 99 u32 chain (0[ ]+$|0 fh 42: ht divisor 256|0 fh 800: ht divisor 1)", + "matchCount": "3", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" + ] + }, + { + "id": "6658", + "name": "Add/Replace u32 with custom hash table and invalid handle", + "category": [ + "filter", + "u32" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter replace dev $DEV1 ingress prio 99 handle 42:42 u32 divisor 256", + "expExitCode": "2", + "verifyCmd": "$TC filter show dev $DEV1 ingress", + "matchPattern": "pref 99 u32 chain 0", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" + ] + }, + { + "id": "9d0a", + "name": "Replace valid u32 with custom hash table and invalid handle", + "category": [ + "filter", + "u32" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$TC qdisc add dev $DEV1 ingress", + "$TC filter add dev $DEV1 ingress prio 99 handle 42: u32 divisor 256" + ], + "cmdUnderTest": "$TC filter replace dev $DEV1 ingress prio 99 handle 42:42 u32 divisor 128", + "expExitCode": "2", + "verifyCmd": "$TC filter show dev $DEV1 ingress", + "matchPattern": "pref 99 u32 chain (0[ ]+$|0 fh 42: ht divisor 256|0 fh 800: ht divisor 1)", + "matchCount": "3", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" + ] + }, + { + "id": "1644", + "name": "Add u32 filter that links to a custom hash table", + "category": [ + "filter", + "u32" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$TC qdisc add dev $DEV1 ingress", + "$TC filter add dev $DEV1 ingress prio 99 handle 43: u32 divisor 256" + ], + "cmdUnderTest": "$TC filter add dev $DEV1 ingress protocol ip prio 98 u32 link 43: hashkey mask 0x0000ff00 at 12 match ip src 192.168.0.0/16", + "expExitCode": "0", + "verifyCmd": "$TC filter show dev $DEV1 ingress", + "matchPattern": "filter protocol ip pref 98 u32 chain (0[ ]+$|0 fh 801: ht divisor 1|0 fh 801::800 order 2048 key ht 801 bkt 0 link 43:.*match c0a80000/ffff0000 at 12.*hash mask 0000ff00 at 12)", + "matchCount": "3", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" + ] + }, + { + "id": "74c2", + "name": "Add/Replace u32 filter with invalid hash table id", + "category": [ + "filter", + "u32" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$TC qdisc add dev $DEV1 ingress" + ], + "cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 20 u32 ht 47:47 action drop", + "expExitCode": "2", + "verifyCmd": "$TC filter show dev $DEV1 ingress", + "matchPattern": "filter protocol ip pref 20 u32 chain 0", + "matchCount": "0", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" + ] + }, + { + "id": "1fe6", + "name": "Replace valid u32 filter with invalid hash table id", + "category": [ + "filter", + "u32" + ], + "plugins": { + "requires": "nsPlugin" + }, + "setup": [ + "$TC qdisc add dev $DEV1 ingress", + "$TC filter add dev $DEV1 ingress protocol ip prio 99 handle 43: u32 divisor 1", + "$TC filter add dev $DEV1 ingress protocol ip prio 98 u32 ht 43: match tcp src 22 FFFF classid 1:3" + ], + "cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 98 u32 ht 43:1 match tcp src 23 FFFF classid 1:4", + "expExitCode": "2", + "verifyCmd": "$TC filter show dev $DEV1 ingress", + "matchPattern": "filter protocol ip pref 99 u32 chain (0[ ]+$|0 fh (43|800): ht divisor 1|0 fh 43::800 order 2048 key ht 43 bkt 0 flowid 1:3.*match 00160000/ffff0000 at nexthdr\\+0)", + "matchCount": "4", + "teardown": [ + "$TC qdisc del dev $DEV1 ingress" + ] + } +] diff --git a/tools/testing/selftests/tpm2/test_smoke.sh b/tools/testing/selftests/tpm2/test_smoke.sh index 80521d46220c..8155c2ea7ccb 100755 --- a/tools/testing/selftests/tpm2/test_smoke.sh +++ b/tools/testing/selftests/tpm2/test_smoke.sh @@ -2,3 +2,9 @@ # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) python -m unittest -v tpm2_tests.SmokeTest +python -m unittest -v tpm2_tests.AsyncTest + +CLEAR_CMD=$(which tpm2_clear) +if [ -n $CLEAR_CMD ]; then + tpm2_clear -T device +fi diff --git a/tools/testing/selftests/tpm2/tpm2.py b/tools/testing/selftests/tpm2/tpm2.py index 828c18584624..d0fcb66a88a6 100644 --- a/tools/testing/selftests/tpm2/tpm2.py +++ b/tools/testing/selftests/tpm2/tpm2.py @@ -6,8 +6,8 @@ import socket import struct import sys import unittest -from fcntl import ioctl - +import fcntl +import select TPM2_ST_NO_SESSIONS = 0x8001 TPM2_ST_SESSIONS = 0x8002 @@ -352,6 +352,7 @@ def hex_dump(d): class Client: FLAG_DEBUG = 0x01 FLAG_SPACE = 0x02 + FLAG_NONBLOCK = 0x04 TPM_IOC_NEW_SPACE = 0xa200 def __init__(self, flags = 0): @@ -362,13 +363,27 @@ class Client: else: self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0) + if (self.flags & Client.FLAG_NONBLOCK): + flags = fcntl.fcntl(self.tpm, fcntl.F_GETFL) + flags |= os.O_NONBLOCK + fcntl.fcntl(self.tpm, fcntl.F_SETFL, flags) + self.tpm_poll = select.poll() + def close(self): self.tpm.close() def send_cmd(self, cmd): self.tpm.write(cmd) + + if (self.flags & Client.FLAG_NONBLOCK): + self.tpm_poll.register(self.tpm, select.POLLIN) + self.tpm_poll.poll(10000) + rsp = self.tpm.read() + if (self.flags & Client.FLAG_NONBLOCK): + self.tpm_poll.unregister(self.tpm) + if (self.flags & Client.FLAG_DEBUG) != 0: sys.stderr.write('cmd' + os.linesep) sys.stderr.write(hex_dump(cmd) + os.linesep) diff --git a/tools/testing/selftests/tpm2/tpm2_tests.py b/tools/testing/selftests/tpm2/tpm2_tests.py index d4973be53493..728be7c69b76 100644 --- a/tools/testing/selftests/tpm2/tpm2_tests.py +++ b/tools/testing/selftests/tpm2/tpm2_tests.py @@ -288,3 +288,16 @@ class SpaceTest(unittest.TestCase): self.assertEqual(rc, tpm2.TPM2_RC_COMMAND_CODE | tpm2.TSS2_RESMGR_TPM_RC_LAYER) + +class AsyncTest(unittest.TestCase): + def setUp(self): + logging.basicConfig(filename='AsyncTest.log', level=logging.DEBUG) + + def test_async(self): + log = logging.getLogger(__name__) + log.debug(sys._getframe().f_code.co_name) + + async_client = tpm2.Client(tpm2.Client.FLAG_NONBLOCK) + log.debug("Calling get_cap in a NON_BLOCKING mode") + async_client.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_LOADED_SESSION) + async_client.close() |