Author: jilles
Date: Tue Aug 25 20:33:37 2009
New Revision: 196554
URL: http://svn.freebsd.org/changeset/base/196554

Log:
  Add some tests for poll(2)/shutdown(2) interaction.

Added:
  head/tools/regression/poll/sockpoll.c   (contents, props changed)
Modified:
  head/tools/regression/poll/Makefile

Modified: head/tools/regression/poll/Makefile
==============================================================================
--- head/tools/regression/poll/Makefile Tue Aug 25 20:21:16 2009        
(r196553)
+++ head/tools/regression/poll/Makefile Tue Aug 25 20:33:37 2009        
(r196554)
@@ -3,14 +3,15 @@
 # Nothing yet works with gmake for the path to the sources.
 .PATH: ..
 
-PROG=  pipepoll pipeselect
+PROG=  pipepoll pipeselect sockpoll
 CFLAGS+= -Werror -Wall
 
 all: ${PROG}
 pipepoll: pipepoll.c
 pipeselect: pipeselect.c
+sockpoll: sockpoll.c
 
-pipepoll pipeselect:
+pipepoll pipeselect sockpoll:
        ${CC} ${CFLAGS} ${LDFLAGS} -o $@ $...@.c
 
 test: all

Added: head/tools/regression/poll/sockpoll.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/tools/regression/poll/sockpoll.c       Tue Aug 25 20:33:37 2009        
(r196554)
@@ -0,0 +1,202 @@
+/* $FreeBSD$ */
+
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static const char *
+decode_events(int events)
+{
+       char *ncresult;
+       const char *result;
+
+       switch (events) {
+       case POLLIN:
+               result = "POLLIN";
+               break;
+       case POLLOUT:
+               result = "POLLOUT";
+               break;
+       case POLLIN | POLLOUT:
+               result = "POLLIN | POLLOUT";
+               break;
+       case POLLHUP:
+               result = "POLLHUP";
+               break;
+       case POLLIN | POLLHUP:
+               result = "POLLIN | POLLHUP";
+               break;
+       case POLLOUT | POLLHUP:
+               result = "POLLOUT | POLLHUP";
+               break;
+       case POLLIN | POLLOUT | POLLHUP:
+               result = "POLLIN | POLLOUT | POLLHUP";
+               break;
+       default:
+               asprintf(&ncresult, "%#x", events);
+               result = ncresult;
+               break;
+       }
+       return (result);
+}
+
+static void
+report(int num, const char *state, int expected, int got)
+{
+       if (expected == got)
+               printf("ok %-2d    ", num);
+       else
+               printf("not ok %-2d", num);
+       printf(" state %s: expected %s; got %s\n",
+           state, decode_events(expected), decode_events(got));
+       fflush(stdout);
+}
+
+static int
+set_nonblocking(int sck)
+{
+       int flags;
+
+       flags = fcntl(sck, F_GETFL, 0);
+       flags |= O_NONBLOCK;
+
+       if (fcntl(sck, F_SETFL, flags))
+               return -1;
+
+       return 0;
+}
+
+static char largeblock[1048576]; /* should be more than AF_UNIX sockbuf size */
+static int fd[2];
+static struct pollfd pfd0;
+static struct pollfd pfd1;
+
+void
+setup(void)
+{
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0)
+               err(1, "socketpair");
+       if (set_nonblocking(fd[0]) == -1)
+               err(1, "fcntl");
+       if (set_nonblocking(fd[1]) == -1)
+               err(1, "fcntl");
+       pfd0.fd = fd[0];
+       pfd0.events = POLLIN | POLLOUT;
+       pfd1.fd = fd[1];
+       pfd1.events = POLLIN | POLLOUT;
+}
+
+int
+main(void)
+{
+       int num;
+
+       num = 1;
+       printf("1..18\n");
+       fflush(stdout);
+
+       /* Large write with close */
+       setup();
+       if (poll(&pfd0, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "initial 0", POLLOUT, pfd0.revents);
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "initial 1", POLLOUT, pfd1.revents);
+       if (write(fd[0], largeblock, sizeof(largeblock)) == -1)
+               err(1, "write");
+       if (poll(&pfd0, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "after large write", 0, pfd0.revents);
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "other side after large write", POLLIN | POLLOUT, 
pfd1.revents);
+       close(fd[0]);
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "other side after close", POLLIN | POLLHUP, pfd1.revents);
+       if (read(fd[1], largeblock, sizeof(largeblock)) == -1)
+               err(1, "read");
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "other side after reading input", POLLHUP, pfd1.revents);
+       close(fd[1]);
+
+       /* With shutdown(SHUT_WR) */
+       setup();
+       if (shutdown(fd[0], SHUT_WR) == -1)
+               err(1, "shutdown");
+       if (poll(&pfd0, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "after shutdown(SHUT_WR)", POLLOUT, pfd0.revents);
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, 
pfd1.revents);
+       switch (read(fd[1], largeblock, sizeof(largeblock))) {
+               case 0:
+                       break;
+               case -1:
+                       err(1, "read after other side shutdown");
+                       break;
+               default:
+                       errx(1, "kernel made up data that was never written");
+       }
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "other side after reading EOF", POLLIN | POLLOUT, 
pfd1.revents);
+       if (write(fd[1], largeblock, sizeof(largeblock)) == -1)
+               err(1, "write");
+       if (poll(&pfd0, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "after data from other side", POLLIN | POLLOUT, 
pfd0.revents);
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "after writing", POLLIN, pfd1.revents);
+       if (shutdown(fd[1], SHUT_WR) == -1)
+               err(1, "shutdown second");
+       if (poll(&pfd0, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "after second shutdown", POLLIN | POLLHUP, pfd0.revents);
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "after second shutdown", POLLHUP, pfd1.revents);
+       close(fd[0]);
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "after close", POLLHUP, pfd1.revents);
+       close(fd[1]);
+
+       /*
+        * With shutdown(SHUT_RD)
+        * Note that shutdown(SHUT_WR) is passed to the peer, but
+        * shutdown(SHUT_RD) is not.
+        */
+       setup();
+       if (shutdown(fd[0], SHUT_RD) == -1)
+               err(1, "shutdown");
+       if (poll(&pfd0, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "after shutdown(SHUT_RD)", POLLIN | POLLOUT, 
pfd0.revents);
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, 
pfd1.revents);
+       if (shutdown(fd[0], SHUT_WR) == -1)
+               err(1, "shutdown");
+       if (poll(&pfd0, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "after shutdown(SHUT_WR)", POLLHUP, pfd0.revents);
+       if (poll(&pfd1, 1, 0) == -1)
+               err(1, "poll");
+       report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, 
pfd1.revents);
+       close(fd[0]);
+       close(fd[1]);
+
+       return (0);
+}
_______________________________________________
svn-src-all@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"

Reply via email to