18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci#include <api/fd/array.h> 38c2ecf20Sopenharmony_ci#include <poll.h> 48c2ecf20Sopenharmony_ci#include "util/debug.h" 58c2ecf20Sopenharmony_ci#include "tests/tests.h" 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_cistatic void fdarray__init_revents(struct fdarray *fda, short revents) 88c2ecf20Sopenharmony_ci{ 98c2ecf20Sopenharmony_ci int fd; 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci fda->nr = fda->nr_alloc; 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci for (fd = 0; fd < fda->nr; ++fd) { 148c2ecf20Sopenharmony_ci fda->entries[fd].fd = fda->nr - fd; 158c2ecf20Sopenharmony_ci fda->entries[fd].events = revents; 168c2ecf20Sopenharmony_ci fda->entries[fd].revents = revents; 178c2ecf20Sopenharmony_ci } 188c2ecf20Sopenharmony_ci} 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic int fdarray__fprintf_prefix(struct fdarray *fda, const char *prefix, FILE *fp) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci int printed = 0; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci if (verbose <= 0) 258c2ecf20Sopenharmony_ci return 0; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci printed += fprintf(fp, "\n%s: ", prefix); 288c2ecf20Sopenharmony_ci return printed + fdarray__fprintf(fda, fp); 298c2ecf20Sopenharmony_ci} 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ciint test__fdarray__filter(struct test *test __maybe_unused, int subtest __maybe_unused) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci int nr_fds, err = TEST_FAIL; 348c2ecf20Sopenharmony_ci struct fdarray *fda = fdarray__new(5, 5); 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci if (fda == NULL) { 378c2ecf20Sopenharmony_ci pr_debug("\nfdarray__new() failed!"); 388c2ecf20Sopenharmony_ci goto out; 398c2ecf20Sopenharmony_ci } 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci fdarray__init_revents(fda, POLLIN); 428c2ecf20Sopenharmony_ci nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); 438c2ecf20Sopenharmony_ci if (nr_fds != fda->nr_alloc) { 448c2ecf20Sopenharmony_ci pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything", 458c2ecf20Sopenharmony_ci nr_fds, fda->nr_alloc); 468c2ecf20Sopenharmony_ci goto out_delete; 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci fdarray__init_revents(fda, POLLHUP); 508c2ecf20Sopenharmony_ci nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); 518c2ecf20Sopenharmony_ci if (nr_fds != 0) { 528c2ecf20Sopenharmony_ci pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds", 538c2ecf20Sopenharmony_ci nr_fds, fda->nr_alloc); 548c2ecf20Sopenharmony_ci goto out_delete; 558c2ecf20Sopenharmony_ci } 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci fdarray__init_revents(fda, POLLHUP); 588c2ecf20Sopenharmony_ci fda->entries[2].revents = POLLIN; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci pr_debug("\nfiltering all but fda->entries[2]:"); 618c2ecf20Sopenharmony_ci fdarray__fprintf_prefix(fda, "before", stderr); 628c2ecf20Sopenharmony_ci nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); 638c2ecf20Sopenharmony_ci fdarray__fprintf_prefix(fda, " after", stderr); 648c2ecf20Sopenharmony_ci if (nr_fds != 1) { 658c2ecf20Sopenharmony_ci pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds); 668c2ecf20Sopenharmony_ci goto out_delete; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci fdarray__init_revents(fda, POLLHUP); 708c2ecf20Sopenharmony_ci fda->entries[0].revents = POLLIN; 718c2ecf20Sopenharmony_ci fda->entries[3].revents = POLLIN; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):"); 748c2ecf20Sopenharmony_ci fdarray__fprintf_prefix(fda, "before", stderr); 758c2ecf20Sopenharmony_ci nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL); 768c2ecf20Sopenharmony_ci fdarray__fprintf_prefix(fda, " after", stderr); 778c2ecf20Sopenharmony_ci if (nr_fds != 2) { 788c2ecf20Sopenharmony_ci pr_debug("\nfdarray__filter()=%d != 2, should have left just two events", 798c2ecf20Sopenharmony_ci nr_fds); 808c2ecf20Sopenharmony_ci goto out_delete; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci pr_debug("\n"); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci err = 0; 868c2ecf20Sopenharmony_ciout_delete: 878c2ecf20Sopenharmony_ci fdarray__delete(fda); 888c2ecf20Sopenharmony_ciout: 898c2ecf20Sopenharmony_ci return err; 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciint test__fdarray__add(struct test *test __maybe_unused, int subtest __maybe_unused) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci int err = TEST_FAIL; 958c2ecf20Sopenharmony_ci struct fdarray *fda = fdarray__new(2, 2); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci if (fda == NULL) { 988c2ecf20Sopenharmony_ci pr_debug("\nfdarray__new() failed!"); 998c2ecf20Sopenharmony_ci goto out; 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci#define FDA_CHECK(_idx, _fd, _revents) \ 1038c2ecf20Sopenharmony_ci if (fda->entries[_idx].fd != _fd) { \ 1048c2ecf20Sopenharmony_ci pr_debug("\n%d: fda->entries[%d](%d) != %d!", \ 1058c2ecf20Sopenharmony_ci __LINE__, _idx, fda->entries[1].fd, _fd); \ 1068c2ecf20Sopenharmony_ci goto out_delete; \ 1078c2ecf20Sopenharmony_ci } \ 1088c2ecf20Sopenharmony_ci if (fda->entries[_idx].events != (_revents)) { \ 1098c2ecf20Sopenharmony_ci pr_debug("\n%d: fda->entries[%d].revents(%d) != %d!", \ 1108c2ecf20Sopenharmony_ci __LINE__, _idx, fda->entries[_idx].fd, _revents); \ 1118c2ecf20Sopenharmony_ci goto out_delete; \ 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci#define FDA_ADD(_idx, _fd, _revents, _nr) \ 1158c2ecf20Sopenharmony_ci if (fdarray__add(fda, _fd, _revents, fdarray_flag__default) < 0) { \ 1168c2ecf20Sopenharmony_ci pr_debug("\n%d: fdarray__add(fda, %d, %d) failed!", \ 1178c2ecf20Sopenharmony_ci __LINE__,_fd, _revents); \ 1188c2ecf20Sopenharmony_ci goto out_delete; \ 1198c2ecf20Sopenharmony_ci } \ 1208c2ecf20Sopenharmony_ci if (fda->nr != _nr) { \ 1218c2ecf20Sopenharmony_ci pr_debug("\n%d: fdarray__add(fda, %d, %d)=%d != %d", \ 1228c2ecf20Sopenharmony_ci __LINE__,_fd, _revents, fda->nr, _nr); \ 1238c2ecf20Sopenharmony_ci goto out_delete; \ 1248c2ecf20Sopenharmony_ci } \ 1258c2ecf20Sopenharmony_ci FDA_CHECK(_idx, _fd, _revents) 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci FDA_ADD(0, 1, POLLIN, 1); 1288c2ecf20Sopenharmony_ci FDA_ADD(1, 2, POLLERR, 2); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci fdarray__fprintf_prefix(fda, "before growing array", stderr); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci FDA_ADD(2, 35, POLLHUP, 3); 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (fda->entries == NULL) { 1358c2ecf20Sopenharmony_ci pr_debug("\nfdarray__add(fda, 35, POLLHUP) should have allocated fda->pollfd!"); 1368c2ecf20Sopenharmony_ci goto out_delete; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci fdarray__fprintf_prefix(fda, "after 3rd add", stderr); 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci FDA_ADD(3, 88, POLLIN | POLLOUT, 4); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci fdarray__fprintf_prefix(fda, "after 4th add", stderr); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci FDA_CHECK(0, 1, POLLIN); 1468c2ecf20Sopenharmony_ci FDA_CHECK(1, 2, POLLERR); 1478c2ecf20Sopenharmony_ci FDA_CHECK(2, 35, POLLHUP); 1488c2ecf20Sopenharmony_ci FDA_CHECK(3, 88, POLLIN | POLLOUT); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci#undef FDA_ADD 1518c2ecf20Sopenharmony_ci#undef FDA_CHECK 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci pr_debug("\n"); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci err = 0; 1568c2ecf20Sopenharmony_ciout_delete: 1578c2ecf20Sopenharmony_ci fdarray__delete(fda); 1588c2ecf20Sopenharmony_ciout: 1598c2ecf20Sopenharmony_ci return err; 1608c2ecf20Sopenharmony_ci} 161