Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2024 Samsung Electronics Co., Ltd.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : : #include "spdk_internal/cunit.h"
8 : : #include "util/fd_group.c"
9 : :
10 : : static int
11 : 0 : fd_group_cb_fn(void *ctx)
12 : : {
13 : 0 : return 0;
14 : : }
15 : :
16 : : static void
17 : 3 : test_fd_group_basic(void)
18 : : {
19 : 3 : struct spdk_fd_group *fgrp;
20 : 3 : struct event_handler *ehdlr = NULL;
21 : : int fd;
22 : : int rc;
23 : 3 : int cb_arg;
24 : :
25 : 3 : rc = spdk_fd_group_create(&fgrp);
26 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
27 : :
28 : 3 : fd = epoll_create1(0);
29 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(fd >= 0);
30 : :
31 : 3 : rc = SPDK_FD_GROUP_ADD(fgrp, fd, fd_group_cb_fn, &cb_arg);
32 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
33 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(fgrp->num_fds == 1);
34 : :
35 : : /* Verify that event handler is initialized correctly */
36 : 3 : ehdlr = TAILQ_FIRST(&fgrp->event_handlers);
37 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ehdlr != NULL);
38 : 3 : CU_ASSERT(ehdlr->fd == fd);
39 : 3 : CU_ASSERT(ehdlr->state == EVENT_HANDLER_STATE_WAITING);
40 : 3 : CU_ASSERT(ehdlr->events == EPOLLIN);
41 : :
42 : : /* Modify event type and see if event handler is updated correctly */
43 : 3 : rc = spdk_fd_group_event_modify(fgrp, fd, EPOLLIN | EPOLLERR);
44 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
45 : :
46 : 3 : ehdlr = TAILQ_FIRST(&fgrp->event_handlers);
47 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ehdlr != NULL);
48 : 3 : CU_ASSERT(ehdlr->events == (EPOLLIN | EPOLLERR));
49 : :
50 : 3 : spdk_fd_group_remove(fgrp, fd);
51 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(fgrp->num_fds == 0);
52 : :
53 : 3 : rc = close(fd);
54 : 3 : CU_ASSERT(rc == 0);
55 : :
56 : 3 : spdk_fd_group_destroy(fgrp);
57 : 3 : }
58 : :
59 : : static void
60 : 3 : test_fd_group_nest_unnest(void)
61 : : {
62 : 3 : struct spdk_fd_group *parent, *child, *not_parent;
63 : : int fd_parent, fd_child, fd_child_2;
64 : : int rc;
65 : 3 : int cb_arg;
66 : :
67 : 3 : rc = spdk_fd_group_create(&parent);
68 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
69 : :
70 : 3 : rc = spdk_fd_group_create(&child);
71 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
72 : :
73 : 3 : rc = spdk_fd_group_create(¬_parent);
74 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
75 : :
76 : 3 : fd_parent = epoll_create1(0);
77 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(fd_parent >= 0);
78 : :
79 : 3 : fd_child = epoll_create1(0);
80 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(fd_child >= 0);
81 : :
82 : 3 : fd_child_2 = epoll_create1(0);
83 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(fd_child_2 >= 0);
84 : :
85 : 3 : rc = SPDK_FD_GROUP_ADD(parent, fd_parent, fd_group_cb_fn, &cb_arg);
86 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
87 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(parent->num_fds == 1);
88 : :
89 : 3 : rc = SPDK_FD_GROUP_ADD(child, fd_child, fd_group_cb_fn, &cb_arg);
90 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
91 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(child->num_fds == 1);
92 : :
93 : : /* Nest child fd group to a parent fd group and verify their relation */
94 : 3 : rc = spdk_fd_group_nest(parent, child);
95 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
96 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(child->parent == parent);
97 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(parent->num_fds == 2);
98 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(child->num_fds == 0);
99 : :
100 : : /* Register second child fd to the child fd group and verify that the parent fd group
101 : : * has the correct number of fds.
102 : : */
103 : 3 : rc = SPDK_FD_GROUP_ADD(child, fd_child_2, fd_group_cb_fn, &cb_arg);
104 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
105 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(child->num_fds == 0);
106 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(parent->num_fds == 3);
107 : :
108 : : /* Unnest child fd group from wrong parent fd group and verify that it fails. */
109 : 3 : rc = spdk_fd_group_unnest(not_parent, child);
110 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == -EINVAL);
111 : :
112 : : /* Unnest child fd group from its parent fd group and verify it. */
113 : 3 : rc = spdk_fd_group_unnest(parent, child);
114 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(rc == 0);
115 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(child->parent == NULL);
116 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(parent->num_fds == 1);
117 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(child->num_fds == 2);
118 : :
119 : 3 : spdk_fd_group_remove(child, fd_child);
120 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(child->num_fds == 1);
121 : :
122 : 3 : spdk_fd_group_remove(child, fd_child_2);
123 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(child->num_fds == 0);
124 : :
125 : 3 : spdk_fd_group_remove(parent, fd_parent);
126 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(parent->num_fds == 0);
127 : :
128 : 3 : rc = close(fd_child);
129 : 3 : CU_ASSERT(rc == 0);
130 : :
131 : 3 : rc = close(fd_child_2);
132 : 3 : CU_ASSERT(rc == 0);
133 : :
134 : 3 : rc = close(fd_parent);
135 : 3 : CU_ASSERT(rc == 0);
136 : :
137 : 3 : spdk_fd_group_destroy(child);
138 : 3 : spdk_fd_group_destroy(parent);
139 : 3 : spdk_fd_group_destroy(not_parent);
140 : 3 : }
141 : :
142 : : struct ut_fgrp {
143 : : struct spdk_fd_group *fgrp;
144 : : size_t num_fds;
145 : : #define UT_MAX_FDS 4
146 : : int fd[UT_MAX_FDS];
147 : : };
148 : :
149 : : static void
150 : 3 : test_fd_group_multi_nest(void)
151 : : {
152 : 3 : struct ut_fgrp fgrp[] = {
153 : : { .num_fds = 1 },
154 : : { .num_fds = 2 },
155 : : { .num_fds = 2 },
156 : : { .num_fds = 3 },
157 : : };
158 : : size_t i, j;
159 : : int fd, rc;
160 : :
161 : : /* Create four fd_groups with the folowing hierarchy:
162 : : * fgrp[0]
163 : : * (fd:0)
164 : : * |
165 : : * fgrp[1]-----+-----fgrp[2]
166 : : * (fd:1,2) (fd:3,4)
167 : : * |
168 : : * fgrp[3]
169 : : * (fd:5,6,7)
170 : : */
171 [ + + ]: 15 : for (i = 0; i < SPDK_COUNTOF(fgrp); i++) {
172 : 12 : rc = spdk_fd_group_create(&fgrp[i].fgrp);
173 [ - + ]: 12 : SPDK_CU_ASSERT_FATAL(rc == 0);
174 [ + + ]: 36 : for (j = 0; j < fgrp[i].num_fds; j++) {
175 : 24 : fgrp[i].fd[j] = fd = eventfd(0, 0);
176 : 24 : CU_ASSERT(fd >= 0);
177 : 24 : rc = SPDK_FD_GROUP_ADD(fgrp[i].fgrp, fd, fd_group_cb_fn, NULL);
178 : 24 : CU_ASSERT_EQUAL(rc, 0);
179 : : }
180 : : }
181 : :
182 : 3 : CU_ASSERT_EQUAL(fgrp[0].fgrp->num_fds, fgrp[0].num_fds);
183 : 3 : CU_ASSERT_EQUAL(fgrp[1].fgrp->num_fds, fgrp[1].num_fds);
184 : 3 : CU_ASSERT_EQUAL(fgrp[2].fgrp->num_fds, fgrp[2].num_fds);
185 : 3 : CU_ASSERT_EQUAL(fgrp[3].fgrp->num_fds, fgrp[3].num_fds);
186 : :
187 : 3 : rc = spdk_fd_group_nest(fgrp[0].fgrp, fgrp[2].fgrp);
188 : 3 : CU_ASSERT_EQUAL(rc, 0);
189 : 3 : rc = spdk_fd_group_nest(fgrp[1].fgrp, fgrp[3].fgrp);
190 : 3 : CU_ASSERT_EQUAL(rc, 0);
191 : 3 : rc = spdk_fd_group_nest(fgrp[0].fgrp, fgrp[1].fgrp);
192 : 3 : CU_ASSERT_EQUAL(rc, 0);
193 : :
194 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[0].fgrp->parent, NULL);
195 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[1].fgrp->parent, fgrp[0].fgrp);
196 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[2].fgrp->parent, fgrp[0].fgrp);
197 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[3].fgrp->parent, fgrp[1].fgrp);
198 : 3 : CU_ASSERT_EQUAL(fgrp[0].fgrp->num_fds,
199 : : fgrp[0].num_fds + fgrp[1].num_fds +
200 : : fgrp[2].num_fds + fgrp[3].num_fds);
201 : 3 : CU_ASSERT_EQUAL(fgrp[1].fgrp->num_fds, 0);
202 : 3 : CU_ASSERT_EQUAL(fgrp[2].fgrp->num_fds, 0);
203 : 3 : CU_ASSERT_EQUAL(fgrp[3].fgrp->num_fds, 0);
204 : :
205 : : /* Unnest fgrp[1] and verify that it now owns its own fds along with fgrp[3] fds */
206 : 3 : rc = spdk_fd_group_unnest(fgrp[0].fgrp, fgrp[1].fgrp);
207 : 3 : CU_ASSERT_EQUAL(rc, 0);
208 : :
209 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[0].fgrp->parent, NULL);
210 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[1].fgrp->parent, NULL);
211 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[2].fgrp->parent, fgrp[0].fgrp);
212 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[3].fgrp->parent, fgrp[1].fgrp);
213 : 3 : CU_ASSERT_EQUAL(fgrp[0].fgrp->num_fds, fgrp[0].num_fds + fgrp[2].num_fds);
214 : 3 : CU_ASSERT_EQUAL(fgrp[1].fgrp->num_fds, fgrp[1].num_fds + fgrp[3].num_fds);
215 : 3 : CU_ASSERT_EQUAL(fgrp[2].fgrp->num_fds, 0);
216 : 3 : CU_ASSERT_EQUAL(fgrp[3].fgrp->num_fds, 0);
217 : :
218 : : /* Nest it again, keeping the same configuration */
219 : 3 : rc = spdk_fd_group_nest(fgrp[0].fgrp, fgrp[1].fgrp);
220 : 3 : CU_ASSERT_EQUAL(rc, 0);
221 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[0].fgrp->parent, NULL);
222 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[1].fgrp->parent, fgrp[0].fgrp);
223 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[2].fgrp->parent, fgrp[0].fgrp);
224 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[3].fgrp->parent, fgrp[1].fgrp);
225 : 3 : CU_ASSERT_EQUAL(fgrp[0].fgrp->num_fds,
226 : : fgrp[0].num_fds + fgrp[1].num_fds +
227 : : fgrp[2].num_fds + fgrp[3].num_fds);
228 : 3 : CU_ASSERT_EQUAL(fgrp[1].fgrp->num_fds, 0);
229 : 3 : CU_ASSERT_EQUAL(fgrp[2].fgrp->num_fds, 0);
230 : 3 : CU_ASSERT_EQUAL(fgrp[3].fgrp->num_fds, 0);
231 : :
232 : : /* Add a new fd to the fgrp at the bottom, fgrp[3] */
233 : 3 : fgrp[3].fd[fgrp[3].num_fds++] = fd = eventfd(0, 0);
234 : 3 : rc = SPDK_FD_GROUP_ADD(fgrp[3].fgrp, fd, fd_group_cb_fn, NULL);
235 : 3 : CU_ASSERT_EQUAL(rc, 0);
236 : 3 : CU_ASSERT_EQUAL(fgrp[0].fgrp->num_fds,
237 : : fgrp[0].num_fds + fgrp[1].num_fds +
238 : : fgrp[2].num_fds + fgrp[3].num_fds);
239 : 3 : CU_ASSERT_EQUAL(fgrp[1].fgrp->num_fds, 0);
240 : 3 : CU_ASSERT_EQUAL(fgrp[2].fgrp->num_fds, 0);
241 : 3 : CU_ASSERT_EQUAL(fgrp[3].fgrp->num_fds, 0);
242 : :
243 : : /* Remove one of the fds from fgrp[2] */
244 : 3 : fd = fgrp[2].fd[--fgrp[2].num_fds];
245 : 3 : spdk_fd_group_remove(fgrp[2].fgrp, fd);
246 : 3 : close(fd);
247 : 3 : CU_ASSERT_EQUAL(fgrp[0].fgrp->num_fds,
248 : : fgrp[0].num_fds + fgrp[1].num_fds +
249 : : fgrp[2].num_fds + fgrp[3].num_fds);
250 : 3 : CU_ASSERT_EQUAL(fgrp[1].fgrp->num_fds, 0);
251 : 3 : CU_ASSERT_EQUAL(fgrp[2].fgrp->num_fds, 0);
252 : 3 : CU_ASSERT_EQUAL(fgrp[3].fgrp->num_fds, 0);
253 : :
254 : : /* Unnest the fgrp at the bottom, fgrp[3] */
255 : 3 : rc = spdk_fd_group_unnest(fgrp[1].fgrp, fgrp[3].fgrp);
256 : 3 : CU_ASSERT_EQUAL(rc, 0);
257 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[0].fgrp->parent, NULL);
258 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[1].fgrp->parent, fgrp[0].fgrp);
259 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[2].fgrp->parent, fgrp[0].fgrp);
260 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[3].fgrp->parent, NULL);
261 : 3 : CU_ASSERT_EQUAL(fgrp[0].fgrp->num_fds, fgrp[0].num_fds + fgrp[1].num_fds + fgrp[2].num_fds);
262 : 3 : CU_ASSERT_EQUAL(fgrp[1].fgrp->num_fds, 0);
263 : 3 : CU_ASSERT_EQUAL(fgrp[2].fgrp->num_fds, 0);
264 : 3 : CU_ASSERT_EQUAL(fgrp[3].fgrp->num_fds, fgrp[3].num_fds);
265 : :
266 : : /* Unnest the remaining fgrps, fgrp[1] and fgrp[2] */
267 : 3 : rc = spdk_fd_group_unnest(fgrp[0].fgrp, fgrp[1].fgrp);
268 : 3 : CU_ASSERT_EQUAL(rc, 0);
269 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[0].fgrp->parent, NULL);
270 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[1].fgrp->parent, NULL);
271 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[2].fgrp->parent, fgrp[0].fgrp);
272 : 3 : CU_ASSERT_EQUAL(fgrp[0].fgrp->num_fds, fgrp[0].num_fds + fgrp[2].num_fds);
273 : 3 : CU_ASSERT_EQUAL(fgrp[1].fgrp->num_fds, fgrp[1].num_fds);
274 : 3 : CU_ASSERT_EQUAL(fgrp[2].fgrp->num_fds, 0);
275 : :
276 : 3 : rc = spdk_fd_group_unnest(fgrp[0].fgrp, fgrp[2].fgrp);
277 : 3 : CU_ASSERT_EQUAL(rc, 0);
278 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[0].fgrp->parent, NULL);
279 : 3 : CU_ASSERT_PTR_EQUAL(fgrp[2].fgrp->parent, NULL);;
280 : 3 : CU_ASSERT_EQUAL(fgrp[0].fgrp->num_fds, fgrp[0].num_fds);
281 : 3 : CU_ASSERT_EQUAL(fgrp[2].fgrp->num_fds, fgrp[2].num_fds);
282 : :
283 [ + + ]: 15 : for (i = 0; i < SPDK_COUNTOF(fgrp); i++) {
284 [ + + ]: 36 : for (j = 0; j < fgrp[i].num_fds; j++) {
285 : 24 : spdk_fd_group_remove(fgrp[i].fgrp, fgrp[i].fd[j]);
286 : 24 : close(fgrp[i].fd[j]);
287 : : }
288 : 12 : spdk_fd_group_destroy(fgrp[i].fgrp);
289 : : }
290 : 3 : }
291 : :
292 : : int
293 : 3 : main(int argc, char **argv)
294 : : {
295 : 3 : CU_pSuite suite = NULL;
296 : : unsigned int num_failures;
297 : :
298 : 3 : CU_initialize_registry();
299 : :
300 : 3 : suite = CU_add_suite("fd_group", NULL, NULL);
301 : :
302 : 3 : CU_ADD_TEST(suite, test_fd_group_basic);
303 : 3 : CU_ADD_TEST(suite, test_fd_group_nest_unnest);
304 : 3 : CU_ADD_TEST(suite, test_fd_group_multi_nest);
305 : :
306 : 3 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
307 : :
308 : 3 : CU_cleanup_registry();
309 : :
310 : 3 : return num_failures;
311 : : }
|