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, 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, 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, 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, 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