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));
95 /* Create the other socket */
96 s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
98 err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
101 atf_tc_fail("connect(2) failed");
105 s1 = accept(s, NULL, NULL);
108 atf_tc_fail("accept(2) failed");
119 static volatile sig_atomic_t got_sigpipe = 0;
121 shutdown_send_sigpipe_handler(int __unused x)
127 * Parameterized test function bodies
130 test_eagain(size_t sndbufsize, size_t rcvbufsize)
134 const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
135 const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
136 const int numpkts = totalsize / pktsize;
137 char sndbuf[pktsize];
140 /* setup the socket pair */
141 do_socketpair_nonblocking(sv);
142 /* Setup the buffers */
143 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
144 sizeof(sndbufsize)));
145 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
146 sizeof(rcvbufsize)));
148 bzero(sndbuf, pktsize);
149 /* Send data until we get EAGAIN */
150 for(i=0; i < numpkts; i++) {
151 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
153 if (errno == EAGAIN) {
160 atf_tc_fail("send returned < 0 but not EAGAIN");
164 atf_tc_fail("Never got EAGAIN");
168 test_sendrecv_symmetric_buffers(size_t bufsize, int blocking) {
171 const ssize_t pktsize = bufsize / 2;
172 char sndbuf[pktsize];
173 char recv_buf[pktsize];
174 ssize_t ssize, rsize;
176 /* setup the socket pair */
180 do_socketpair_nonblocking(sv);
182 /* Setup the buffers */
183 s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
184 ATF_REQUIRE_EQ(0, s);
185 s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
186 ATF_REQUIRE_EQ(0, s);
188 /* Fill the send buffer */
189 bzero(sndbuf, pktsize);
191 /* send and receive the packet */
192 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
195 atf_tc_fail("send returned < 0");
197 ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
200 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
203 atf_tc_fail("recv returned < 0");
205 ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
212 test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
214 int num_sent, num_received;
216 const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
218 char sndbuf[pktsize];
219 char rcvbuf[pktsize];
220 char comparebuf[pktsize];
221 ssize_t ssize, rsize;
222 bool currently_sending = true;
224 /* setup the socket pair */
225 do_socketpair_nonblocking(sv);
226 /* Setup the buffers */
227 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
228 sizeof(sndbufsize)));
229 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
230 sizeof(rcvbufsize)));
232 /* Send a total amount of data comfortably greater than the buffers */
233 numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
234 for (num_sent=0, num_received=0;
235 num_sent < numpkts || num_received < numpkts; ) {
236 if (currently_sending && num_sent < numpkts) {
237 /* The simulated sending process */
238 /* fill the buffer */
239 memset(sndbuf, num_sent, pktsize);
240 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
243 * XXX: This is bug-compatible with the kernel.
244 * The kernel returns EMSGSIZE when it should
247 if (errno == EAGAIN || errno == EMSGSIZE)
248 currently_sending = false;
251 atf_tc_fail("send failed");
254 ATF_CHECK_EQ_MSG(pktsize, ssize,
255 "expected %zd=send(...) but got %zd",
260 /* The simulated receiving process */
261 rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
263 if (errno == EAGAIN) {
264 currently_sending = true;
265 ATF_REQUIRE_MSG(num_sent < numpkts,
266 "Packets were lost!");
270 atf_tc_fail("recv failed");
273 ATF_CHECK_EQ_MSG(pktsize, rsize,
274 "expected %zd=recv(...) but got %zd",
276 memset(comparebuf, num_received, pktsize);
277 ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
279 "Received data miscompare");
292 } test_pipe_thread_data_t;
295 test_pipe_writer(void* args)
297 test_pipe_thread_data_t* td = args;
298 char sndbuf[td->pktsize];
302 for(i=0; i < td->numpkts; i++) {
303 memset(sndbuf, i, td->pktsize);
304 ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
307 atf_tc_fail("send returned < 0");
309 ATF_CHECK_EQ_MSG(td->pktsize, ssize,
310 "expected %zd=send(...) but got %zd",
317 test_pipe_reader(void* args)
319 test_pipe_thread_data_t* td = args;
320 char rcvbuf[td->pktsize];
321 char comparebuf[td->pktsize];
325 for(i=0; i < td->numpkts; i++) {
326 memset(comparebuf, i, td->pktsize);
327 rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
330 atf_tc_fail("recv returned < 0");
332 ATF_CHECK_EQ_MSG(td->pktsize, rsize,
333 "expected %zd=send(...) but got %zd",
335 d = memcmp(comparebuf, rcvbuf, td->pktsize);
336 ATF_CHECK_EQ_MSG(0, d,
337 "Received data miscompare on packet %d", i);
344 test_pipe(size_t sndbufsize, size_t rcvbufsize)
346 test_pipe_thread_data_t writer_data, reader_data;
347 pthread_t writer, reader;
349 const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
352 /* setup the socket pair */
354 /* Setup the buffers */
355 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
356 sizeof(sndbufsize)));
357 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
358 sizeof(rcvbufsize)));
360 /* Send a total amount of data comfortably greater than the buffers */
361 numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
363 /* Start the child threads */
364 writer_data.pktsize = pktsize;
365 writer_data.numpkts = numpkts;
366 writer_data.so = sv[0];
367 reader_data.pktsize = pktsize;
368 reader_data.numpkts = numpkts;
369 reader_data.so = sv[1];
370 ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
371 (void*)&writer_data));
373 * Give the writer time to start writing, and hopefully block, before
374 * starting the reader. This increases the likelihood of the test case
375 * failing due to PR kern/185812
378 ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
379 (void*)&reader_data));
381 /* Join the children */
382 ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
383 ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
393 /* Create a SEQPACKET socket */
394 ATF_TC_WITHOUT_HEAD(create_socket);
395 ATF_TC_BODY(create_socket, tc)
399 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
404 /* Create SEQPACKET sockets using socketpair(2) */
405 ATF_TC_WITHOUT_HEAD(create_socketpair);
406 ATF_TC_BODY(create_socketpair, tc)
411 s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
413 ATF_CHECK(sv[0] >= 0);
414 ATF_CHECK(sv[1] >= 0);
415 ATF_CHECK(sv[0] != sv[1]);
420 /* Call listen(2) without first calling bind(2). It should fail */
421 ATF_TC_WITHOUT_HEAD(listen_unbound);
422 ATF_TC_BODY(listen_unbound, tc)
426 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
429 /* expect listen to fail since we haven't called bind(2) */
434 /* Bind the socket to a file */
435 ATF_TC_WITHOUT_HEAD(bind);
436 ATF_TC_BODY(bind, tc)
438 struct sockaddr_un sun;
439 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
440 const char *path = "sock";
443 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
446 bzero(&sun, sizeof(sun));
447 sun.sun_family = AF_LOCAL;
448 sun.sun_len = sizeof(sun);
449 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
450 r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
455 /* listen(2) a socket that is already bound(2) should succeed */
456 ATF_TC_WITHOUT_HEAD(listen_bound);
457 ATF_TC_BODY(listen_bound, tc)
459 struct sockaddr_un sun;
460 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
461 const char *path = "sock";
464 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
467 bzero(&sun, sizeof(sun));
468 sun.sun_family = AF_LOCAL;
469 sun.sun_len = sizeof(sun);
470 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
471 r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
478 /* connect(2) can make a connection */
479 ATF_TC_WITHOUT_HEAD(connect);
480 ATF_TC_BODY(connect, tc)
482 struct sockaddr_un sun;
483 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
484 const char *path = "sock";
485 int s, r, err, l, s2;
487 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
490 bzero(&sun, sizeof(sun));
491 sun.sun_family = AF_LOCAL;
492 sun.sun_len = sizeof(sun);
493 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
494 r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
499 /* Create the other socket */
500 s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
501 ATF_REQUIRE(s2 >= 0);
502 err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
505 atf_tc_fail("connect(2) failed");
511 /* accept(2) can receive a connection */
512 ATF_TC_WITHOUT_HEAD(accept);
513 ATF_TC_BODY(accept, tc)
517 mk_pair_of_sockets(sv);
523 /* Set O_NONBLOCK on the socket */
524 ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
525 ATF_TC_BODY(fcntl_nonblock, tc)
529 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
531 if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
533 atf_tc_fail("fcntl failed");
538 /* Resize the send and receive buffers */
539 ATF_TC_WITHOUT_HEAD(resize_buffers);
540 ATF_TC_BODY(resize_buffers, tc)
546 socklen_t sl = sizeof(xs);
548 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
551 printf(" Socket Buffer Sizes\n");
552 printf(" | SNDBUF | RCVBUF |\n");
553 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
554 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
555 printf("Default | %7d | %7d |\n", xs, xr);
557 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
558 perror("setsockopt");
559 atf_tc_fail("setsockopt(SO_SNDBUF) failed");
561 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
562 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
563 printf("After changing SNDBUF | %7d | %7d |\n", xs, xr);
565 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
566 perror("setsockopt");
567 atf_tc_fail("setsockopt(SO_RCVBUF) failed");
569 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
570 ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
571 printf("After changing RCVBUF | %7d | %7d |\n", xs, xr);
576 * Resize the send and receive buffers of a connected socketpair
577 * Print some useful debugging info too
579 ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
580 ATF_TC_BODY(resize_connected_buffers, tc)
587 socklen_t sl = sizeof(ls);
589 /* setup the socket pair */
592 printf(" Socket Buffer Sizes\n");
593 printf(" | Left Socket | Right Socket |\n");
594 printf(" | SNDBUF | RCVBUF | SNDBUF | RCVBUF |\n");
595 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
596 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
597 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
598 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
599 printf("Default | %7d | %7d | %7d | %7d |\n",
602 /* Update one side's send buffer */
603 err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
605 perror("setsockopt");
606 atf_tc_fail("setsockopt(SO_SNDBUF) failed");
609 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
610 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
611 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
612 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
613 printf("After changing Left's SNDBUF | %7d | %7d | %7d | %7d |\n",
616 /* Update the same side's receive buffer */
617 err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
619 perror("setsockopt");
620 atf_tc_fail("setsockopt(SO_RCVBUF) failed");
623 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
624 ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
625 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
626 ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
627 printf("After changing Left's RCVBUF | %7d | %7d | %7d | %7d |\n",
634 /* send(2) and recv(2) a single short record */
635 ATF_TC_WITHOUT_HEAD(send_recv);
636 ATF_TC_BODY(send_recv, tc)
639 const int bufsize = 64;
640 const char *data = "data";
641 char recv_buf[bufsize];
643 ssize_t ssize, rsize;
645 /* setup the socket pair */
648 /* send and receive a small packet */
649 datalen = strlen(data) + 1; /* +1 for the null */
650 ssize = send(sv[0], data, datalen, MSG_EOR);
653 atf_tc_fail("send returned < 0");
655 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
658 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
659 ATF_CHECK_EQ(datalen, rsize);
664 /* sendto(2) and recvfrom(2) a single short record
665 * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
666 * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
668 * According to the same spec, not all protocols are required to provide the
669 * source addres in recvfrom(2).
671 ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
672 ATF_TC_BODY(sendto_recvfrom, tc)
675 struct sockaddr_storage from;
677 const int bufsize = 64;
678 const char *data = "data";
679 char recv_buf[bufsize];
681 ssize_t ssize, rsize;
684 /* setup the socket pair */
685 path = mk_pair_of_sockets(sv);
687 /* send and receive a small packet */
688 datalen = strlen(data) + 1; /* +1 for the null */
689 ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
692 atf_tc_fail("send returned < 0");
694 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
697 fromlen = sizeof(from);
698 rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
699 (struct sockaddr*)&from, &fromlen);
702 atf_tc_fail("recvfrom returned < 0");
704 ATF_CHECK_EQ(datalen, rsize);
707 * FreeBSD does not currently provide the source address for SEQ_PACKET
708 * AF_UNIX sockets, and POSIX does not require it, so these two checks
709 * are disabled. If FreeBSD gains that feature in the future, then
710 * these checks may be reenabled
712 /* ATF_CHECK_EQ(PF_LOCAL, from.ss_family); */
713 /* ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); */
719 * send(2) and recv(2) a single short record with sockets created the
720 * traditional way, involving bind, listen, connect, and accept
722 ATF_TC_WITHOUT_HEAD(send_recv_with_connect);
723 ATF_TC_BODY(send_recv_with_connect, tc)
726 const int bufsize = 64;
727 const char *data = "data";
728 char recv_buf[bufsize];
730 ssize_t ssize, rsize;
732 mk_pair_of_sockets(sv);
734 /* send and receive a small packet */
735 datalen = strlen(data) + 1; /* +1 for the null */
736 ssize = send(sv[0], data, datalen, MSG_EOR);
739 atf_tc_fail("send returned < 0");
741 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
744 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
745 ATF_CHECK_EQ(datalen, rsize);
750 /* send(2) should fail on a shutdown socket */
751 ATF_TC_WITHOUT_HEAD(shutdown_send);
752 ATF_TC_BODY(shutdown_send, tc)
754 struct sockaddr_un sun;
755 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
756 const char *path = "sock";
757 const char *data = "data";
761 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
764 bzero(&sun, sizeof(sun));
765 sun.sun_family = AF_LOCAL;
766 sun.sun_len = sizeof(sun);
767 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
768 err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
770 ATF_CHECK_EQ(0, err);
772 /* Create the other socket */
773 s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
774 ATF_REQUIRE(s2 >= 0);
775 err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
778 atf_tc_fail("connect(2) failed");
781 ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
782 /* USE MSG_NOSIGNAL so we don't get SIGPIPE */
783 ssize = send(s2, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
784 ATF_CHECK_EQ(EPIPE, errno);
785 ATF_CHECK_EQ(-1, ssize);
790 /* send(2) should cause SIGPIPE on a shutdown socket */
791 ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
792 ATF_TC_BODY(shutdown_send_sigpipe, tc)
794 struct sockaddr_un sun;
795 /* ATF's isolation mechanisms will guarantee uniqueness of this file */
796 const char *path = "sock";
797 const char *data = "data";
801 s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
804 bzero(&sun, sizeof(sun));
805 sun.sun_family = AF_LOCAL;
806 sun.sun_len = sizeof(sun);
807 strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
808 err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
810 ATF_CHECK_EQ(0, err);
812 /* Create the other socket */
813 s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
814 ATF_REQUIRE(s2 >= 0);
815 err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
818 atf_tc_fail("connect(2) failed");
821 ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
822 ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
823 ssize = send(s2, data, sizeof(data), MSG_EOR);
824 ATF_CHECK_EQ(1, got_sigpipe);
829 /* nonblocking send(2) and recv(2) a single short record */
830 ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
831 ATF_TC_BODY(send_recv_nonblocking, tc)
834 const int bufsize = 64;
835 const char *data = "data";
836 char recv_buf[bufsize];
838 ssize_t ssize, rsize;
840 /* setup the socket pair */
841 do_socketpair_nonblocking(sv);
843 /* Verify that there is nothing to receive */
844 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
845 ATF_CHECK_EQ(EAGAIN, errno);
846 ATF_CHECK_EQ(-1, rsize);
848 /* send and receive a small packet */
849 datalen = strlen(data) + 1; /* +1 for the null */
850 ssize = send(sv[0], data, datalen, MSG_EOR);
853 atf_tc_fail("send returned < 0");
855 ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
858 rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
859 ATF_CHECK_EQ(datalen, rsize);
865 * We should get EMSGSIZE if we try to send a message larger than the socket
866 * buffer, with blocking sockets
868 ATF_TC_WITHOUT_HEAD(emsgsize);
869 ATF_TC_BODY(emsgsize, tc)
872 const size_t sndbufsize = 8192;
873 const size_t rcvbufsize = 8192;
874 const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
875 char sndbuf[pktsize];
878 /* setup the socket pair */
880 /* Setup the buffers */
881 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
882 sizeof(sndbufsize)));
883 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
884 sizeof(rcvbufsize)));
886 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
887 ATF_CHECK_EQ(EMSGSIZE, errno);
888 ATF_CHECK_EQ(-1, ssize);
894 * We should get EMSGSIZE if we try to send a message larger than the socket
895 * buffer, with nonblocking sockets
897 ATF_TC_WITHOUT_HEAD(emsgsize_nonblocking);
898 ATF_TC_BODY(emsgsize_nonblocking, tc)
901 const size_t sndbufsize = 8192;
902 const size_t rcvbufsize = 8192;
903 const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
904 char sndbuf[pktsize];
907 /* setup the socket pair */
908 do_socketpair_nonblocking(sv);
909 /* Setup the buffers */
910 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
911 sizeof(sndbufsize)));
912 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
913 sizeof(rcvbufsize)));
915 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
916 ATF_CHECK_EQ(EMSGSIZE, errno);
917 ATF_CHECK_EQ(-1, ssize);
924 * We should get EAGAIN if we try to send a message larger than the socket
925 * buffer, with nonblocking sockets. Test with several different sockbuf sizes
927 ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
928 ATF_TC_BODY(eagain_8k_8k, tc)
930 test_eagain(8192, 8192);
932 ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
933 ATF_TC_BODY(eagain_8k_128k, tc)
935 test_eagain(8192, 131072);
937 ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
938 ATF_TC_BODY(eagain_128k_8k, tc)
940 test_eagain(131072, 8192);
942 ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
943 ATF_TC_BODY(eagain_128k_128k, tc)
945 test_eagain(131072, 131072);
950 * nonblocking send(2) and recv(2) of several records, which should collectively
951 * fill up the send buffer but not the receive buffer
953 ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
954 ATF_TC_BODY(rcvbuf_oversized, tc)
958 const ssize_t pktsize = 1024;
959 const size_t sndbufsize = 8192;
960 const size_t rcvbufsize = 131072;
961 const size_t geometric_mean_bufsize = 32768;
962 const int numpkts = geometric_mean_bufsize / pktsize;
963 char sndbuf[pktsize];
964 char recv_buf[pktsize];
965 ssize_t ssize, rsize;
967 /* setup the socket pair */
968 do_socketpair_nonblocking(sv);
969 ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
970 sizeof(sndbufsize)));
971 ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
972 sizeof(rcvbufsize)));
975 * Send and receive packets that are collectively greater than the send
976 * buffer, but less than the receive buffer
978 for (i=0; i < numpkts; i++) {
979 /* Fill the buffer */
980 memset(sndbuf, i, pktsize);
982 /* send the packet */
983 ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
986 atf_tc_fail("send returned < 0");
988 ATF_CHECK_EQ_MSG(pktsize, ssize,
989 "expected %zd=send(...) but got %zd", pktsize, ssize);
993 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
996 atf_tc_fail("recv returned < 0");
998 ATF_CHECK_EQ_MSG(pktsize, rsize,
999 "expected %zd=send(...) but got %zd", pktsize, rsize);
1001 /* Verify the contents */
1002 ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
1003 "Received data miscompare");
1006 /* Trying to receive again should return EAGAIN */
1007 rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
1008 ATF_CHECK_EQ(EAGAIN, errno);
1009 ATF_CHECK_EQ(-1, rsize);
1015 * Simulate the behavior of a blocking pipe. The sender will send until his
1016 * buffer fills up, then we'll simulate a scheduler switch that will allow the
1017 * receiver to read until his buffer empties. Repeat the process until the
1018 * transfer is complete.
1019 * Repeat the test with multiple send and receive buffer sizes
1021 ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
1022 ATF_TC_BODY(pipe_simulator_8k_8k, tc)
1024 test_pipe_simulator(8192, 8192);
1027 ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
1028 ATF_TC_BODY(pipe_simulator_8k_128k, tc)
1030 test_pipe_simulator(8192, 131072);
1033 ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
1034 ATF_TC_BODY(pipe_simulator_128k_8k, tc)
1036 test_pipe_simulator(131072, 8192);
1039 ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
1040 ATF_TC_BODY(pipe_simulator_128k_128k, tc)
1042 test_pipe_simulator(131072, 131072);
1046 * Test blocking I/O by passing data between two threads. The total amount of
1047 * data will be >> buffer size to force blocking. Repeat the test with multiple
1048 * send and receive buffer sizes
1050 ATF_TC_WITHOUT_HEAD(pipe_8k_8k);
1051 ATF_TC_BODY(pipe_8k_8k, tc)
1053 test_pipe(8192, 8192);
1056 ATF_TC_WITHOUT_HEAD(pipe_8k_128k);
1057 ATF_TC_BODY(pipe_8k_128k, tc)
1059 test_pipe(8192, 131072);
1062 ATF_TC_WITHOUT_HEAD(pipe_128k_8k);
1063 ATF_TC_BODY(pipe_128k_8k, tc)
1065 test_pipe(131072, 8192);
1068 ATF_TC_WITHOUT_HEAD(pipe_128k_128k);
1069 ATF_TC_BODY(pipe_128k_128k, tc)
1071 test_pipe(131072, 131072);
1076 * Test single-packet I/O with and without blocking, with symmetric buffers of
1079 ATF_TC_WITHOUT_HEAD(sendrecv_8k);
1080 ATF_TC_BODY(sendrecv_8k, tc)
1082 test_sendrecv_symmetric_buffers(8 * 1024, true);
1084 ATF_TC_WITHOUT_HEAD(sendrecv_16k);
1085 ATF_TC_BODY(sendrecv_16k, tc)
1087 test_sendrecv_symmetric_buffers(16 * 1024, true);
1089 ATF_TC_WITHOUT_HEAD(sendrecv_32k);
1090 ATF_TC_BODY(sendrecv_32k, tc)
1092 test_sendrecv_symmetric_buffers(32 * 1024, true);
1094 ATF_TC_WITHOUT_HEAD(sendrecv_64k);
1095 ATF_TC_BODY(sendrecv_64k, tc)
1097 test_sendrecv_symmetric_buffers(64 * 1024, true);
1099 ATF_TC_WITHOUT_HEAD(sendrecv_128k);
1100 ATF_TC_BODY(sendrecv_128k, tc)
1102 test_sendrecv_symmetric_buffers(128 * 1024, true);
1104 ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1105 ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1107 test_sendrecv_symmetric_buffers(8 * 1024, false);
1109 ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1110 ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1112 test_sendrecv_symmetric_buffers(16 * 1024, false);
1114 ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1115 ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1117 test_sendrecv_symmetric_buffers(32 * 1024, false);
1119 ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1120 ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1122 test_sendrecv_symmetric_buffers(64 * 1024, false);
1124 ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1125 ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1127 test_sendrecv_symmetric_buffers(128 * 1024, false);
1137 /* Basic creation and connection tests */
1138 ATF_TP_ADD_TC(tp, create_socket);
1139 ATF_TP_ADD_TC(tp, create_socketpair);
1140 ATF_TP_ADD_TC(tp, listen_unbound);
1141 ATF_TP_ADD_TC(tp, bind);
1142 ATF_TP_ADD_TC(tp, listen_bound);
1143 ATF_TP_ADD_TC(tp, connect);
1144 ATF_TP_ADD_TC(tp, accept);
1145 ATF_TP_ADD_TC(tp, fcntl_nonblock);
1146 ATF_TP_ADD_TC(tp, resize_buffers);
1147 ATF_TP_ADD_TC(tp, resize_connected_buffers);
1149 /* Unthreaded I/O tests */
1150 ATF_TP_ADD_TC(tp, send_recv);
1151 ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1152 ATF_TP_ADD_TC(tp, send_recv_with_connect);
1153 ATF_TP_ADD_TC(tp, sendto_recvfrom);
1154 ATF_TP_ADD_TC(tp, shutdown_send);
1155 ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1156 ATF_TP_ADD_TC(tp, emsgsize);
1157 ATF_TP_ADD_TC(tp, emsgsize_nonblocking);
1158 ATF_TP_ADD_TC(tp, eagain_8k_8k);
1159 ATF_TP_ADD_TC(tp, eagain_8k_128k);
1160 ATF_TP_ADD_TC(tp, eagain_128k_8k);
1161 ATF_TP_ADD_TC(tp, eagain_128k_128k);
1162 ATF_TP_ADD_TC(tp, sendrecv_8k);
1163 ATF_TP_ADD_TC(tp, sendrecv_16k);
1164 ATF_TP_ADD_TC(tp, sendrecv_32k);
1165 ATF_TP_ADD_TC(tp, sendrecv_64k);
1166 ATF_TP_ADD_TC(tp, sendrecv_128k);
1167 ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1168 ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1169 ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1170 ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1171 ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1172 ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1173 ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1174 ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1175 ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1176 ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1178 /* Threaded I/O tests with blocking sockets */
1179 ATF_TP_ADD_TC(tp, pipe_8k_8k);
1180 ATF_TP_ADD_TC(tp, pipe_8k_128k);
1181 ATF_TP_ADD_TC(tp, pipe_128k_8k);
1182 ATF_TP_ADD_TC(tp, pipe_128k_128k);
1184 return atf_no_error();