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