Changeset View
Changeset View
Standalone View
Standalone View
tests/sys/kern/unix_stream.c
| Show First 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | ATF_TC_BODY(send_0, tc) | ||||
| close(sv[1]); | close(sv[1]); | ||||
| } | } | ||||
| struct check_ctx; | struct check_ctx; | ||||
| typedef void check_func_t(struct check_ctx *); | typedef void check_func_t(struct check_ctx *); | ||||
| struct check_ctx { | struct check_ctx { | ||||
| check_func_t *method; | check_func_t *method; | ||||
| int sv[2]; | int sv[2]; | ||||
| int kq; | |||||
| bool timeout; | bool timeout; | ||||
| union { | union { | ||||
| enum { SELECT_RD, SELECT_WR } select_what; | enum { SELECT_RD, SELECT_WR } select_what; | ||||
| short poll_events; | short poll_events; | ||||
| short kev_filter; | short kev_filter; | ||||
| }; | }; | ||||
| int nfds; | int nfds; | ||||
| union { | union { | ||||
| Show All 31 Lines | check_poll(struct check_ctx *ctx) | ||||
| }; | }; | ||||
| nfds = poll(pfd, 1, ctx->timeout ? 1 : INFTIM); | nfds = poll(pfd, 1, ctx->timeout ? 1 : INFTIM); | ||||
| ATF_REQUIRE_MSG(nfds == ctx->nfds, | ATF_REQUIRE_MSG(nfds == ctx->nfds, | ||||
| "poll() returns %d errno %d", nfds, errno); | "poll() returns %d errno %d", nfds, errno); | ||||
| ATF_REQUIRE((pfd[0].revents & ctx->poll_revents) == ctx->poll_revents); | ATF_REQUIRE((pfd[0].revents & ctx->poll_revents) == ctx->poll_revents); | ||||
| } | } | ||||
| static void | static void | ||||
| check_kevent(struct check_ctx *ctx) | add_kevent(struct check_ctx *ctx) | ||||
| { | { | ||||
| struct kevent kev; | struct kevent kev; | ||||
| int nfds, kq; | int kq, nfds; | ||||
| ATF_REQUIRE(kq = kqueue()); | if (ctx->kq <= 0) { | ||||
| kq = kqueue(); | |||||
| ATF_REQUIRE(kq > 0); | |||||
| ctx->kq = kq; | |||||
| } | |||||
| EV_SET(&kev, ctx->sv[0], ctx->kev_filter, 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); | nfds = kevent(ctx->kq, &kev, 1, NULL, 0, NULL); | ||||
| ATF_REQUIRE_MSG(nfds == 0, | ATF_REQUIRE_MSG(nfds == 0, | ||||
| "kevent() returns %d errno %d", nfds, errno); | "kevent() returns %d errno %d", nfds, errno); | ||||
| nfds = kevent(kq, NULL, 0, &kev, 1, ctx->timeout ? | } | ||||
| static void | |||||
| check_kevent(struct check_ctx *ctx) | |||||
| { | |||||
| struct kevent kev; | |||||
| int nfds; | |||||
| nfds = kevent(ctx->kq, NULL, 0, &kev, 1, ctx->timeout ? | |||||
| &(struct timespec){.tv_nsec = 1000000} : NULL); | &(struct timespec){.tv_nsec = 1000000} : NULL); | ||||
| ATF_REQUIRE_MSG(nfds == ctx->nfds, | ATF_REQUIRE_MSG(nfds == ctx->nfds, | ||||
| "kevent() returns %d errno %d", nfds, errno); | "kevent() returns %d errno %d", nfds, errno); | ||||
| ATF_REQUIRE(kev.ident == (uintptr_t)ctx->sv[0] && | if (nfds > 0) { | ||||
| kev.filter == ctx->kev_filter && | ATF_REQUIRE_EQ(kev.ident, (uintptr_t)ctx->sv[0]); | ||||
| (kev.flags & ctx->kev_flags) == ctx->kev_flags); | ATF_REQUIRE_EQ(kev.filter, ctx->kev_filter); | ||||
| close(kq); | ATF_REQUIRE_EQ(kev.flags & ctx->kev_flags, ctx->kev_flags); | ||||
| } | } | ||||
| close(ctx->kq); | |||||
| ctx->kq = -1; | |||||
| } | |||||
| static void | static void | ||||
| add_and_check_kevent(struct check_ctx *ctx) | |||||
| { | |||||
| add_kevent(ctx); | |||||
| check_kevent(ctx); | |||||
| } | |||||
| static void | |||||
| full_socketpair(int *sv) | full_socketpair(int *sv) | ||||
| { | { | ||||
| void *buf; | void *buf; | ||||
| u_long sendspace; | u_long sendspace; | ||||
| sendspace = getsendspace(); | sendspace = getsendspace(); | ||||
| ATF_REQUIRE((buf = malloc(sendspace)) != NULL); | ATF_REQUIRE((buf = malloc(sendspace)) != NULL); | ||||
| do_socketpair(sv); | do_socketpair(sv); | ||||
| ▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | ATF_TC_BODY(full_writability_poll, tc) | ||||
| close(ctx.sv[0]); | close(ctx.sv[0]); | ||||
| close(ctx.sv[1]); | close(ctx.sv[1]); | ||||
| } | } | ||||
| ATF_TC_WITHOUT_HEAD(full_writability_kevent); | ATF_TC_WITHOUT_HEAD(full_writability_kevent); | ||||
| ATF_TC_BODY(full_writability_kevent, tc) | ATF_TC_BODY(full_writability_kevent, tc) | ||||
| { | { | ||||
| struct check_ctx ctx = { | struct check_ctx ctx = { | ||||
| .method = check_kevent, | .method = add_and_check_kevent, | ||||
| .kev_filter = EVFILT_WRITE, | .kev_filter = EVFILT_WRITE, | ||||
| }; | }; | ||||
| full_socketpair(ctx.sv); | full_socketpair(ctx.sv); | ||||
| full_writability_check(&ctx); | full_writability_check(&ctx); | ||||
| close(ctx.sv[0]); | close(ctx.sv[0]); | ||||
| close(ctx.sv[1]); | close(ctx.sv[1]); | ||||
| } | } | ||||
| ATF_TC_WITHOUT_HEAD(connected_writability); | ATF_TC_WITHOUT_HEAD(connected_writability); | ||||
| ATF_TC_BODY(connected_writability, tc) | ATF_TC_BODY(connected_writability, tc) | ||||
| { | { | ||||
| struct check_ctx ctx = { | struct check_ctx ctx = { | ||||
| .timeout = true, | .timeout = true, | ||||
| .nfds = 1, | .nfds = 1, | ||||
| }; | }; | ||||
| do_socketpair(ctx.sv); | do_socketpair(ctx.sv); | ||||
| ctx.select_what = SELECT_WR; | ctx.select_what = SELECT_WR; | ||||
| check_select(&ctx); | check_select(&ctx); | ||||
| ctx.poll_events = POLLOUT | POLLWRNORM; | ctx.poll_events = POLLOUT | POLLWRNORM; | ||||
| check_poll(&ctx); | check_poll(&ctx); | ||||
| ctx.kev_filter = EVFILT_WRITE; | ctx.kev_filter = EVFILT_WRITE; | ||||
| check_kevent(&ctx); | add_and_check_kevent(&ctx); | ||||
| close(ctx.sv[0]); | close(ctx.sv[0]); | ||||
| close(ctx.sv[1]); | close(ctx.sv[1]); | ||||
| } | } | ||||
| ATF_TC_WITHOUT_HEAD(unconnected_writability); | ATF_TC_WITHOUT_HEAD(unconnected_writability); | ||||
| ATF_TC_BODY(unconnected_writability, tc) | ATF_TC_BODY(unconnected_writability, tc) | ||||
| { | { | ||||
| struct check_ctx ctx = { | struct check_ctx ctx = { | ||||
| .timeout = true, | .timeout = true, | ||||
| .nfds = 0, | .nfds = 0, | ||||
| }; | }; | ||||
| ATF_REQUIRE((ctx.sv[0] = socket(PF_LOCAL, SOCK_STREAM, 0)) > 0); | ATF_REQUIRE((ctx.sv[0] = socket(PF_LOCAL, SOCK_STREAM, 0)) > 0); | ||||
| ctx.select_what = SELECT_WR; | ctx.select_what = SELECT_WR; | ||||
| check_select(&ctx); | check_select(&ctx); | ||||
| ctx.poll_events = POLLOUT | POLLWRNORM; | ctx.poll_events = POLLOUT | POLLWRNORM; | ||||
| check_poll(&ctx); | check_poll(&ctx); | ||||
| ctx.kev_filter = EVFILT_WRITE; | ctx.kev_filter = EVFILT_WRITE; | ||||
| check_kevent(&ctx); | add_and_check_kevent(&ctx); | ||||
| close(ctx.sv[0]); | close(ctx.sv[0]); | ||||
| } | } | ||||
| ATF_TC_WITHOUT_HEAD(peerclosed_writability); | ATF_TC_WITHOUT_HEAD(peerclosed_writability_level); | ||||
| ATF_TC_BODY(peerclosed_writability, tc) | ATF_TC_BODY(peerclosed_writability_level, tc) | ||||
| { | { | ||||
| struct check_ctx ctx = { | struct check_ctx ctx = { | ||||
| .timeout = false, | .timeout = false, | ||||
| .nfds = 1, | .nfds = 1, | ||||
| }; | }; | ||||
| do_socketpair(ctx.sv); | do_socketpair(ctx.sv); | ||||
| close(ctx.sv[1]); | close(ctx.sv[1]); | ||||
| ctx.select_what = SELECT_WR; | ctx.select_what = SELECT_WR; | ||||
| check_select(&ctx); | check_select(&ctx); | ||||
| ctx.poll_events = POLLOUT | POLLWRNORM; | ctx.poll_events = POLLOUT | POLLWRNORM; | ||||
| check_poll(&ctx); | check_poll(&ctx); | ||||
| ctx.kev_filter = EVFILT_WRITE; | ctx.kev_filter = EVFILT_WRITE; | ||||
| ctx.kev_flags = EV_EOF; | ctx.kev_flags = EV_EOF; | ||||
| add_and_check_kevent(&ctx); | |||||
| close(ctx.sv[0]); | |||||
| } | |||||
| ATF_TC_WITHOUT_HEAD(peerclosed_writability_edge); | |||||
| ATF_TC_BODY(peerclosed_writability_edge, tc) | |||||
| { | |||||
| struct check_ctx ctx = { | |||||
| .timeout = false, | |||||
| .nfds = 1, | |||||
| }; | |||||
| do_socketpair(ctx.sv); | |||||
| ctx.kev_filter = EVFILT_WRITE; | |||||
| ctx.kev_flags = EV_EOF; | |||||
| add_kevent(&ctx); | |||||
| close(ctx.sv[1]); | |||||
| check_kevent(&ctx); | check_kevent(&ctx); | ||||
| close(ctx.sv[0]); | close(ctx.sv[0]); | ||||
| } | } | ||||
| ATF_TC_WITHOUT_HEAD(peershutdown_writability); | ATF_TC_WITHOUT_HEAD(peershutdown_writability); | ||||
| ATF_TC_BODY(peershutdown_writability, tc) | ATF_TC_BODY(peershutdown_writability, tc) | ||||
| { | { | ||||
| Show All 13 Lines | ATF_TC_BODY(peershutdown_writability, tc) | ||||
| * XXXGL: historically unix(4) sockets were not reporting peer's | * XXXGL: historically unix(4) sockets were not reporting peer's | ||||
| * shutdown(SHUT_RD) as our EV_EOF. The kevent(2) manual page says | * 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 | * "filter will set EV_EOF when the reader disconnects", which is hard | ||||
| * to interpret unambigously. For now leave the historic behavior, | * to interpret unambigously. For now leave the historic behavior, | ||||
| * but we may want to change that in uipc_usrreq.c:uipc_filt_sowrite(), | * but we may want to change that in uipc_usrreq.c:uipc_filt_sowrite(), | ||||
| * and then this test will also expect EV_EOF in returned flags. | * and then this test will also expect EV_EOF in returned flags. | ||||
| */ | */ | ||||
| ctx.kev_filter = EVFILT_WRITE; | ctx.kev_filter = EVFILT_WRITE; | ||||
| check_kevent(&ctx); | add_and_check_kevent(&ctx); | ||||
| close(ctx.sv[0]); | close(ctx.sv[0]); | ||||
| close(ctx.sv[1]); | close(ctx.sv[1]); | ||||
| } | } | ||||
| ATF_TC_WITHOUT_HEAD(peershutdown_readability); | ATF_TC_WITHOUT_HEAD(peershutdown_readability); | ||||
| ATF_TC_BODY(peershutdown_readability, tc) | ATF_TC_BODY(peershutdown_readability, tc) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | peershutdown_wakeup(&(struct check_ctx){ | ||||
| .poll_revents = POLLRDHUP, | .poll_revents = POLLRDHUP, | ||||
| }); | }); | ||||
| } | } | ||||
| ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_kevent); | ATF_TC_WITHOUT_HEAD(peershutdown_wakeup_kevent); | ||||
| ATF_TC_BODY(peershutdown_wakeup_kevent, tc) | ATF_TC_BODY(peershutdown_wakeup_kevent, tc) | ||||
| { | { | ||||
| peershutdown_wakeup(&(struct check_ctx){ | peershutdown_wakeup(&(struct check_ctx){ | ||||
| .method = check_kevent, | .method = add_and_check_kevent, | ||||
| .kev_filter = EVFILT_READ, | .kev_filter = EVFILT_READ, | ||||
| .kev_flags = EV_EOF, | .kev_flags = EV_EOF, | ||||
| }); | }); | ||||
| } | } | ||||
| ATF_TC_WITHOUT_HEAD(ourshutdown_kevent); | ATF_TC_WITHOUT_HEAD(ourshutdown_kevent); | ||||
| ATF_TC_BODY(ourshutdown_kevent, tc) | ATF_TC_BODY(ourshutdown_kevent, tc) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| ATF_TP_ADD_TC(tp, getpeereid); | ATF_TP_ADD_TC(tp, getpeereid); | ||||
| ATF_TP_ADD_TC(tp, send_0); | ATF_TP_ADD_TC(tp, send_0); | ||||
| ATF_TP_ADD_TC(tp, connected_writability); | ATF_TP_ADD_TC(tp, connected_writability); | ||||
| ATF_TP_ADD_TC(tp, unconnected_writability); | ATF_TP_ADD_TC(tp, unconnected_writability); | ||||
| ATF_TP_ADD_TC(tp, full_writability_select); | ATF_TP_ADD_TC(tp, full_writability_select); | ||||
| ATF_TP_ADD_TC(tp, full_writability_poll); | ATF_TP_ADD_TC(tp, full_writability_poll); | ||||
| ATF_TP_ADD_TC(tp, full_writability_kevent); | ATF_TP_ADD_TC(tp, full_writability_kevent); | ||||
| ATF_TP_ADD_TC(tp, peerclosed_writability); | ATF_TP_ADD_TC(tp, peerclosed_writability_level); | ||||
| ATF_TP_ADD_TC(tp, peerclosed_writability_edge); | |||||
| ATF_TP_ADD_TC(tp, peershutdown_writability); | ATF_TP_ADD_TC(tp, peershutdown_writability); | ||||
| ATF_TP_ADD_TC(tp, peershutdown_readability); | ATF_TP_ADD_TC(tp, peershutdown_readability); | ||||
| ATF_TP_ADD_TC(tp, peershutdown_wakeup_select); | ATF_TP_ADD_TC(tp, peershutdown_wakeup_select); | ||||
| ATF_TP_ADD_TC(tp, peershutdown_wakeup_poll); | ATF_TP_ADD_TC(tp, peershutdown_wakeup_poll); | ||||
| ATF_TP_ADD_TC(tp, peershutdown_wakeup_kevent); | ATF_TP_ADD_TC(tp, peershutdown_wakeup_kevent); | ||||
| ATF_TP_ADD_TC(tp, ourshutdown_kevent); | ATF_TP_ADD_TC(tp, ourshutdown_kevent); | ||||
| ATF_TP_ADD_TC(tp, SO_SNDTIMEO); | ATF_TP_ADD_TC(tp, SO_SNDTIMEO); | ||||
| return atf_no_error(); | return atf_no_error(); | ||||
| } | } | ||||