>Number:         185812
>Category:       kern
>Synopsis:       send(2) on a UNIX domain SEQPACKET socket returns EMSGSIZE 
>instead of EAGAIN
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jan 15 21:10:00 UTC 2014
>Closed-Date:
>Last-Modified:
>Originator:     Alan Somers
>Release:        CURRENT
>Organization:
Spectra Logic
>Environment:
FreeBSD alans-fbsd-head 11.0-CURRENT FreeBSD 11.0-CURRENT #22 r260496: Thu Jan  
9 16:39:42 MST 2014     
[email protected]:/vmpool/obj/usr/home/alans/freebsd/head/sys/GENERIC  
amd64
>Description:
If you overflow the buffer of a nonblocking unix domain seqpacket socket, 
send(2) should return EAGAIN.  Instead, it returns EMSGSIZE.
>How-To-Repeat:
The bug is reproduced by several testcases in the attached ATF test program.  
Most consise is unix_seqpacket:eagain_8k_8k
>Fix:
None known.  But a clue is offered by this comment at sys/kern/uipc_usrreq.c:987

                /*
                 * XXXRW: While fine for SOCK_STREAM, this conflates maximum
                 * datagram size and back-pressure for SOCK_SEQPACKET, which
                 * can lead to undesired return of EMSGSIZE on send instead
                 * of more desirable blocking.
                 */

Patch attached with submission follows:

Index: sys/kern/tests/Makefile
===================================================================
--- sys/kern/tests/Makefile     (revision 0)
+++ sys/kern/tests/Makefile     (working copy)
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+TESTSDIR=      ${TESTSBASE}/sys/kern
+
+ATF_TESTS_C=   unix_seqpacket
+
+.include <atf.test.mk>
Index: sys/kern/tests/unix_seqpacket.c
===================================================================
--- sys/kern/tests/unix_seqpacket.c     (revision 0)
+++ sys/kern/tests/unix_seqpacket.c     (working copy)
@@ -0,0 +1,649 @@
+/*-
+ * Copyright (c) 2014 Spectra Logic Corporation. All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <stdio.h>
+
+#include <atf-c.h>
+
+/*
+ * Helper functions
+ */
+
+#define MIN(x, y)      ((x) < (y) ? (x) : (y))
+#define MAX(x, y)      ((x) > (y) ? (x) : (y))
+
+void
+do_socketpair(int *sv)
+{
+       int s;
+       
+       s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
+       ATF_REQUIRE_EQ(0, s);
+       ATF_REQUIRE(sv[0] >= 0);
+       ATF_REQUIRE(sv[1] >= 0);
+       ATF_REQUIRE(sv[0] != sv[1]);
+}
+
+void
+do_socketpair_nonblocking(int *sv)
+{
+       int s;
+       
+       s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
+       ATF_REQUIRE_EQ(0, s);
+       ATF_REQUIRE(sv[0] >= 0);
+       ATF_REQUIRE(sv[1] >= 0);
+       ATF_REQUIRE(sv[0] != sv[1]);
+       ATF_REQUIRE(-1 != fcntl(sv[0], F_SETFL, O_NONBLOCK));
+       ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK));
+}
+
+/*
+ * Parameterized test function bodies
+ */
+void
+test_eagain(size_t sndbufsize, size_t rcvbufsize)
+{
+       int i;
+       int sv[2];
+       const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
+       const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
+       char sndbuf[pktsize];
+       char recv_buf[pktsize];
+       ssize_t ssize, rsize;
+
+       /* setup the socket pair */
+       do_socketpair(sv);
+       /* Setup the buffers */
+       ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
+           sizeof(sndbufsize)));
+       ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
+           sizeof(rcvbufsize)));
+
+       bzero(sndbuf, pktsize);
+       /* Send data until we get EAGAIN */
+       for(i=0; i < totalsize / pktsize; i++) {
+               ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
+               if (ssize == -1) {
+                       if (errno == EAGAIN)
+                               atf_tc_pass();
+                       else {
+                               perror("send");
+                               atf_tc_fail("send returned < 0 but not EAGAIN");
+                       }
+               }
+       }
+       atf_tc_fail("Never got EAGAIN");
+}
+
+void
+test_nonblocking_symmetric_buffers(size_t bufsize) {
+       int s;
+       int sv[2];
+       const size_t pktsize = bufsize / 2;
+       char sndbuf[pktsize];
+       char recv_buf[pktsize];
+       ssize_t ssize, rsize;
+
+       /* setup the socket pair */
+       do_socketpair_nonblocking(sv);
+       /* Setup the buffers */
+       s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
+       ATF_REQUIRE_EQ(0, s);
+       s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
+       ATF_REQUIRE_EQ(0, s);
+
+       /* Fill the send buffer */
+       bzero(sndbuf, pktsize);
+
+       /* send and receive the packet */
+       ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
+       if (ssize < 0) {
+               perror("send");
+               atf_tc_fail("send returned < 0");
+       }
+       ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
+           pktsize, ssize);
+
+       rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
+       if (rsize < 0) {
+               perror("recv");
+               atf_tc_fail("recv returned < 0");
+       }
+       ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
+           pktsize, rsize);
+}
+
+void
+test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
+{
+       int s, num_sent, num_received;
+       int sv[2];
+       const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
+       int numpkts;
+       char sndbuf[pktsize];
+       char rcvbuf[pktsize];
+       char comparebuf[pktsize];
+       ssize_t ssize, rsize;
+       bool currently_sending = true;
+
+       /* setup the socket pair */
+       do_socketpair_nonblocking(sv);
+       /* Setup the buffers */
+       ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
+           sizeof(sndbufsize)));
+       ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
+           sizeof(rcvbufsize)));
+
+       /* Send a total amount of data comfortably greater than the buffers */
+       numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
+       for (num_sent=0, num_received=0;
+            num_sent < numpkts || num_received < numpkts; ) {
+               if (currently_sending && num_sent < numpkts) {
+                       /* The simulated sending process */
+                       /* fill the buffer */
+                       memset(sndbuf, num_sent, pktsize);
+                       ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
+                       if (ssize < 0) {
+                               /* 
+                                * XXX: This is bug-compatible with the kernel.
+                                * The kernel returns EMSGSIZE when it should
+                                * return EAGAIN
+                                */
+                               if (errno == EAGAIN || errno == EMSGSIZE)
+                                       currently_sending = false;
+                               else {
+                                       perror("send");
+                                       atf_tc_fail("send failed");
+                               }
+                       } else  {
+                               ATF_CHECK_EQ_MSG(pktsize, ssize,
+                                   "expected %zd=send(...) but got %zd",
+                                   pktsize, ssize);
+                               num_sent++;
+                       }
+               } else {
+                       /* The simulated receiving process */
+                       rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
+                       if (rsize < 0) {
+                               if (errno == EAGAIN) {
+                                       currently_sending = true;
+                                       ATF_REQUIRE_MSG(num_sent < numpkts,
+                                           "Packets were lost!");
+                               }
+                               else {
+                                       perror("recv");
+                                       atf_tc_fail("recv failed");
+                               }
+                       } else  {
+                               ATF_CHECK_EQ_MSG(pktsize, rsize,
+                                   "expected %zd=recv(...) but got %zd",
+                                   pktsize, rsize);
+                               memset(comparebuf, num_received, pktsize);
+                               ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
+                                                          pktsize), 
+                                   "Received data miscompare");
+                               num_received++;
+                       }
+               }
+       }
+}
+
+
+/*
+ * Test Cases
+ */
+
+/* Create a SEQPACKET socket */
+ATF_TC_WITHOUT_HEAD(create_socket);
+ATF_TC_BODY(create_socket, tc)
+{
+       int s;
+
+       s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
+       ATF_CHECK(s >= 0);
+}
+
+/* Create SEQPACKET sockets using socketpair(2) */
+ATF_TC_WITHOUT_HEAD(create_socketpair);
+ATF_TC_BODY(create_socketpair, tc)
+{
+       int sv[2];
+       int s;
+
+       s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
+       ATF_CHECK_EQ(0, s);
+       ATF_CHECK(sv[0] >= 0);
+       ATF_CHECK(sv[1] >= 0);
+       ATF_CHECK(sv[0] != sv[1]);
+}
+
+/* Call listen(2) without first calling bind(2).  It should fail */
+ATF_TC_WITHOUT_HEAD(listen_unbound);
+ATF_TC_BODY(listen_unbound, tc)
+{
+       int s, r;
+
+       s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
+       ATF_REQUIRE(s > 0);
+       r = listen(s, -1);
+       /* expect listen to fail since we haven't called bind(2) */
+       ATF_CHECK(r != 0);
+}
+
+/* Bind the socket to a file */
+ATF_TC_WITHOUT_HEAD(bind);
+ATF_TC_BODY(bind, tc)
+{
+       struct sockaddr_un sun;
+       /* ATF's isolation mechanisms will guarantee uniqueness of this file */
+       const char *path = "sock";
+       int s, r;
+
+       s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
+       ATF_REQUIRE(s >= 0);
+
+       bzero(&sun, sizeof(sun));
+       sun.sun_family = AF_LOCAL;
+       sun.sun_len = sizeof(sun);
+       strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
+       r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
+       ATF_CHECK_EQ(0, r);
+}
+
+/* listen(2) a socket that is already bound(2) should succeed */
+ATF_TC_WITHOUT_HEAD(listen_bound);
+ATF_TC_BODY(listen_bound, tc)
+{
+       struct sockaddr_un sun;
+       /* ATF's isolation mechanisms will guarantee uniqueness of this file */
+       const char *path = "sock";
+       int s, r, l;
+
+       s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
+       ATF_REQUIRE(s >= 0);
+
+       bzero(&sun, sizeof(sun));
+       sun.sun_family = AF_LOCAL;
+       sun.sun_len = sizeof(sun);
+       strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
+       r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
+       l = listen(s, -1);
+       ATF_CHECK_EQ(0, r);
+       ATF_CHECK_EQ(0, l);
+}
+
+/* Set O_NONBLOCK on the socket */
+ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
+ATF_TC_BODY(fcntl_nonblock, tc)
+{
+       int s;
+
+       s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
+       ATF_REQUIRE(s >= 0);
+       if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
+               perror("fcntl");
+               atf_tc_fail("fcntl failed");
+       }
+}
+
+/* Resize the send and receive buffers */
+ATF_TC_WITHOUT_HEAD(resize_buffers);
+ATF_TC_BODY(resize_buffers, tc)
+{
+       int s;
+       int sndbuf = 8192;
+       int rcvbuf = 8192;
+
+       s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
+       ATF_REQUIRE(s >= 0);
+       if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
+               perror("setsockopt");
+               atf_tc_fail("setsockopt(SO_SNDBUF) failed");
+       }
+       if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &sndbuf, sizeof(sndbuf)) != 0){
+               perror("setsockopt");
+               atf_tc_fail("setsockopt(SO_RCVBUF) failed");
+       }
+}
+
+/* send(2) and recv(2) a single short record */
+ATF_TC_WITHOUT_HEAD(send_recv);
+ATF_TC_BODY(send_recv, tc)
+{
+       int s;
+       int sv[2];
+       const int bufsize = 64;
+       const char *data = "data";
+       char recv_buf[bufsize];
+       size_t datalen;
+       ssize_t ssize, rsize;
+
+       /* setup the socket pair */
+       do_socketpair(sv);
+
+       /* send and receive a small packet */
+       datalen = strlen(data) + 1;     /* +1 for the null */
+       ssize = send(sv[0], data, datalen, MSG_EOR);
+       if (ssize < 0) {
+               perror("send");
+               atf_tc_fail("send returned < 0");
+       }
+       ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
+           datalen, ssize);
+
+       rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
+       ATF_CHECK_EQ(datalen, rsize);
+}
+
+/* nonblocking send(2) and recv(2) a single short record */
+ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
+ATF_TC_BODY(send_recv_nonblocking, tc)
+{
+       int s;
+       int sv[2];
+       const int bufsize = 64;
+       const char *data = "data";
+       char recv_buf[bufsize];
+       size_t datalen;
+       ssize_t ssize, rsize;
+
+       /* setup the socket pair */
+       do_socketpair_nonblocking(sv);
+
+       /* Verify that there is nothing to receive */
+       rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
+       ATF_CHECK_EQ(EAGAIN, errno);
+       ATF_CHECK_EQ(-1, rsize);
+
+       /* send and receive a small packet */
+       datalen = strlen(data) + 1;     /* +1 for the null */
+       ssize = send(sv[0], data, datalen, MSG_EOR);
+       if (ssize < 0) {
+               perror("send");
+               atf_tc_fail("send returned < 0");
+       }
+       ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
+           datalen, ssize);
+
+       rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
+       ATF_CHECK_EQ(datalen, rsize);
+}
+
+/* 
+ * We should get EMSGSIZE if we try to send a message larger than the socket
+ * buffer, with blocking sockets
+ */
+ATF_TC_WITHOUT_HEAD(emsgsize);
+ATF_TC_BODY(emsgsize, tc)
+{
+       int s;
+       int sv[2];
+       const size_t sndbufsize = 8192;
+       const size_t rcvbufsize = 8192;
+       const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
+       char sndbuf[pktsize];
+       char recv_buf[pktsize];
+       ssize_t ssize, rsize;
+
+       /* setup the socket pair */
+       do_socketpair(sv);
+       /* Setup the buffers */
+       ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
+           sizeof(sndbufsize)));
+       ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
+           sizeof(rcvbufsize)));
+
+       ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
+       ATF_CHECK_EQ(EMSGSIZE, errno);
+       ATF_CHECK_EQ(-1, ssize);
+}
+
+/* 
+ * We should get EMSGSIZE if we try to send a message larger than the socket
+ * buffer, with nonblocking sockets
+ */
+ATF_TC_WITHOUT_HEAD(emsgsize_nonblocking);
+ATF_TC_BODY(emsgsize_nonblocking, tc)
+{
+       int s;
+       int sv[2];
+       const size_t sndbufsize = 8192;
+       const size_t rcvbufsize = 8192;
+       const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
+       char sndbuf[pktsize];
+       char recv_buf[pktsize];
+       ssize_t ssize, rsize;
+
+       /* setup the socket pair */
+       do_socketpair_nonblocking(sv);
+       /* Setup the buffers */
+       ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
+           sizeof(sndbufsize)));
+       ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
+           sizeof(rcvbufsize)));
+
+       ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
+       ATF_CHECK_EQ(EMSGSIZE, errno);
+       ATF_CHECK_EQ(-1, ssize);
+}
+
+
+/* 
+ * We should get EAGAIN if we try to send a message larger than the socket
+ * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
+ */
+ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
+ATF_TC_BODY(eagain_8k_8k, tc)
+{
+       test_eagain(8192, 8192);
+}
+ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
+ATF_TC_BODY(eagain_8k_128k, tc)
+{
+       test_eagain(8192, 131072);
+}
+ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
+ATF_TC_BODY(eagain_128k_8k, tc)
+{
+       test_eagain(131072, 8192);
+}
+ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
+ATF_TC_BODY(eagain_128k_128k, tc)
+{
+       test_eagain(131072, 131072);
+}
+
+
+/* 
+ * nonblocking send(2) and recv(2) of several records, which should 
collectively
+ * fill up the send buffer but not the receive buffer
+ */
+ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
+ATF_TC_BODY(rcvbuf_oversized, tc)
+{
+       int s, i, j;
+       int sv[2];
+       const size_t sndbufsize = 8192;
+       const size_t rcvbufsize = 131072;
+       const size_t geom_mean_bufsize = 32768;
+       const int pktsize = 1024;
+       char sndbuf[pktsize];
+       char recv_buf[pktsize];
+       size_t datalen;
+       ssize_t ssize, rsize;
+
+       /* setup the socket pair */
+       do_socketpair_nonblocking(sv);
+
+       /* 
+        * Send and receive packets that are collectively greater than the send
+        * buffer, but less than the receive buffer
+        */
+       for (i=0; i < geom_mean_bufsize / pktsize; i++) {
+               /* Fill the buffer */
+               memset(sndbuf, i, pktsize);
+
+               /* send the packet */
+               ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
+               if (ssize < 0) {
+                       perror("send");
+                       atf_tc_fail("send returned < 0");
+               }
+               ATF_CHECK_EQ_MSG(pktsize, ssize,
+                   "expected %zd=send(...) but got %zd", pktsize, ssize);
+
+               /* Receive it */
+
+               rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
+               if (rsize < 0) {
+                       perror("recv");
+                       atf_tc_fail("recv returned < 0");
+               }
+               ATF_CHECK_EQ_MSG(pktsize, rsize,
+                   "expected %zd=send(...) but got %zd", pktsize, rsize);
+
+               /* Verify the contents */
+               ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize), 
+                   "Received data miscompare");
+       }
+
+       /* Trying to receive again should return EAGAIN */
+       rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
+       ATF_CHECK_EQ(EAGAIN, errno);
+       ATF_CHECK_EQ(-1, rsize);
+}
+
+/* 
+ * Simulate the behavior of a blocking pipe.  The sender will send until his
+ * buffer fills up, then we'll simulate a scheduler switch that will allow the
+ * receiver to read until his buffer empties.  Repeat the process until the
+ * transfer is complete.
+ * Repeat the test with multiple send and receive buffer sizes
+ */
+ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
+ATF_TC_BODY(pipe_simulator_8k_8k, tc)
+{
+       test_pipe_simulator(8192, 8192);
+}
+
+ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
+ATF_TC_BODY(pipe_simulator_8k_128k, tc)
+{
+       test_pipe_simulator(8192, 131072);
+}
+
+ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
+ATF_TC_BODY(pipe_simulator_128k_8k, tc)
+{
+       test_pipe_simulator(131072, 8192);
+}
+
+ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
+ATF_TC_BODY(pipe_simulator_128k_128k, tc)
+{
+       test_pipe_simulator(131072, 131072);
+}
+
+/* Test nonblocking I/O with 8K buffers */
+ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
+ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
+{
+       test_nonblocking_symmetric_buffers(8 * 1024);
+}
+
+/* Test nonblocking I/O with 16K buffers */
+ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
+ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
+{
+       test_nonblocking_symmetric_buffers(16 * 1024);
+}
+
+/* Test nonblocking I/O with 32K buffers */
+ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
+ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
+{
+       test_nonblocking_symmetric_buffers(32 * 1024);
+}
+
+/* Test nonblocking I/O with 64K buffers */
+ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
+ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
+{
+       test_nonblocking_symmetric_buffers(64 * 1024);
+}
+
+/* Test nonblocking I/O with 128K buffers */
+ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
+ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
+{
+       test_nonblocking_symmetric_buffers(128 * 1024);
+}
+
+
+/*
+ * Main.
+ */
+
+ATF_TP_ADD_TCS(tp)
+{
+       /* Basic creation and connection tests */
+       ATF_TP_ADD_TC(tp, create_socket);
+       ATF_TP_ADD_TC(tp, create_socketpair);
+       ATF_TP_ADD_TC(tp, listen_unbound);
+       ATF_TP_ADD_TC(tp, bind);
+       ATF_TP_ADD_TC(tp, listen_bound);
+       ATF_TP_ADD_TC(tp, fcntl_nonblock);
+       ATF_TP_ADD_TC(tp, resize_buffers);
+
+       /* Unthreaded I/O tests */
+       ATF_TP_ADD_TC(tp, send_recv);
+       ATF_TP_ADD_TC(tp, send_recv_nonblocking);
+       ATF_TP_ADD_TC(tp, emsgsize);
+       ATF_TP_ADD_TC(tp, emsgsize_nonblocking);
+       ATF_TP_ADD_TC(tp, eagain_8k_8k);
+       ATF_TP_ADD_TC(tp, eagain_8k_128k);
+       ATF_TP_ADD_TC(tp, eagain_128k_8k);
+       ATF_TP_ADD_TC(tp, eagain_128k_128k);
+       ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
+       ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
+       ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
+       ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
+       ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
+       ATF_TP_ADD_TC(tp, rcvbuf_oversized);
+       ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
+       ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
+       ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
+       ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
+
+       return atf_no_error();
+}
Index: sys/tests/Makefile
===================================================================
--- sys/tests/Makefile  (revision 0)
+++ sys/tests/Makefile  (working copy)
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+TESTSDIR=      ${TESTSBASE}/sys
+
+.PATH:         ${.CURDIR:H:H}/tests
+KYUAFILE=      yes
+
+.include <bsd.test.mk>
Index: etc/mtree/BSD.tests.dist
===================================================================
--- etc/mtree/BSD.tests.dist    (revision 260696)
+++ etc/mtree/BSD.tests.dist    (working copy)
@@ -78,6 +78,10 @@
                 ..
             ..
         ..
+       sys
+           kern
+           ..
+       ..
         usr.bin
             atf
                 atf-sh


>Release-Note:
>Audit-Trail:
>Unformatted:
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "[email protected]"

Reply via email to