The following reply was made to PR kern/185813; it has been noted by GNATS.

From: dfil...@freebsd.org (dfilter service)
To: bug-follo...@freebsd.org
Cc:  
Subject: Re: kern/185813: commit references a PR
Date: Thu, 23 Jan 2014 17:26:41 +0000 (UTC)

 Author: asomers
 Date: Thu Jan 23 17:26:28 2014
 New Revision: 261081
 URL: http://svnweb.freebsd.org/changeset/base/261081
 
 Log:
   Replace the old unix_seqpacket and unix_seqpacket_exercise tests, which
   were a little broken and not automatable, with unix_seqpacket_test.
   It's coverage is a superset of the old tests and it uses ATF.  It
   includes test cases for bugs kern/185813 and kern/185812.
   
   PR:          kern/185812
   PR:          kern/185813
   Sponsored by:        Spectra Logic
   MFC after:   2 weeks
 
 Added:
   head/tests/sys/
   head/tests/sys/Makefile   (contents, props changed)
   head/tests/sys/kern/
   head/tests/sys/kern/Makefile   (contents, props changed)
   head/tests/sys/kern/unix_seqpacket_test.c   (contents, props changed)
 Deleted:
   head/tools/regression/sockets/unix_seqpacket/
   head/tools/regression/sockets/unix_seqpacket_exercise/
 Modified:
   head/Makefile.inc1
   head/etc/mtree/BSD.tests.dist
 
 Modified: head/Makefile.inc1
 ==============================================================================
 --- head/Makefile.inc1 Thu Jan 23 17:24:26 2014        (r261080)
 +++ head/Makefile.inc1 Thu Jan 23 17:26:28 2014        (r261081)
 @@ -417,7 +417,7 @@ LIB32WMAKEFLAGS+=  \
                -DNO_LINT
  
  LIB32WMAKE=   ${LIB32WMAKEENV} ${MAKE} ${LIB32WMAKEFLAGS} \
 -              -DWITHOUT_MAN -DWITHOUT_INFO -DWITHOUT_HTML
 +              -DWITHOUT_MAN -DWITHOUT_INFO -DWITHOUT_HTML -DNO_TESTS
  LIB32IMAKE=   ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*:N_LDSCRIPTROOT=*} -DNO_INCS \
                ${IMAKE_INSTALL}
  .endif
 
 Modified: head/etc/mtree/BSD.tests.dist
 ==============================================================================
 --- head/etc/mtree/BSD.tests.dist      Thu Jan 23 17:24:26 2014        
(r261080)
 +++ head/etc/mtree/BSD.tests.dist      Thu Jan 23 17:26:28 2014        
(r261081)
 @@ -78,6 +78,10 @@
                  ..
              ..
          ..
 +        sys
 +            kern
 +            ..
 +        ..
          usr.bin
              atf
                  atf-sh
 
 Added: head/tests/sys/Makefile
 ==============================================================================
 --- /dev/null  00:00:00 1970   (empty, because file is newly added)
 +++ head/tests/sys/Makefile    Thu Jan 23 17:26:28 2014        (r261081)
 @@ -0,0 +1,13 @@
 +# $FreeBSD$
 +
 +.include <bsd.own.mk>
 +
 +TESTSDIR= ${TESTSBASE}/sys
 +
 +KYUAFILE= yes
 +
 +CLEANFILES+= Kyuafile
 +Kyuafile: ${.CURDIR}/../Kyuafile
 +      cp -f ${.CURDIR}/../Kyuafile .
 +
 +.include <bsd.test.mk>
 
 Added: head/tests/sys/kern/Makefile
 ==============================================================================
 --- /dev/null  00:00:00 1970   (empty, because file is newly added)
 +++ head/tests/sys/kern/Makefile       Thu Jan 23 17:26:28 2014        
(r261081)
 @@ -0,0 +1,10 @@
 +# $FreeBSD$
 +
 +TESTSDIR=     ${TESTSBASE}/sys/kern
 +
 +ATF_TESTS_C=  unix_seqpacket_test
 +TEST_METADATA.unix_seqpacket_test+=   timeout="15"
 +
 +LDADD+=               -lpthread
 +
 +.include <atf.test.mk>
 
 Added: head/tests/sys/kern/unix_seqpacket_test.c
 ==============================================================================
 --- /dev/null  00:00:00 1970   (empty, because file is newly added)
 +++ head/tests/sys/kern/unix_seqpacket_test.c  Thu Jan 23 17:26:28 2014        
(r261081)
 @@ -0,0 +1,1117 @@
 +/*-
 + * 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 <pthread.h>
 +#include <signal.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));
 +}
 +
 +/* 
 + * Returns a pair of sockets made the hard way: bind, listen, connect & accept
 + * @return    const char* The path to the socket
 + */
 +const char*
 +mk_pair_of_sockets(int *sv)
 +{
 +      struct sockaddr_un sun;
 +      /* ATF's isolation mechanisms will guarantee uniqueness of this file */
 +      const char *path = "sock";
 +      int s, err, s2, s1;
 +
 +      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));
 +      err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
 +      err = listen(s, -1);
 +      ATF_CHECK_EQ(0, err);
 +      ATF_CHECK_EQ(0, err);
 +
 +      /* Create the other socket */
 +      s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
 +      ATF_REQUIRE(s2 >= 0);
 +      err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
 +      if (err != 0) {
 +              perror("connect");
 +              atf_tc_fail("connect(2) failed");
 +      }
 +      
 +      /* Accept it */
 +      s1 = accept(s, NULL, NULL);
 +      if (s1 == -1) {
 +              perror("accept");
 +              atf_tc_fail("accept(2) failed");
 +      }
 +
 +      sv[0] = s1;
 +      sv[1] = s2;
 +      return (path);
 +}
 +
 +static volatile sig_atomic_t got_sigpipe = 0;
 +static void
 +shutdown_send_sigpipe_handler(int x)
 +{
 +      got_sigpipe = 1;
 +}
 +
 +/*
 + * 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_sendrecv_symmetric_buffers(size_t bufsize, int blocking) {
 +      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 */
 +      if (blocking)
 +              do_socketpair(sv);
 +      else
 +              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++;
 +                      }
 +              }
 +      }
 +}
 +
 +typedef struct {
 +      ssize_t pktsize;
 +      int     numpkts;
 +      int     so;
 +} test_pipe_thread_data_t;
 +
 +static void*
 +test_pipe_writer(void* args)
 +{
 +      test_pipe_thread_data_t* td = args;
 +      char sndbuf[td->pktsize];
 +      ssize_t ssize;
 +      int i;
 +
 +      for(i=0; i < td->numpkts; i++) {
 +                      memset(sndbuf, i, td->pktsize);
 +                      ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
 +                      if (ssize < 0) {
 +                              perror("send");
 +                              atf_tc_fail("send returned < 0");
 +                      }
 +                      ATF_CHECK_EQ_MSG(td->pktsize, ssize,
 +                                       "expected %zd=send(...) but got %zd",
 +                                        td->pktsize, ssize);
 +      }
 +      return (0);
 +}
 +
 +static void*
 +test_pipe_reader(void* args)
 +{
 +      test_pipe_thread_data_t* td = args;
 +      char rcvbuf[td->pktsize];
 +      char comparebuf[td->pktsize];
 +      ssize_t rsize;
 +      int i, d;
 +
 +      for(i=0; i < td->numpkts; i++) {
 +              memset(comparebuf, i, td->pktsize);
 +              rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
 +              if (rsize < 0) {
 +                      perror("recv");
 +                      atf_tc_fail("recv returned < 0");
 +              }
 +              ATF_CHECK_EQ_MSG(td->pktsize, rsize,
 +                               "expected %zd=send(...) but got %zd",
 +                               td->pktsize, rsize);
 +              d = memcmp(comparebuf, rcvbuf, td->pktsize);
 +              ATF_CHECK_EQ_MSG(0, d, 
 +                               "Received data miscompare on packet %d", i);
 +      }
 +      return (0);
 +}
 +
 +
 +void
 +test_pipe(size_t sndbufsize, size_t rcvbufsize)
 +{
 +      test_pipe_thread_data_t writer_data, reader_data;
 +      pthread_t writer, reader;
 +      int num_sent, num_received;
 +      int sv[2];
 +      const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
 +      int numpkts;
 +
 +      /* 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)));
 +
 +      /* Send a total amount of data comfortably greater than the buffers */
 +      numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
 +
 +      /* Start the child threads */
 +      writer_data.pktsize = pktsize;
 +      writer_data.numpkts = numpkts;
 +      writer_data.so = sv[0];
 +      reader_data.pktsize = pktsize;
 +      reader_data.numpkts = numpkts;
 +      reader_data.so = sv[1];
 +      ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
 +                                       (void*)&writer_data));
 +      ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
 +                                       (void*)&reader_data));
 +
 +      /* Join the children */
 +      ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
 +      ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
 +}
 +
 +
 +/*
 + * 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);
 +}
 +
 +/* connect(2) can make a connection */
 +ATF_TC_WITHOUT_HEAD(connect);
 +ATF_TC_BODY(connect, tc)
 +{
 +      struct sockaddr_un sun;
 +      /* ATF's isolation mechanisms will guarantee uniqueness of this file */
 +      const char *path = "sock";
 +      int s, r, err, l, s2;
 +
 +      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);
 +
 +      /* Create the other socket */
 +      s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
 +      ATF_REQUIRE(s2 >= 0);
 +      err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
 +      if (err != 0) {
 +              perror("connect");
 +              atf_tc_fail("connect(2) failed");
 +      }
 +}
 +
 +/* accept(2) can receive a connection */
 +ATF_TC_WITHOUT_HEAD(accept);
 +ATF_TC_BODY(accept, tc)
 +{
 +      int sv[2];
 +
 +      mk_pair_of_sockets(sv);
 +}
 +
 +
 +/* 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 = 12345;
 +      int rcvbuf = 23456;
 +      int xs, xr;
 +      socklen_t sl = sizeof(xs);
 +
 +      s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
 +      ATF_REQUIRE(s >= 0);
 +
 +      printf("                       Socket Buffer Sizes\n");
 +      printf("                              | SNDBUF  | RCVBUF  |\n");
 +      ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
 +      printf("Default                       | %7d | %7d |\n", xs, xr);
 +
 +      if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
 +              perror("setsockopt");
 +              atf_tc_fail("setsockopt(SO_SNDBUF) failed");
 +      }
 +      ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
 +      printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
 +      
 +      if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
 +              perror("setsockopt");
 +              atf_tc_fail("setsockopt(SO_RCVBUF) failed");
 +      }
 +      ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
 +      printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
 +}
 +
 +/*
 + * Resize the send and receive buffers of a connected socketpair
 + * Print some useful debugging info too
 + */
 +ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
 +ATF_TC_BODY(resize_connected_buffers, tc)
 +{
 +      int sv[2];
 +      int sndbuf = 12345;
 +      int rcvbuf = 23456;
 +      int err;
 +      int ls, lr, rs, rr;
 +      socklen_t sl = sizeof(ls);
 +
 +      /* setup the socket pair */
 +      do_socketpair(sv);
 +
 +      printf("                       Socket Buffer Sizes\n");
 +      printf("                              | Left Socket       | Right 
Socket      |\n");
 +      printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | 
RCVBUF  |\n");
 +      ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
 +      printf("Default                       | %7d | %7d | %7d | %7d |\n",
 +          ls, lr, rs, rr);
 +
 +      /* Update one side's send buffer */
 +      err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
 +      if (err != 0){
 +              perror("setsockopt");
 +              atf_tc_fail("setsockopt(SO_SNDBUF) failed");
 +      }
 +
 +      ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
 +      printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
 +          ls, lr, rs, rr);
 +
 +      /* Update the same side's receive buffer */
 +      err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
 +      if (err != 0){
 +              perror("setsockopt");
 +              atf_tc_fail("setsockopt(SO_RCVBUF) failed");
 +      }
 +
 +      ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
 +      ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
 +      printf("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
 +          ls, lr, rs, rr);
 +}
 +
 +
 +/* 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);
 +}
 +
 +/* sendto(2) and recvfrom(2) a single short record
 + * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 
2004
 + * Edition, sendto(2) is exactly the same as send(2) on a connection-mode 
socket
 + *
 + * According to the same spec, not all protocols are required to provide the
 + * source addres in recvfrom(2).
 + */
 +ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
 +ATF_TC_BODY(sendto_recvfrom, tc)
 +{
 +      const char* path;
 +      struct sockaddr_storage from;
 +      int s;
 +      int sv[2];
 +      const int bufsize = 64;
 +      const char *data = "data";
 +      char recv_buf[bufsize];
 +      size_t datalen;
 +      ssize_t ssize, rsize;
 +      socklen_t fromlen;
 +
 +      /* setup the socket pair */
 +      path = mk_pair_of_sockets(sv);
 +
 +      /* send and receive a small packet */
 +      datalen = strlen(data) + 1;     /* +1 for the null */
 +      ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
 +      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);
 +
 +      fromlen = sizeof(from);
 +      rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
 +          (struct sockaddr*)&from, &fromlen);
 +      if (ssize < 0) {
 +              perror("recvfrom");
 +              atf_tc_fail("recvfrom returned < 0");
 +      }
 +      ATF_CHECK_EQ(datalen, rsize);
 +
 +      /* 
 +       * FreeBSD does not currently provide the source address for SEQ_PACKET
 +       * AF_UNIX sockets, and POSIX does not require it, so these two checks
 +       * are disabled.  If FreeBSD gains that feature in the future, then
 +       * these checks may be reenabled
 +       */
 +      /* ATF_CHECK_EQ(PF_LOCAL, from.ss_family); */
 +      /* ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); */
 +}
 +
 +/* 
 + * send(2) and recv(2) a single short record with sockets created the
 + * traditional way, involving bind, listen, connect, and accept
 + */
 +ATF_TC_WITHOUT_HEAD(send_recv_with_connect);
 +ATF_TC_BODY(send_recv_with_connect, tc)
 +{
 +      const char* path;
 +      int sv[2];
 +      const int bufsize = 64;
 +      const char *data = "data";
 +      char recv_buf[bufsize];
 +      size_t datalen;
 +      ssize_t ssize, rsize;
 +
 +      mk_pair_of_sockets(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);
 +}
 +
 +/* send(2) should fail on a shutdown socket */
 +ATF_TC_WITHOUT_HEAD(shutdown_send);
 +ATF_TC_BODY(shutdown_send, tc)
 +{
 +      int s;
 +      const char *data = "data";
 +      ssize_t ssize;
 +
 +      s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
 +      ATF_CHECK(s >= 0);
 +      ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
 +      /* USE MSG_NOSIGNAL so we don't get SIGPIPE */
 +      ssize = send(s, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
 +      ATF_CHECK_EQ(EPIPE, errno);
 +      ATF_CHECK_EQ(-1, ssize);
 +}
 +
 +/* send(2) should cause SIGPIPE on a shutdown socket */
 +ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
 +ATF_TC_BODY(shutdown_send_sigpipe, tc)
 +{
 +      int s;
 +      const char *data = "data";
 +      ssize_t ssize;
 +
 +      s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
 +      ATF_CHECK(s >= 0);
 +      ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
 +      ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
 +      ssize = send(s, data, sizeof(data), MSG_EOR);
 +      ATF_CHECK_EQ(1, got_sigpipe);
 +}
 +
 +/* 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)
 +{
 +      atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET 
socket returns EMSGSIZE instead of EAGAIN");
 +      test_eagain(8192, 8192);
 +}
 +ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
 +ATF_TC_BODY(eagain_8k_128k, tc)
 +{
 +      atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET 
socket returns EMSGSIZE instead of EAGAIN");
 +      test_eagain(8192, 131072);
 +}
 +ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
 +ATF_TC_BODY(eagain_128k_8k, tc)
 +{
 +      atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET 
socket returns EMSGSIZE instead of EAGAIN");
 +      test_eagain(131072, 8192);
 +}
 +ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
 +ATF_TC_BODY(eagain_128k_128k, tc)
 +{
 +      atf_tc_expect_fail("PR kern/185812 send(2) on a UNIX domain SEQPACKET 
socket returns EMSGSIZE instead of EAGAIN");
 +      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);
 +}
 +
 
 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
 _______________________________________________
 svn-src-...@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"
 
_______________________________________________
freebsd-bugs@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bugs
To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"

Reply via email to