1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <api/fd/array.h> |
3 | #include <poll.h> |
4 | #include "util/debug.h" |
5 | #include "tests/tests.h" |
6 | |
7 | static void fdarray__init_revents(struct fdarray *fda, short revents) |
8 | { |
9 | int fd; |
10 | |
11 | fda->nr = fda->nr_alloc; |
12 | |
13 | for (fd = 0; fd < fda->nr; ++fd) { |
14 | fda->entries[fd].fd = fda->nr - fd; |
15 | fda->entries[fd].events = revents; |
16 | fda->entries[fd].revents = revents; |
17 | } |
18 | } |
19 | |
20 | static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE *fp) |
21 | { |
22 | int printed = 0; |
23 | |
24 | if (verbose <= 0) |
25 | return 0; |
26 | |
27 | printed += fprintf(fp, "\n%s: " , prefix); |
28 | return printed + fdarray__fprintf(fda, fp); |
29 | } |
30 | |
31 | static int test__fdarray__filter(struct test_suite *test __maybe_unused, int subtest __maybe_unused) |
32 | { |
33 | int nr_fds, err = TEST_FAIL; |
34 | struct fdarray *fda = fdarray__new(5, 5); |
35 | |
36 | if (fda == NULL) { |
37 | pr_debug("\nfdarray__new() failed!" ); |
38 | goto out; |
39 | } |
40 | |
41 | fdarray__init_revents(fda, revents: POLLIN); |
42 | nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); |
43 | if (nr_fds != fda->nr_alloc) { |
44 | pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything" , |
45 | nr_fds, fda->nr_alloc); |
46 | goto out_delete; |
47 | } |
48 | |
49 | fdarray__init_revents(fda, revents: POLLHUP); |
50 | nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); |
51 | if (nr_fds != 0) { |
52 | pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds" , |
53 | nr_fds, fda->nr_alloc); |
54 | goto out_delete; |
55 | } |
56 | |
57 | fdarray__init_revents(fda, revents: POLLHUP); |
58 | fda->entries[2].revents = POLLIN; |
59 | |
60 | pr_debug("\nfiltering all but fda->entries[2]:" ); |
61 | fdarray__fprintf_prefix(fda, "before" , stderr); |
62 | nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); |
63 | fdarray__fprintf_prefix(fda, " after" , stderr); |
64 | if (nr_fds != 1) { |
65 | pr_debug("\nfdarray__filter()=%d != 1, should have left just one event" , nr_fds); |
66 | goto out_delete; |
67 | } |
68 | |
69 | fdarray__init_revents(fda, revents: POLLHUP); |
70 | fda->entries[0].revents = POLLIN; |
71 | fda->entries[3].revents = POLLIN; |
72 | |
73 | pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):" ); |
74 | fdarray__fprintf_prefix(fda, "before" , stderr); |
75 | nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); |
76 | fdarray__fprintf_prefix(fda, " after" , stderr); |
77 | if (nr_fds != 2) { |
78 | pr_debug("\nfdarray__filter()=%d != 2, should have left just two events" , |
79 | nr_fds); |
80 | goto out_delete; |
81 | } |
82 | |
83 | pr_debug("\n" ); |
84 | |
85 | err = 0; |
86 | out_delete: |
87 | fdarray__delete(fda); |
88 | out: |
89 | return err; |
90 | } |
91 | |
92 | static int test__fdarray__add(struct test_suite *test __maybe_unused, int subtest __maybe_unused) |
93 | { |
94 | int err = TEST_FAIL; |
95 | struct fdarray *fda = fdarray__new(2, 2); |
96 | |
97 | if (fda == NULL) { |
98 | pr_debug("\nfdarray__new() failed!" ); |
99 | goto out; |
100 | } |
101 | |
102 | #define FDA_CHECK(_idx, _fd, _revents) \ |
103 | if (fda->entries[_idx].fd != _fd) { \ |
104 | pr_debug("\n%d: fda->entries[%d](%d) != %d!", \ |
105 | __LINE__, _idx, fda->entries[1].fd, _fd); \ |
106 | goto out_delete; \ |
107 | } \ |
108 | if (fda->entries[_idx].events != (_revents)) { \ |
109 | pr_debug("\n%d: fda->entries[%d].revents(%d) != %d!", \ |
110 | __LINE__, _idx, fda->entries[_idx].fd, _revents); \ |
111 | goto out_delete; \ |
112 | } |
113 | |
114 | #define FDA_ADD(_idx, _fd, _revents, _nr) \ |
115 | if (fdarray__add(fda, _fd, _revents, fdarray_flag__default) < 0) { \ |
116 | pr_debug("\n%d: fdarray__add(fda, %d, %d) failed!", \ |
117 | __LINE__,_fd, _revents); \ |
118 | goto out_delete; \ |
119 | } \ |
120 | if (fda->nr != _nr) { \ |
121 | pr_debug("\n%d: fdarray__add(fda, %d, %d)=%d != %d", \ |
122 | __LINE__,_fd, _revents, fda->nr, _nr); \ |
123 | goto out_delete; \ |
124 | } \ |
125 | FDA_CHECK(_idx, _fd, _revents) |
126 | |
127 | FDA_ADD(0, 1, POLLIN, 1); |
128 | FDA_ADD(1, 2, POLLERR, 2); |
129 | |
130 | fdarray__fprintf_prefix(fda, "before growing array" , stderr); |
131 | |
132 | FDA_ADD(2, 35, POLLHUP, 3); |
133 | |
134 | if (fda->entries == NULL) { |
135 | pr_debug("\nfdarray__add(fda, 35, POLLHUP) should have allocated fda->pollfd!" ); |
136 | goto out_delete; |
137 | } |
138 | |
139 | fdarray__fprintf_prefix(fda, "after 3rd add" , stderr); |
140 | |
141 | FDA_ADD(3, 88, POLLIN | POLLOUT, 4); |
142 | |
143 | fdarray__fprintf_prefix(fda, "after 4th add" , stderr); |
144 | |
145 | FDA_CHECK(0, 1, POLLIN); |
146 | FDA_CHECK(1, 2, POLLERR); |
147 | FDA_CHECK(2, 35, POLLHUP); |
148 | FDA_CHECK(3, 88, POLLIN | POLLOUT); |
149 | |
150 | #undef FDA_ADD |
151 | #undef FDA_CHECK |
152 | |
153 | pr_debug("\n" ); |
154 | |
155 | err = 0; |
156 | out_delete: |
157 | fdarray__delete(fda); |
158 | out: |
159 | return err; |
160 | } |
161 | |
162 | DEFINE_SUITE("Filter fds with revents mask in a fdarray" , fdarray__filter); |
163 | DEFINE_SUITE("Add fd to a fdarray, making it autogrow" , fdarray__add); |
164 | |