2 * Copyright (c) 2014 Spectra Logic Corporation. All rights reserved.
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
6 * 1. Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * 2. Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in the
10 * documentation and/or other materials provided with the distribution.
12 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
16 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
32 #include <sys/socket.h>
43 #define MIN(x, y) ((x) < (y) ? (x) : (y))
44 #define MAX(x, y) ((x) > (y) ? (x) : (y))
47 do_socketpair(int *sv)
51 s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
53 ATF_REQUIRE(sv[0] >= 0);
54 ATF_REQUIRE(sv[1] >= 0);
55 ATF_REQUIRE(sv[0] != sv[1]);
59 do_socketpair_nonblocking(int *sv)
63 s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
65 ATF_REQUIRE(sv[0] >= 0);
66 ATF_REQUIRE(sv[1] >= 0);
67 ATF_REQUIRE(sv[0] != sv[1]);
68 ATF_REQUIRE(-1 != fcntl(sv[0], F_SETFL, O_NONBLOCK));
69 ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK));
73 * Returns a pair of sockets made the hard way: bind, listen, connect & accept
74 * @return const char* The path to the socket
77 mk_pair_of_sockets(int *sv)
79 struct sockaddr_un sun;
80 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
81 const char *path = "sock";
84 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
87 bzero(&sun, sizeof(sun));
88 sun.sun_family = AF_LOCAL;
89 sun.sun_len = sizeof(sun);
90 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
91 err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
96 /* Create the other socket */
97 s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
99 err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
102 atf_tc_fail("connect(2) failed");
106 s1 = accept(s, NULL, NULL);
109 atf_tc_fail("accept(2) failed");
117 static volatile sig_atomic_t got_sigpipe = 0;
119 shutdown_send_sigpipe_handler(int __unused x)
125 * Parameterized test function bodies
128 test_eagain(size_t sndbufsize, size_t rcvbufsize)
132 const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
133 const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
134 const int numpkts = totalsize / pktsize;
135 char sndbuf[pktsize];
138 /* setup the socket pair */
139 do_socketpair_nonblocking(sv);
140 /* Setup the buffers */
141 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
142 sizeof(sndbufsize)));
143 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
144 sizeof(rcvbufsize)));
146 bzero(sndbuf, pktsize);
147 /* Send data until we get EAGAIN */
148 for(i=0; i < numpkts; i++) {
149 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
155 atf_tc_fail("send returned < 0 but not EAGAIN");
159 atf_tc_fail("Never got EAGAIN");
163 test_sendrecv_symmetric_buffers(size_t bufsize, int blocking) {
166 const ssize_t pktsize = bufsize / 2;
167 char sndbuf[pktsize];
168 char recv_buf[pktsize];
169 ssize_t ssize, rsize;
171 /* setup the socket pair */
175 do_socketpair_nonblocking(sv);
177 /* Setup the buffers */
178 s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
179 ATF_REQUIRE_EQ(0, s);
180 s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
181 ATF_REQUIRE_EQ(0, s);
183 /* Fill the send buffer */
184 bzero(sndbuf, pktsize);
186 /* send and receive the packet */
187 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
190 atf_tc_fail("send returned < 0");
192 ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
195 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
198 atf_tc_fail("recv returned < 0");
200 ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
205 test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
207 int num_sent, num_received;
209 const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
211 char sndbuf[pktsize];
212 char rcvbuf[pktsize];
213 char comparebuf[pktsize];
214 ssize_t ssize, rsize;
215 bool currently_sending = true;
217 /* setup the socket pair */
218 do_socketpair_nonblocking(sv);
219 /* Setup the buffers */
220 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
221 sizeof(sndbufsize)));
222 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
223 sizeof(rcvbufsize)));
225 /* Send a total amount of data comfortably greater than the buffers */
226 numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
227 for (num_sent=0, num_received=0;
228 num_sent < numpkts || num_received < numpkts; ) {
229 if (currently_sending && num_sent < numpkts) {
230 /* The simulated sending process */
231 /* fill the buffer */
232 memset(sndbuf, num_sent, pktsize);
233 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
236 * XXX: This is bug-compatible with the kernel.
237 * The kernel returns EMSGSIZE when it should
240 if (errno == EAGAIN || errno == EMSGSIZE)
241 currently_sending = false;
244 atf_tc_fail("send failed");
247 ATF_CHECK_EQ_MSG(pktsize, ssize,
248 "expected %zd=send(...) but got %zd",
253 /* The simulated receiving process */
254 rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
256 if (errno == EAGAIN) {
257 currently_sending = true;
258 ATF_REQUIRE_MSG(num_sent < numpkts,
259 "Packets were lost!");
263 atf_tc_fail("recv failed");
266 ATF_CHECK_EQ_MSG(pktsize, rsize,
267 "expected %zd=recv(...) but got %zd",
269 memset(comparebuf, num_received, pktsize);
270 ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
272 "Received data miscompare");
283 } test_pipe_thread_data_t;
286 test_pipe_writer(void* args)
288 test_pipe_thread_data_t* td = args;
289 char sndbuf[td->pktsize];
293 for(i=0; i < td->numpkts; i++) {
294 memset(sndbuf, i, td->pktsize);
295 ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
298 atf_tc_fail("send returned < 0");
300 ATF_CHECK_EQ_MSG(td->pktsize, ssize,
301 "expected %zd=send(...) but got %zd",
308 test_pipe_reader(void* args)
310 test_pipe_thread_data_t* td = args;
311 char rcvbuf[td->pktsize];
312 char comparebuf[td->pktsize];
316 for(i=0; i < td->numpkts; i++) {
317 memset(comparebuf, i, td->pktsize);
318 rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
321 atf_tc_fail("recv returned < 0");
323 ATF_CHECK_EQ_MSG(td->pktsize, rsize,
324 "expected %zd=send(...) but got %zd",
326 d = memcmp(comparebuf, rcvbuf, td->pktsize);
327 ATF_CHECK_EQ_MSG(0, d,
328 "Received data miscompare on packet %d", i);
335 test_pipe(size_t sndbufsize, size_t rcvbufsize)
337 test_pipe_thread_data_t writer_data, reader_data;
338 pthread_t writer, reader;
340 const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
343 /* setup the socket pair */
345 /* Setup the buffers */
346 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
347 sizeof(sndbufsize)));
348 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
349 sizeof(rcvbufsize)));
351 /* Send a total amount of data comfortably greater than the buffers */
352 numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
354 /* Start the child threads */
355 writer_data.pktsize = pktsize;
356 writer_data.numpkts = numpkts;
357 writer_data.so = sv[0];
358 reader_data.pktsize = pktsize;
359 reader_data.numpkts = numpkts;
360 reader_data.so = sv[1];
361 ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
362 (void*)&writer_data));
364 * Give the writer time to start writing, and hopefully block, before
365 * starting the reader. This increases the likelihood of the test case
366 * failing due to PR kern/185812
369 ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
370 (void*)&reader_data));
372 /* Join the children */
373 ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
374 ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
382 /* Create a SEQPACKET socket */
383 ATF_TC_WITHOUT_HEAD(create_socket);
384 ATF_TC_BODY(create_socket, tc)
388 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
392 /* Create SEQPACKET sockets using socketpair(2) */
393 ATF_TC_WITHOUT_HEAD(create_socketpair);
394 ATF_TC_BODY(create_socketpair, tc)
399 s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
401 ATF_CHECK(sv[0] >= 0);
402 ATF_CHECK(sv[1] >= 0);
403 ATF_CHECK(sv[0] != sv[1]);
406 /* Call listen(2) without first calling bind(2). It should fail */
407 ATF_TC_WITHOUT_HEAD(listen_unbound);
408 ATF_TC_BODY(listen_unbound, tc)
412 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
415 /* expect listen to fail since we haven't called bind(2) */
419 /* Bind the socket to a file */
420 ATF_TC_WITHOUT_HEAD(bind);
421 ATF_TC_BODY(bind, tc)
423 struct sockaddr_un sun;
424 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
425 const char *path = "sock";
428 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
431 bzero(&sun, sizeof(sun));
432 sun.sun_family = AF_LOCAL;
433 sun.sun_len = sizeof(sun);
434 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
435 r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
439 /* listen(2) a socket that is already bound(2) should succeed */
440 ATF_TC_WITHOUT_HEAD(listen_bound);
441 ATF_TC_BODY(listen_bound, tc)
443 struct sockaddr_un sun;
444 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
445 const char *path = "sock";
448 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
451 bzero(&sun, sizeof(sun));
452 sun.sun_family = AF_LOCAL;
453 sun.sun_len = sizeof(sun);
454 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
455 r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
461 /* connect(2) can make a connection */
462 ATF_TC_WITHOUT_HEAD(connect);
463 ATF_TC_BODY(connect, tc)
465 struct sockaddr_un sun;
466 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
467 const char *path = "sock";
468 int s, r, err, l, s2;
470 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
473 bzero(&sun, sizeof(sun));
474 sun.sun_family = AF_LOCAL;
475 sun.sun_len = sizeof(sun);
476 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
477 r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
482 /* Create the other socket */
483 s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
484 ATF_REQUIRE(s2 >= 0);
485 err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
488 atf_tc_fail("connect(2) failed");
492 /* accept(2) can receive a connection */
493 ATF_TC_WITHOUT_HEAD(accept);
494 ATF_TC_BODY(accept, tc)
498 mk_pair_of_sockets(sv);
502 /* Set O_NONBLOCK on the socket */
503 ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
504 ATF_TC_BODY(fcntl_nonblock, tc)
508 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
510 if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
512 atf_tc_fail("fcntl failed");
516 /* Resize the send and receive buffers */
517 ATF_TC_WITHOUT_HEAD(resize_buffers);
518 ATF_TC_BODY(resize_buffers, tc)
524 socklen_t sl = sizeof(xs);
526 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
529 printf(" Socket Buffer Sizes\n");
530 printf(" | SNDBUF | RCVBUF |\n");
531 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
532 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
533 printf("Default | %7d | %7d |\n", xs, xr);
535 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
536 perror("setsockopt");
537 atf_tc_fail("setsockopt(SO_SNDBUF) failed");
539 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
540 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
541 printf("After changing SNDBUF | %7d | %7d |\n", xs, xr);
543 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
544 perror("setsockopt");
545 atf_tc_fail("setsockopt(SO_RCVBUF) failed");
547 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
548 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
549 printf("After changing RCVBUF | %7d | %7d |\n", xs, xr);
553 * Resize the send and receive buffers of a connected socketpair
554 * Print some useful debugging info too
556 ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
557 ATF_TC_BODY(resize_connected_buffers, tc)
564 socklen_t sl = sizeof(ls);
566 /* setup the socket pair */
569 printf(" Socket Buffer Sizes\n");
570 printf(" | Left Socket | Right Socket |\n");
571 printf(" | SNDBUF | RCVBUF | SNDBUF | RCVBUF |\n");
572 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
573 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
574 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
575 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
576 printf("Default | %7d | %7d | %7d | %7d |\n",
579 /* Update one side's send buffer */
580 err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
582 perror("setsockopt");
583 atf_tc_fail("setsockopt(SO_SNDBUF) failed");
586 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
587 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
588 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
589 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
590 printf("After changing Left's SNDBUF | %7d | %7d | %7d | %7d |\n",
593 /* Update the same side's receive buffer */
594 err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
596 perror("setsockopt");
597 atf_tc_fail("setsockopt(SO_RCVBUF) failed");
600 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
601 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
602 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
603 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
604 printf("After changing Left's RCVBUF | %7d | %7d | %7d | %7d |\n",
609 /* send(2) and recv(2) a single short record */
610 ATF_TC_WITHOUT_HEAD(send_recv);
611 ATF_TC_BODY(send_recv, tc)
614 const int bufsize = 64;
615 const char *data = "data";
616 char recv_buf[bufsize];
618 ssize_t ssize, rsize;
620 /* setup the socket pair */
623 /* send and receive a small packet */
624 datalen = strlen(data) + 1; /* +1 for the null */
625 ssize = send(sv[0], data, datalen, MSG_EOR);
628 atf_tc_fail("send returned < 0");
630 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
633 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
634 ATF_CHECK_EQ(datalen, rsize);
637 /* sendto(2) and recvfrom(2) a single short record
638 * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
639 * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
641 * According to the same spec, not all protocols are required to provide the
642 * source addres in recvfrom(2).
644 ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
645 ATF_TC_BODY(sendto_recvfrom, tc)
648 struct sockaddr_storage from;
650 const int bufsize = 64;
651 const char *data = "data";
652 char recv_buf[bufsize];
654 ssize_t ssize, rsize;
657 /* setup the socket pair */
658 path = mk_pair_of_sockets(sv);
660 /* send and receive a small packet */
661 datalen = strlen(data) + 1; /* +1 for the null */
662 ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
665 atf_tc_fail("send returned < 0");
667 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
670 fromlen = sizeof(from);
671 rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
672 (struct sockaddr*)&from, &fromlen);
675 atf_tc_fail("recvfrom returned < 0");
677 ATF_CHECK_EQ(datalen, rsize);
680 * FreeBSD does not currently provide the source address for SEQ_PACKET
681 * AF_UNIX sockets, and POSIX does not require it, so these two checks
682 * are disabled. If FreeBSD gains that feature in the future, then
683 * these checks may be reenabled
685 /* ATF_CHECK_EQ(PF_LOCAL, from.ss_family); */
686 /* ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); */
690 * send(2) and recv(2) a single short record with sockets created the
691 * traditional way, involving bind, listen, connect, and accept
693 ATF_TC_WITHOUT_HEAD(send_recv_with_connect);
694 ATF_TC_BODY(send_recv_with_connect, tc)
697 const int bufsize = 64;
698 const char *data = "data";
699 char recv_buf[bufsize];
701 ssize_t ssize, rsize;
703 mk_pair_of_sockets(sv);
705 /* send and receive a small packet */
706 datalen = strlen(data) + 1; /* +1 for the null */
707 ssize = send(sv[0], data, datalen, MSG_EOR);
710 atf_tc_fail("send returned < 0");
712 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
715 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
716 ATF_CHECK_EQ(datalen, rsize);
719 /* send(2) should fail on a shutdown socket */
720 ATF_TC_WITHOUT_HEAD(shutdown_send);
721 ATF_TC_BODY(shutdown_send, tc)
724 const char *data = "data";
727 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
729 ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
730 /* USE MSG_NOSIGNAL so we don't get SIGPIPE */
731 ssize = send(s, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
732 ATF_CHECK_EQ(EPIPE, errno);
733 ATF_CHECK_EQ(-1, ssize);
736 /* send(2) should cause SIGPIPE on a shutdown socket */
737 ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
738 ATF_TC_BODY(shutdown_send_sigpipe, tc)
741 const char *data = "data";
744 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
746 ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
747 ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
748 ssize = send(s, data, sizeof(data), MSG_EOR);
749 ATF_CHECK_EQ(1, got_sigpipe);
752 /* nonblocking send(2) and recv(2) a single short record */
753 ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
754 ATF_TC_BODY(send_recv_nonblocking, tc)
757 const int bufsize = 64;
758 const char *data = "data";
759 char recv_buf[bufsize];
761 ssize_t ssize, rsize;
763 /* setup the socket pair */
764 do_socketpair_nonblocking(sv);
766 /* Verify that there is nothing to receive */
767 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
768 ATF_CHECK_EQ(EAGAIN, errno);
769 ATF_CHECK_EQ(-1, rsize);
771 /* send and receive a small packet */
772 datalen = strlen(data) + 1; /* +1 for the null */
773 ssize = send(sv[0], data, datalen, MSG_EOR);
776 atf_tc_fail("send returned < 0");
778 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
781 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
782 ATF_CHECK_EQ(datalen, rsize);
786 * We should get EMSGSIZE if we try to send a message larger than the socket
787 * buffer, with blocking sockets
789 ATF_TC_WITHOUT_HEAD(emsgsize);
790 ATF_TC_BODY(emsgsize, tc)
793 const size_t sndbufsize = 8192;
794 const size_t rcvbufsize = 8192;
795 const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
796 char sndbuf[pktsize];
799 /* setup the socket pair */
801 /* Setup the buffers */
802 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
803 sizeof(sndbufsize)));
804 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
805 sizeof(rcvbufsize)));
807 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
808 ATF_CHECK_EQ(EMSGSIZE, errno);
809 ATF_CHECK_EQ(-1, ssize);
813 * We should get EMSGSIZE if we try to send a message larger than the socket
814 * buffer, with nonblocking sockets
816 ATF_TC_WITHOUT_HEAD(emsgsize_nonblocking);
817 ATF_TC_BODY(emsgsize_nonblocking, tc)
820 const size_t sndbufsize = 8192;
821 const size_t rcvbufsize = 8192;
822 const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
823 char sndbuf[pktsize];
826 /* setup the socket pair */
827 do_socketpair_nonblocking(sv);
828 /* Setup the buffers */
829 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
830 sizeof(sndbufsize)));
831 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
832 sizeof(rcvbufsize)));
834 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
835 ATF_CHECK_EQ(EMSGSIZE, errno);
836 ATF_CHECK_EQ(-1, ssize);
841 * We should get EAGAIN if we try to send a message larger than the socket
842 * buffer, with nonblocking sockets. Test with several different sockbuf sizes
844 ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
845 ATF_TC_BODY(eagain_8k_8k, tc)
847 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
848 test_eagain(8192, 8192);
850 ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
851 ATF_TC_BODY(eagain_8k_128k, tc)
853 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
854 test_eagain(8192, 131072);
856 ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
857 ATF_TC_BODY(eagain_128k_8k, tc)
859 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
860 test_eagain(131072, 8192);
862 ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
863 ATF_TC_BODY(eagain_128k_128k, tc)
865 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
866 test_eagain(131072, 131072);
871 * nonblocking send(2) and recv(2) of several records, which should collectively
872 * fill up the send buffer but not the receive buffer
874 ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
875 ATF_TC_BODY(rcvbuf_oversized, tc)
879 const int pktsize = 1024;
880 const size_t sndbufsize = 8192;
881 const size_t rcvbufsize = 131072;
882 const size_t geometric_mean_bufsize = 32768;
883 const int numpkts = geometric_mean_bufsize / pktsize;
884 char sndbuf[pktsize];
885 char recv_buf[pktsize];
886 ssize_t ssize, rsize;
888 /* setup the socket pair */
889 do_socketpair_nonblocking(sv);
890 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
891 sizeof(sndbufsize)));
892 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
893 sizeof(rcvbufsize)));
896 * Send and receive packets that are collectively greater than the send
897 * buffer, but less than the receive buffer
899 for (i=0; i < numpkts; i++) {
900 /* Fill the buffer */
901 memset(sndbuf, i, pktsize);
903 /* send the packet */
904 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
907 atf_tc_fail("send returned < 0");
909 ATF_CHECK_EQ_MSG(pktsize, ssize,
910 "expected %zd=send(...) but got %zd", pktsize, ssize);
914 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
917 atf_tc_fail("recv returned < 0");
919 ATF_CHECK_EQ_MSG(pktsize, rsize,
920 "expected %zd=send(...) but got %zd", pktsize, rsize);
922 /* Verify the contents */
923 ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
924 "Received data miscompare");
927 /* Trying to receive again should return EAGAIN */
928 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
929 ATF_CHECK_EQ(EAGAIN, errno);
930 ATF_CHECK_EQ(-1, rsize);
934 * Simulate the behavior of a blocking pipe. The sender will send until his
935 * buffer fills up, then we'll simulate a scheduler switch that will allow the
936 * receiver to read until his buffer empties. Repeat the process until the
937 * transfer is complete.
938 * Repeat the test with multiple send and receive buffer sizes
940 ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
941 ATF_TC_BODY(pipe_simulator_8k_8k, tc)
943 test_pipe_simulator(8192, 8192);
946 ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
947 ATF_TC_BODY(pipe_simulator_8k_128k, tc)
949 test_pipe_simulator(8192, 131072);
952 ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
953 ATF_TC_BODY(pipe_simulator_128k_8k, tc)
955 test_pipe_simulator(131072, 8192);
958 ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
959 ATF_TC_BODY(pipe_simulator_128k_128k, tc)
961 test_pipe_simulator(131072, 131072);
965 * Test blocking I/O by passing data between two threads. The total amount of
966 * data will be >> buffer size to force blocking. Repeat the test with multiple
967 * send and receive buffer sizes
969 ATF_TC_WITHOUT_HEAD(pipe_8k_8k);
970 ATF_TC_BODY(pipe_8k_8k, tc)
972 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
973 test_pipe(8192, 8192);
976 ATF_TC_WITHOUT_HEAD(pipe_8k_128k);
977 ATF_TC_BODY(pipe_8k_128k, tc)
979 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
980 test_pipe(8192, 131072);
983 ATF_TC_WITHOUT_HEAD(pipe_128k_8k);
984 ATF_TC_BODY(pipe_128k_8k, tc)
987 * kern/185812 causes this test case to both fail and timeout. The
988 * atf-c-api(3) doesn't have a way to set such an expectation.
989 * If you use atf_tc_expect_fail, then it will timeout. If you use
990 * atf_tc_expect_timeout, then it will fail. If you use both, then it
991 * will show up as an unexpected pass, which is much worse
993 * https://code.google.com/p/kyua/issues/detail?id=76
995 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
996 test_pipe(131072, 8192);
999 ATF_TC_WITHOUT_HEAD(pipe_128k_128k);
1000 ATF_TC_BODY(pipe_128k_128k, tc)
1002 atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE instead of EAGAIN");
1003 test_pipe(131072, 131072);
1008 * Test single-packet I/O with and without blocking, with symmetric buffers of
1011 ATF_TC_WITHOUT_HEAD(sendrecv_8k);
1012 ATF_TC_BODY(sendrecv_8k, tc)
1014 test_sendrecv_symmetric_buffers(8 * 1024, true);
1016 ATF_TC_WITHOUT_HEAD(sendrecv_16k);
1017 ATF_TC_BODY(sendrecv_16k, tc)
1019 test_sendrecv_symmetric_buffers(16 * 1024, true);
1021 ATF_TC_WITHOUT_HEAD(sendrecv_32k);
1022 ATF_TC_BODY(sendrecv_32k, tc)
1024 test_sendrecv_symmetric_buffers(32 * 1024, true);
1026 ATF_TC_WITHOUT_HEAD(sendrecv_64k);
1027 ATF_TC_BODY(sendrecv_64k, tc)
1029 test_sendrecv_symmetric_buffers(64 * 1024, true);
1031 ATF_TC_WITHOUT_HEAD(sendrecv_128k);
1032 ATF_TC_BODY(sendrecv_128k, tc)
1034 test_sendrecv_symmetric_buffers(128 * 1024, true);
1036 ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1037 ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1039 test_sendrecv_symmetric_buffers(8 * 1024, false);
1041 ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1042 ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1044 test_sendrecv_symmetric_buffers(16 * 1024, false);
1046 ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1047 ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1049 test_sendrecv_symmetric_buffers(32 * 1024, false);
1051 ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1052 ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1054 test_sendrecv_symmetric_buffers(64 * 1024, false);
1056 ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1057 ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1059 test_sendrecv_symmetric_buffers(128 * 1024, false);
1069 /* Basic creation and connection tests */
1070 ATF_TP_ADD_TC(tp, create_socket);
1071 ATF_TP_ADD_TC(tp, create_socketpair);
1072 ATF_TP_ADD_TC(tp, listen_unbound);
1073 ATF_TP_ADD_TC(tp, bind);
1074 ATF_TP_ADD_TC(tp, listen_bound);
1075 ATF_TP_ADD_TC(tp, connect);
1076 ATF_TP_ADD_TC(tp, accept);
1077 ATF_TP_ADD_TC(tp, fcntl_nonblock);
1078 ATF_TP_ADD_TC(tp, resize_buffers);
1079 ATF_TP_ADD_TC(tp, resize_connected_buffers);
1081 /* Unthreaded I/O tests */
1082 ATF_TP_ADD_TC(tp, send_recv);
1083 ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1084 ATF_TP_ADD_TC(tp, send_recv_with_connect);
1085 ATF_TP_ADD_TC(tp, sendto_recvfrom);
1086 ATF_TP_ADD_TC(tp, shutdown_send);
1087 ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1088 ATF_TP_ADD_TC(tp, emsgsize);
1089 ATF_TP_ADD_TC(tp, emsgsize_nonblocking);
1090 ATF_TP_ADD_TC(tp, eagain_8k_8k);
1091 ATF_TP_ADD_TC(tp, eagain_8k_128k);
1092 ATF_TP_ADD_TC(tp, eagain_128k_8k);
1093 ATF_TP_ADD_TC(tp, eagain_128k_128k);
1094 ATF_TP_ADD_TC(tp, sendrecv_8k);
1095 ATF_TP_ADD_TC(tp, sendrecv_16k);
1096 ATF_TP_ADD_TC(tp, sendrecv_32k);
1097 ATF_TP_ADD_TC(tp, sendrecv_64k);
1098 ATF_TP_ADD_TC(tp, sendrecv_128k);
1099 ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1100 ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1101 ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1102 ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1103 ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1104 ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1105 ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1106 ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1107 ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1108 ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1110 /* Threaded I/O tests with blocking sockets */
1111 ATF_TP_ADD_TC(tp, pipe_8k_8k);
1112 ATF_TP_ADD_TC(tp, pipe_8k_128k);
1113 ATF_TP_ADD_TC(tp, pipe_128k_8k);
1114 ATF_TP_ADD_TC(tp, pipe_128k_128k);
1116 return atf_no_error();