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].revents = revents; 16 } 17 } 18 19 static int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE *fp) 20 { 21 int printed = 0; 22 23 if (verbose <= 0) 24 return 0; 25 26 printed += fprintf(fp, "\n%s: ", prefix); 27 return printed + fdarray__fprintf(fda, fp); 28 } 29 30 int test__fdarray__filter(struct test *test __maybe_unused, int subtest __maybe_unused) 31 { 32 int nr_fds, expected_fd[2], fd, err = TEST_FAIL; 33 struct fdarray *fda = fdarray__new(5, 5); 34 35 if (fda == NULL) { 36 pr_debug("\nfdarray__new() failed!"); 37 goto out; 38 } 39 40 fdarray__init_revents(fda, POLLIN); 41 nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); 42 if (nr_fds != fda->nr_alloc) { 43 pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything", 44 nr_fds, fda->nr_alloc); 45 goto out_delete; 46 } 47 48 fdarray__init_revents(fda, POLLHUP); 49 nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); 50 if (nr_fds != 0) { 51 pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds", 52 nr_fds, fda->nr_alloc); 53 goto out_delete; 54 } 55 56 fdarray__init_revents(fda, POLLHUP); 57 fda->entries[2].revents = POLLIN; 58 expected_fd[0] = fda->entries[2].fd; 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 if (fda->entries[0].fd != expected_fd[0]) { 70 pr_debug("\nfda->entries[0].fd=%d != %d\n", 71 fda->entries[0].fd, expected_fd[0]); 72 goto out_delete; 73 } 74 75 fdarray__init_revents(fda, POLLHUP); 76 fda->entries[0].revents = POLLIN; 77 expected_fd[0] = fda->entries[0].fd; 78 fda->entries[3].revents = POLLIN; 79 expected_fd[1] = fda->entries[3].fd; 80 81 pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):"); 82 fdarray__fprintf_prefix(fda, "before", stderr); 83 nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); 84 fdarray__fprintf_prefix(fda, " after", stderr); 85 if (nr_fds != 2) { 86 pr_debug("\nfdarray__filter()=%d != 2, should have left just two events", 87 nr_fds); 88 goto out_delete; 89 } 90 91 for (fd = 0; fd < 2; ++fd) { 92 if (fda->entries[fd].fd != expected_fd[fd]) { 93 pr_debug("\nfda->entries[%d].fd=%d != %d\n", fd, 94 fda->entries[fd].fd, expected_fd[fd]); 95 goto out_delete; 96 } 97 } 98 99 pr_debug("\n"); 100 101 err = 0; 102 out_delete: 103 fdarray__delete(fda); 104 out: 105 return err; 106 } 107 108 int test__fdarray__add(struct test *test __maybe_unused, int subtest __maybe_unused) 109 { 110 int err = TEST_FAIL; 111 struct fdarray *fda = fdarray__new(2, 2); 112 113 if (fda == NULL) { 114 pr_debug("\nfdarray__new() failed!"); 115 goto out; 116 } 117 118 #define FDA_CHECK(_idx, _fd, _revents) \ 119 if (fda->entries[_idx].fd != _fd) { \ 120 pr_debug("\n%d: fda->entries[%d](%d) != %d!", \ 121 __LINE__, _idx, fda->entries[1].fd, _fd); \ 122 goto out_delete; \ 123 } \ 124 if (fda->entries[_idx].events != (_revents)) { \ 125 pr_debug("\n%d: fda->entries[%d].revents(%d) != %d!", \ 126 __LINE__, _idx, fda->entries[_idx].fd, _revents); \ 127 goto out_delete; \ 128 } 129 130 #define FDA_ADD(_idx, _fd, _revents, _nr) \ 131 if (fdarray__add(fda, _fd, _revents) < 0) { \ 132 pr_debug("\n%d: fdarray__add(fda, %d, %d) failed!", \ 133 __LINE__,_fd, _revents); \ 134 goto out_delete; \ 135 } \ 136 if (fda->nr != _nr) { \ 137 pr_debug("\n%d: fdarray__add(fda, %d, %d)=%d != %d", \ 138 __LINE__,_fd, _revents, fda->nr, _nr); \ 139 goto out_delete; \ 140 } \ 141 FDA_CHECK(_idx, _fd, _revents) 142 143 FDA_ADD(0, 1, POLLIN, 1); 144 FDA_ADD(1, 2, POLLERR, 2); 145 146 fdarray__fprintf_prefix(fda, "before growing array", stderr); 147 148 FDA_ADD(2, 35, POLLHUP, 3); 149 150 if (fda->entries == NULL) { 151 pr_debug("\nfdarray__add(fda, 35, POLLHUP) should have allocated fda->pollfd!"); 152 goto out_delete; 153 } 154 155 fdarray__fprintf_prefix(fda, "after 3rd add", stderr); 156 157 FDA_ADD(3, 88, POLLIN | POLLOUT, 4); 158 159 fdarray__fprintf_prefix(fda, "after 4th add", stderr); 160 161 FDA_CHECK(0, 1, POLLIN); 162 FDA_CHECK(1, 2, POLLERR); 163 FDA_CHECK(2, 35, POLLHUP); 164 FDA_CHECK(3, 88, POLLIN | POLLOUT); 165 166 #undef FDA_ADD 167 #undef FDA_CHECK 168 169 pr_debug("\n"); 170 171 err = 0; 172 out_delete: 173 fdarray__delete(fda); 174 out: 175 return err; 176 } 177