1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
3 
4 #include <errno.h>
5 #include <sys/syscall.h>
6 #include <unistd.h>
7 
8 #include "test_map_ops.skel.h"
9 #include "test_progs.h"
10 
11 static void map_update(void)
12 {
13 	(void)syscall(__NR_getpid);
14 }
15 
16 static void map_delete(void)
17 {
18 	(void)syscall(__NR_getppid);
19 }
20 
21 static void map_push(void)
22 {
23 	(void)syscall(__NR_getuid);
24 }
25 
26 static void map_pop(void)
27 {
28 	(void)syscall(__NR_geteuid);
29 }
30 
31 static void map_peek(void)
32 {
33 	(void)syscall(__NR_getgid);
34 }
35 
36 static void map_for_each_pass(void)
37 {
38 	(void)syscall(__NR_gettid);
39 }
40 
41 static void map_for_each_fail(void)
42 {
43 	(void)syscall(__NR_getpgid);
44 }
45 
46 static int setup(struct test_map_ops **skel)
47 {
48 	int err = 0;
49 
50 	if (!skel)
51 		return -1;
52 
53 	*skel = test_map_ops__open();
54 	if (!ASSERT_OK_PTR(*skel, "test_map_ops__open"))
55 		return -1;
56 
57 	(*skel)->rodata->pid = getpid();
58 
59 	err = test_map_ops__load(*skel);
60 	if (!ASSERT_OK(err, "test_map_ops__load"))
61 		return err;
62 
63 	err = test_map_ops__attach(*skel);
64 	if (!ASSERT_OK(err, "test_map_ops__attach"))
65 		return err;
66 
67 	return err;
68 }
69 
70 static void teardown(struct test_map_ops **skel)
71 {
72 	if (skel && *skel)
73 		test_map_ops__destroy(*skel);
74 }
75 
76 static void map_ops_update_delete_subtest(void)
77 {
78 	struct test_map_ops *skel;
79 
80 	if (setup(&skel))
81 		goto teardown;
82 
83 	map_update();
84 	ASSERT_OK(skel->bss->err, "map_update_initial");
85 
86 	map_update();
87 	ASSERT_LT(skel->bss->err, 0, "map_update_existing");
88 	ASSERT_EQ(skel->bss->err, -EEXIST, "map_update_existing");
89 
90 	map_delete();
91 	ASSERT_OK(skel->bss->err, "map_delete_existing");
92 
93 	map_delete();
94 	ASSERT_LT(skel->bss->err, 0, "map_delete_non_existing");
95 	ASSERT_EQ(skel->bss->err, -ENOENT, "map_delete_non_existing");
96 
97 teardown:
98 	teardown(&skel);
99 }
100 
101 static void map_ops_push_peek_pop_subtest(void)
102 {
103 	struct test_map_ops *skel;
104 
105 	if (setup(&skel))
106 		goto teardown;
107 
108 	map_push();
109 	ASSERT_OK(skel->bss->err, "map_push_initial");
110 
111 	map_push();
112 	ASSERT_LT(skel->bss->err, 0, "map_push_when_full");
113 	ASSERT_EQ(skel->bss->err, -E2BIG, "map_push_when_full");
114 
115 	map_peek();
116 	ASSERT_OK(skel->bss->err, "map_peek");
117 
118 	map_pop();
119 	ASSERT_OK(skel->bss->err, "map_pop");
120 
121 	map_peek();
122 	ASSERT_LT(skel->bss->err, 0, "map_peek_when_empty");
123 	ASSERT_EQ(skel->bss->err, -ENOENT, "map_peek_when_empty");
124 
125 	map_pop();
126 	ASSERT_LT(skel->bss->err, 0, "map_pop_when_empty");
127 	ASSERT_EQ(skel->bss->err, -ENOENT, "map_pop_when_empty");
128 
129 teardown:
130 	teardown(&skel);
131 }
132 
133 static void map_ops_for_each_subtest(void)
134 {
135 	struct test_map_ops *skel;
136 
137 	if (setup(&skel))
138 		goto teardown;
139 
140 	map_for_each_pass();
141 	/* expect to iterate over 1 element */
142 	ASSERT_EQ(skel->bss->err, 1, "map_for_each_no_flags");
143 
144 	map_for_each_fail();
145 	ASSERT_LT(skel->bss->err, 0, "map_for_each_with_flags");
146 	ASSERT_EQ(skel->bss->err, -EINVAL, "map_for_each_with_flags");
147 
148 teardown:
149 	teardown(&skel);
150 }
151 
152 void test_map_ops(void)
153 {
154 	if (test__start_subtest("map_ops_update_delete"))
155 		map_ops_update_delete_subtest();
156 
157 	if (test__start_subtest("map_ops_push_peek_pop"))
158 		map_ops_push_peek_pop_subtest();
159 
160 	if (test__start_subtest("map_ops_for_each"))
161 		map_ops_for_each_subtest();
162 }
163