From nobody Tue Jun 10 06:06:06 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4bGdZl0tjfz609c4; Tue, 10 Jun 2025 06:06:07 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4bGdZk6j6gz3q0d; Tue, 10 Jun 2025 06:06:06 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1749535566; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=dTBEgXUtt3GPDY5ddMu9XmOlAWdd408PREp691NLwA8=; b=nxUiIL7clASPFQkduW00NLLnPlQU5O+T8AMV1y+m8DRp7xpXhdpwsfre4lvWZYMVET9erj wK0g+LjD/7OZ5DfNR6QbMRBMlQgF/hL9V23ZipfTe23yMID8uTco1DoY+KnpLH1Pq7l+Rn Yb9ZBscIqq7Fia9WyNXOEROfPzT8naSbhT1rDHg0TpzbUh22h9OLQTs+5iNeDuEd/T4oom /4iPWYfKDQvS/cmnEni1OxgN/4jy1vz3B35RCsiF+/SFXJIMpuc87jRTOEwJNLrfbdrYOM RPWo7fXxhFd8VtmigkR5u9cfXxpBvxTmOMqlAUDlZgOSU9gZcM2sLMX23tHQEw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1749535566; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=dTBEgXUtt3GPDY5ddMu9XmOlAWdd408PREp691NLwA8=; b=yitOwEWw7JT3G7kxqXcLh1dlD5jOf28z5svpRZGf5lBsxaw67wP7QSSEZm+IkUyk/24WfQ maiikk18hdZqCskq1oRxjJosOMurlMu6SsbCAMHW9oWMcYNWNPKeAwk2jar2gp99WwMhfU xIAmY2H9k6Tj90ELFix79BK/6IvSMwCIm5pfEszCr/T4wkcPNAOnYjLUqZeEickVIgDm2v vKjtJ/Nz7yjJRNotfWMl+9fFJOwLyX690xwwUYNTwdC2xJ0PFqX7zzDil7CgSNi9XdcqOr R2PMCLTLg3mh4SV1JW5us86NazHWUUICoyxOt4PVu7CGACZlUI/r6KwqhrRHCg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1749535567; a=rsa-sha256; cv=none; b=XdFJ3XSQGcHQGUfCfiXvCIel3omZs+Sb58u2gY0DJRebepnCKwHmCMPYTlWhebB3vYfhbZ 3dLu3QGOcmdX9wFoKkGGMtfxPCrdkphMeVaQpniLCyHdDjFRPr6ppci0GFnQXHKxeJBmRU vbqzN62d2nwh9lZ84guzpcoOK+6OUQNVeIHKZMW805JIu44f4+xGLw8iYZtN1riOWEESz3 LZE3+C5cVZKc9o1Cj4yUTYXd2sWdvxfntW4GTEmkrvw5RUWPNKFpLvJ47X8Zyy3uzyQjPc bPUPIld2G0nIJTZ6o3cNEe4slMQyQs4EzQaezkUd88+OLDf1enua+oJ3E174sQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4bGdZk63vHzDF6; Tue, 10 Jun 2025 06:06:06 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 55A666OR003551; Tue, 10 Jun 2025 06:06:06 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 55A666XL003548; Tue, 10 Jun 2025 06:06:06 GMT (envelope-from git) Date: Tue, 10 Jun 2025 06:06:06 GMT Message-Id: <202506100606.55A666XL003548@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Gleb Smirnoff Subject: git: 19e599c0e00d - main - tests/unix_stream: refactor event mech tests List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: glebius X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 19e599c0e00dcf0699c38798e5d58fb8423e5810 Auto-Submitted: auto-generated The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=19e599c0e00dcf0699c38798e5d58fb8423e5810 commit 19e599c0e00dcf0699c38798e5d58fb8423e5810 Author: Gleb Smirnoff AuthorDate: 2025-06-10 02:59:31 +0000 Commit: Gleb Smirnoff CommitDate: 2025-06-10 04:57:04 +0000 tests/unix_stream: refactor event mech tests Provide a context that can be used both for writability and readability checks. This collapses two check functions per mech into one. Provide a possibility to check advanced features of an event mech, e.g. returned kev_flags for kevent(2). Should be no functional change. --- tests/sys/kern/unix_stream.c | 293 ++++++++++++++++++++++++------------------- 1 file changed, 161 insertions(+), 132 deletions(-) diff --git a/tests/sys/kern/unix_stream.c b/tests/sys/kern/unix_stream.c index f8ba288308bd..72dbe8ca1d92 100644 --- a/tests/sys/kern/unix_stream.c +++ b/tests/sys/kern/unix_stream.c @@ -102,98 +102,78 @@ ATF_TC_BODY(send_0, tc) close(sv[1]); } -static void -check_readable_select(int fd, int expect, bool timeout) -{ - fd_set rdfds; - int nfds; - - FD_ZERO(&rdfds); - FD_SET(fd, &rdfds); - nfds = select(fd + 1, &rdfds, NULL, NULL, timeout ? - &(struct timeval){.tv_usec = 1000} : NULL); - ATF_REQUIRE_MSG(nfds == expect, - "select() returns %d errno %d", nfds, errno); -} +struct check_ctx; +typedef void check_func_t(struct check_ctx *); +struct check_ctx { + check_func_t *method; + int sv[2]; + bool timeout; + union { + enum { SELECT_RD, SELECT_WR } select_what; + short poll_events; + short kev_filter; + }; + int nfds; + union { + short poll_revents; + unsigned short kev_flags; + }; +}; static void -check_writable_select(int fd, int expect, bool timeout) +check_select(struct check_ctx *ctx) { - fd_set wrfds; + fd_set fds; int nfds; - FD_ZERO(&wrfds); - FD_SET(fd, &wrfds); - nfds = select(fd + 1, NULL, &wrfds, NULL, timeout ? - &(struct timeval){.tv_usec = 1000} : NULL); - ATF_REQUIRE_MSG(nfds == expect, + FD_ZERO(&fds); + FD_SET(ctx->sv[0], &fds); + nfds = select(ctx->sv[0] + 1, + ctx->select_what == SELECT_RD ? &fds : NULL, + ctx->select_what == SELECT_WR ? &fds : NULL, + NULL, + ctx->timeout ? &(struct timeval){.tv_usec = 1000} : NULL); + ATF_REQUIRE_MSG(nfds == ctx->nfds, "select() returns %d errno %d", nfds, errno); } static void -check_readable_poll(int fd, int expect, bool timeout) +check_poll(struct check_ctx *ctx) { struct pollfd pfd[1]; int nfds; pfd[0] = (struct pollfd){ - .fd = fd, - .events = POLLIN | POLLRDNORM, + .fd = ctx->sv[0], + .events = ctx->poll_events, }; - nfds = poll(pfd, 1, timeout ? 1 : INFTIM); - ATF_REQUIRE_MSG(nfds == expect, + nfds = poll(pfd, 1, ctx->timeout ? 1 : INFTIM); + ATF_REQUIRE_MSG(nfds == ctx->nfds, "poll() returns %d errno %d", nfds, errno); + ATF_REQUIRE((pfd[0].revents & ctx->poll_revents) == ctx->poll_revents); } static void -check_writable_poll(int fd, int expect, bool timeout) -{ - struct pollfd pfd[1]; - int nfds; - - pfd[0] = (struct pollfd){ - .fd = fd, - .events = POLLOUT | POLLWRNORM, - }; - nfds = poll(pfd, 1, timeout ? 1 : INFTIM); - ATF_REQUIRE_MSG(nfds == expect, - "poll() returns %d errno %d", nfds, errno); -} - -static void -check_writable_kevent(int fd, int expect, bool timeout) +check_kevent(struct check_ctx *ctx) { struct kevent kev; int nfds, kq; ATF_REQUIRE(kq = kqueue()); - EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, NULL); + EV_SET(&kev, ctx->sv[0], ctx->kev_filter, EV_ADD, 0, 0, NULL); nfds = kevent(kq, &kev, 1, NULL, 0, NULL); ATF_REQUIRE_MSG(nfds == 0, "kevent() returns %d errno %d", nfds, errno); - nfds = kevent(kq, NULL, 0, &kev, 1, timeout ? + nfds = kevent(kq, NULL, 0, &kev, 1, ctx->timeout ? &(struct timespec){.tv_nsec = 1000000} : NULL); - ATF_REQUIRE_MSG(nfds == expect, + ATF_REQUIRE_MSG(nfds == ctx->nfds, "kevent() returns %d errno %d", nfds, errno); + ATF_REQUIRE(kev.ident == (uintptr_t)ctx->sv[0] && + kev.filter == ctx->kev_filter && + (kev.flags & ctx->kev_flags) == ctx->kev_flags); close(kq); } -typedef void check_writable_func_t(int, int, bool); -struct check_writable_ctx { - check_writable_func_t *method; - int fd; -}; - -static void * -check_writable_blocking_thread(void *arg) -{ - struct check_writable_ctx *ctx = arg; - - ctx->method(ctx->fd, 1, false); - - return (NULL); -} - static void full_socketpair(int *sv) { @@ -210,13 +190,19 @@ full_socketpair(int *sv) free(buf); } +static void * +pthread_wrap(void *arg) +{ + struct check_ctx *ctx = arg; + + ctx->method(ctx); + + return (NULL); +} + static void -full_writability_check(int *sv, check_writable_func_t method) +full_writability_check(struct check_ctx *ctx) { - struct check_writable_ctx ctx = { - .method = method, - .fd = sv[0], - }; pthread_t thr; void *buf; u_long space; @@ -225,26 +211,30 @@ full_writability_check(int *sv, check_writable_func_t method) ATF_REQUIRE((buf = malloc(space)) != NULL); /* First check with timeout, expecting 0 fds returned. */ - method(sv[0], 0, true); + ctx->timeout = true; + ctx->nfds = 0; + ctx->method(ctx); /* Launch blocking thread. */ - ATF_REQUIRE(pthread_create(&thr, NULL, check_writable_blocking_thread, - &ctx) == 0); + ctx->timeout = false; + ctx->nfds = 1; + ATF_REQUIRE(pthread_create(&thr, NULL, pthread_wrap, ctx) == 0); /* Sleep a bit to make sure that thread is put to sleep. */ usleep(10000); ATF_REQUIRE(pthread_peekjoin_np(thr, NULL) == EBUSY); /* Read some data and re-check, the fd is expected to be returned. */ - ATF_REQUIRE(read(sv[1], buf, space) == (ssize_t)space); - - method(sv[0], 1, true); + ATF_REQUIRE(read(ctx->sv[1], buf, space) == (ssize_t)space); /* Now check that thread was successfully woken up and exited. */ ATF_REQUIRE(pthread_join(thr, NULL) == 0); - close(sv[0]); - close(sv[1]); + /* Extra check repeating what joined thread already did. */ + ctx->method(ctx); + + close(ctx->sv[0]); + close(ctx->sv[1]); free(buf); } @@ -254,130 +244,169 @@ full_writability_check(int *sv, check_writable_func_t method) ATF_TC_WITHOUT_HEAD(full_writability_select); ATF_TC_BODY(full_writability_select, tc) { - int sv[2]; + struct check_ctx ctx = { + .method = check_select, + .select_what = SELECT_WR, + }; - full_socketpair(sv); - full_writability_check(sv, check_writable_select); - close(sv[0]); - close(sv[1]); + full_socketpair(ctx.sv); + full_writability_check(&ctx); + close(ctx.sv[0]); + close(ctx.sv[1]); } ATF_TC_WITHOUT_HEAD(full_writability_poll); ATF_TC_BODY(full_writability_poll, tc) { - int sv[2]; + struct check_ctx ctx = { + .method = check_poll, + .poll_events = POLLOUT | POLLWRNORM, + }; - full_socketpair(sv); - full_writability_check(sv, check_writable_poll); - close(sv[0]); - close(sv[1]); + full_socketpair(ctx.sv); + full_writability_check(&ctx); + close(ctx.sv[0]); + close(ctx.sv[1]); } ATF_TC_WITHOUT_HEAD(full_writability_kevent); ATF_TC_BODY(full_writability_kevent, tc) { - int sv[2]; + struct check_ctx ctx = { + .method = check_kevent, + .kev_filter = EVFILT_WRITE, + }; - full_socketpair(sv); - full_writability_check(sv, check_writable_kevent); - close(sv[0]); - close(sv[1]); + full_socketpair(ctx.sv); + full_writability_check(&ctx); + close(ctx.sv[0]); + close(ctx.sv[1]); } ATF_TC_WITHOUT_HEAD(connected_writability); ATF_TC_BODY(connected_writability, tc) { - int sv[2]; + struct check_ctx ctx = { + .timeout = true, + .nfds = 1, + }; - do_socketpair(sv); - check_writable_select(sv[0], 1, true); - check_writable_poll(sv[0], 1, true); - check_writable_kevent(sv[0], 1, true); - close(sv[0]); - close(sv[1]); + do_socketpair(ctx.sv); + + ctx.select_what = SELECT_WR; + check_select(&ctx); + ctx.poll_events = POLLOUT | POLLWRNORM; + check_poll(&ctx); + ctx.kev_filter = EVFILT_WRITE; + check_kevent(&ctx); + + close(ctx.sv[0]); + close(ctx.sv[1]); } ATF_TC_WITHOUT_HEAD(unconnected_writability); ATF_TC_BODY(unconnected_writability, tc) { - int s; + struct check_ctx ctx = { + .timeout = true, + .nfds = 0, + }; + + ATF_REQUIRE((ctx.sv[0] = socket(PF_LOCAL, SOCK_STREAM, 0)) > 0); - ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_STREAM, 0)) > 0); - check_writable_select(s, 0, true); - check_writable_poll(s, 0, true); - check_writable_kevent(s, 0, true); - close(s); + ctx.select_what = SELECT_WR; + check_select(&ctx); + ctx.poll_events = POLLOUT | POLLWRNORM; + check_poll(&ctx); + ctx.kev_filter = EVFILT_WRITE; + check_kevent(&ctx); + + close(ctx.sv[0]); } ATF_TC_WITHOUT_HEAD(peerclosed_writability); ATF_TC_BODY(peerclosed_writability, tc) { - struct kevent kev; - int sv[2], kq; - - do_socketpair(sv); - close(sv[1]); + struct check_ctx ctx = { + .timeout = false, + .nfds = 1, + }; - check_writable_select(sv[0], 1, false); - check_writable_poll(sv[0], 1, false); + do_socketpair(ctx.sv); + close(ctx.sv[1]); - ATF_REQUIRE(kq = kqueue()); - EV_SET(&kev, sv[0], EVFILT_WRITE, EV_ADD, 0, 0, NULL); - ATF_REQUIRE(kevent(kq, &kev, 1, &kev, 1, NULL) == 1); - ATF_REQUIRE(kev.ident == (uintptr_t)sv[0] && - kev.filter == EVFILT_WRITE && - kev.flags == EV_EOF); + ctx.select_what = SELECT_WR; + check_select(&ctx); + ctx.poll_events = POLLOUT | POLLWRNORM; + check_poll(&ctx); + ctx.kev_filter = EVFILT_WRITE; + ctx.kev_flags = EV_EOF; + check_kevent(&ctx); - close(sv[0]); + close(ctx.sv[0]); } ATF_TC_WITHOUT_HEAD(peershutdown_writability); ATF_TC_BODY(peershutdown_writability, tc) { - int sv[2]; + struct check_ctx ctx = { + .timeout = false, + .nfds = 1, + }; - do_socketpair(sv); - shutdown(sv[1], SHUT_RD); + do_socketpair(ctx.sv); + shutdown(ctx.sv[1], SHUT_RD); - check_writable_select(sv[0], 1, false); - check_writable_poll(sv[0], 1, false); + ctx.select_what = SELECT_WR; + check_select(&ctx); + ctx.poll_events = POLLOUT | POLLWRNORM; + check_poll(&ctx); /* * XXXGL: historically unix(4) sockets were not reporting peer's * shutdown(SHUT_RD) as our EV_EOF. The kevent(2) manual page says * "filter will set EV_EOF when the reader disconnects", which is hard * to interpret unambigously. For now leave the historic behavior, * but we may want to change that in uipc_usrreq.c:uipc_filt_sowrite(), - * and then this test will look like the peerclosed_writability test. + * and then this test will also expect EV_EOF in returned flags. */ - check_writable_kevent(sv[0], 1, false); + ctx.kev_filter = EVFILT_WRITE; + check_kevent(&ctx); - close(sv[0]); - close(sv[1]); + close(ctx.sv[0]); + close(ctx.sv[1]); } ATF_TC_WITHOUT_HEAD(peershutdown_readability); ATF_TC_BODY(peershutdown_readability, tc) { + struct check_ctx ctx = { + .timeout = false, + .nfds = 1, + }; ssize_t readsz; - int sv[2]; char c; - do_socketpair(sv); - shutdown(sv[1], SHUT_WR); + do_socketpair(ctx.sv); + shutdown(ctx.sv[1], SHUT_WR); /* * The other side should flag as readable in select(2) to allow it to * read(2) and observe EOF. Ensure that both poll(2) and select(2) * are consistent here. */ - check_readable_select(sv[0], 1, false); - check_readable_poll(sv[0], 1, false); + ctx.select_what = SELECT_RD; + check_select(&ctx); + ctx.poll_events = POLLIN | POLLRDNORM; + check_poll(&ctx); - readsz = read(sv[0], &c, sizeof(c)); + /* + * Also check that read doesn't block. + */ + readsz = read(ctx.sv[0], &c, sizeof(c)); ATF_REQUIRE_INTEQ(0, readsz); - close(sv[0]); - close(sv[1]); + close(ctx.sv[0]); + close(ctx.sv[1]); } ATF_TP_ADD_TCS(tp)