summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2015-11-23 09:26:53 +0000
committerngie <ngie@FreeBSD.org>2015-11-23 09:26:53 +0000
commitd84acbd961805440ae74bea28ca28cbbb121b871 (patch)
tree0d3602d114daa2514ee31e0404b5f954cbdf3b69 /tests
parent3cb0c7ddff092a0a02d788dde117fd0769018c4a (diff)
downloadFreeBSD-src-d84acbd961805440ae74bea28ca28cbbb121b871.zip
FreeBSD-src-d84acbd961805440ae74bea28ca28cbbb121b871.tar.gz
MFC r290914:
Integrate tools/regression/pipe in to the FreeBSD test suite as tests/sys/kern/pipe - Fix style(9) bugs - Fix compiler warnings - Use `nitems(x)` instead of `sizeof(x) / sizeof(*x)` pattern The testcases will be converted over to ATF eventually, but for now will be integrated in as plain C tests Sponsored by: EMC / Isilon Storage Division
Diffstat (limited to 'tests')
-rw-r--r--tests/sys/kern/Makefile1
-rw-r--r--tests/sys/kern/pipe/Makefile16
-rw-r--r--tests/sys/kern/pipe/big_pipe_test.c88
-rw-r--r--tests/sys/kern/pipe/pipe_fstat_bug_test.c138
-rw-r--r--tests/sys/kern/pipe/pipe_ino_test.c65
-rw-r--r--tests/sys/kern/pipe/pipe_overcommit1_test.c52
-rw-r--r--tests/sys/kern/pipe/pipe_overcommit2_test.c83
-rw-r--r--tests/sys/kern/pipe/pipe_reverse2_test.c67
-rw-r--r--tests/sys/kern/pipe/pipe_reverse_test.c149
-rw-r--r--tests/sys/kern/pipe/pipe_wraparound_test.c140
10 files changed, 799 insertions, 0 deletions
diff --git a/tests/sys/kern/Makefile b/tests/sys/kern/Makefile
index 337ff73..5328b99 100644
--- a/tests/sys/kern/Makefile
+++ b/tests/sys/kern/Makefile
@@ -20,6 +20,7 @@ WARNS?= 5
TESTS_SUBDIRS+= acct
TESTS_SUBDIRS+= execve
+TESTS_SUBDIRS+= pipe
.include <netbsd-tests.test.mk>
diff --git a/tests/sys/kern/pipe/Makefile b/tests/sys/kern/pipe/Makefile
new file mode 100644
index 0000000..bcd2d07
--- /dev/null
+++ b/tests/sys/kern/pipe/Makefile
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+TESTSDIR= ${TESTSBASE}/sys/kern/pipe
+
+PLAIN_TESTS_C+= big_pipe_test
+PLAIN_TESTS_C+= pipe_fstat_bug_test
+PLAIN_TESTS_C+= pipe_ino_test
+PLAIN_TESTS_C+= pipe_overcommit1_test
+PLAIN_TESTS_C+= pipe_overcommit2_test
+PLAIN_TESTS_C+= pipe_reverse2_test
+PLAIN_TESTS_C+= pipe_reverse_test
+PLAIN_TESTS_C+= pipe_wraparound_test
+
+WARNS?= 6
+
+.include <bsd.test.mk>
diff --git a/tests/sys/kern/pipe/big_pipe_test.c b/tests/sys/kern/pipe/big_pipe_test.c
new file mode 100644
index 0000000..fa5687e
--- /dev/null
+++ b/tests/sys/kern/pipe/big_pipe_test.c
@@ -0,0 +1,88 @@
+#include <sys/select.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define BIG_PIPE_SIZE 64*1024 /* From sys/pipe.h */
+
+/*
+ * Test for the non-blocking big pipe bug (write(2) returning
+ * EAGAIN while select(2) returns the descriptor as ready for write).
+ *
+ * $FreeBSD$
+ */
+
+static void
+write_frame(int fd, char *buf, unsigned long buflen)
+{
+ fd_set wfd;
+ int i;
+
+ while (buflen) {
+ FD_ZERO(&wfd);
+ FD_SET(fd, &wfd);
+ i = select(fd+1, NULL, &wfd, NULL, NULL);
+ if (i < 0)
+ err(1, "select failed");
+ if (i != 1) {
+ errx(1, "select returned unexpected value %d\n", i);
+ exit(1);
+ }
+ i = write(fd, buf, buflen);
+ if (i < 0) {
+ if (errno != EAGAIN)
+ warn("write failed");
+ exit(1);
+ }
+ buf += i;
+ buflen -= i;
+ }
+}
+
+int
+main(void)
+{
+ /* any value over PIPE_SIZE should do */
+ char buf[BIG_PIPE_SIZE];
+ int i, flags, fd[2];
+
+ if (pipe(fd) < 0)
+ errx(1, "pipe failed");
+
+ flags = fcntl(fd[1], F_GETFL);
+ if (flags == -1 || fcntl(fd[1], F_SETFL, flags|O_NONBLOCK) == -1) {
+ printf("fcntl failed: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ switch (fork()) {
+ case -1:
+ err(1, "fork failed: %s\n", strerror(errno));
+ break;
+ case 0:
+ close(fd[1]);
+ for (;;) {
+ /* Any small size should do */
+ i = read(fd[0], buf, 256);
+ if (i == 0)
+ break;
+ if (i < 0)
+ err(1, "read");
+ }
+ exit(0);
+ default:
+ break;
+ }
+
+ close(fd[0]);
+ memset(buf, 0, sizeof buf);
+ for (i = 0; i < 1000; i++)
+ write_frame(fd[1], buf, sizeof buf);
+
+ printf("ok\n");
+ exit(0);
+}
diff --git a/tests/sys/kern/pipe/pipe_fstat_bug_test.c b/tests/sys/kern/pipe/pipe_fstat_bug_test.c
new file mode 100644
index 0000000..ae0b309
--- /dev/null
+++ b/tests/sys/kern/pipe/pipe_fstat_bug_test.c
@@ -0,0 +1,138 @@
+/*
+Copyright (C) 2004 Michael J. Silbersack. 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/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * $FreeBSD$
+ * The goal of this program is to see if fstat reports the correct
+ * data count for a pipe. Prior to revision 1.172 of sys_pipe.c,
+ * 0 would be returned once the pipe entered direct write mode.
+ *
+ * Linux (2.6) always returns zero, so it's not a valuable platform
+ * for comparison.
+ */
+
+int
+main(void)
+{
+ char buffer[32768], buffer2[32768], go[] = "go", go2[] = "go2";
+ int desc[2], ipc_coord[2];
+ ssize_t error;
+ int successes = 0;
+ struct stat status;
+ pid_t new_pid;
+
+ error = pipe(desc);
+ if (error == -1)
+ err(1, "Couldn't allocate data pipe");
+
+ error = pipe(ipc_coord);
+ if (error == -1)
+ err(1, "Couldn't allocate IPC coordination pipe");
+
+ new_pid = fork();
+ assert(new_pid != -1);
+
+ close(new_pid == 0 ? desc[0] : desc[1]);
+
+#define SYNC_R(i, _buf) do { \
+ int _error = errno; \
+ warnx("%d: waiting for synchronization", __LINE__); \
+ if (read(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
+ err(1, "failed to synchronize (%s)", (i == 0 ? "parent" : "child")); \
+ errno = _error; \
+ } while(0)
+
+#define SYNC_W(i, _buf) do { \
+ int _error = errno; \
+ warnx("%d: sending synchronization", __LINE__); \
+ if (write(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
+ err(1, "failed to synchronize (%s)", (i == 0 ? "child" : "parent")); \
+ errno = _error; \
+ } while(0)
+
+#define WRITE(s) do { \
+ ssize_t _size; \
+ if ((_size = write(desc[1], &buffer, s)) != s) \
+ warn("short write; wrote %zd, expected %d", _size, s); \
+ } while(0)
+
+ if (new_pid == 0) {
+
+ SYNC_R(0, go);
+ WRITE(145);
+ SYNC_W(0, go2);
+
+ SYNC_R(0, go);
+ WRITE(2048);
+ SYNC_W(0, go2);
+
+ SYNC_R(0, go);
+ WRITE(4096);
+ SYNC_W(0, go2);
+
+ SYNC_R(0, go);
+ WRITE(8191);
+ SYNC_W(0, go2);
+
+ SYNC_R(0, go);
+ SYNC_W(0, go2); /* XXX: why is this required? */
+ WRITE(8192);
+ SYNC_W(0, go2);
+
+ close(ipc_coord[0]);
+ close(ipc_coord[1]);
+
+ _exit(0);
+ }
+
+ while (successes < 5) {
+ SYNC_W(1, go);
+ SYNC_R(1, go2);
+ fstat(desc[0], &status);
+ error = read(desc[0], &buffer2, sizeof(buffer2));
+
+ if (status.st_size != error)
+ err(1, "FAILURE: stat size %jd read size %zd",
+ (intmax_t)status.st_size, error);
+ if (error > 0) {
+ printf("SUCCESS at stat size %jd read size %zd\n",
+ (intmax_t)status.st_size, error);
+ successes++;
+ }
+ }
+
+ exit(0);
+}
diff --git a/tests/sys/kern/pipe/pipe_ino_test.c b/tests/sys/kern/pipe/pipe_ino_test.c
new file mode 100644
index 0000000..94692aa
--- /dev/null
+++ b/tests/sys/kern/pipe/pipe_ino_test.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2011 Giovanni Trematerra <giovanni.trematerra@gmail.com>
+ * 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 THE 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 THE 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.
+ */
+
+/*
+ * $FreeBSD$
+ * Test conformance to stat(2) SUSv4 description:
+ * "For all other file types defined in this volume of POSIX.1-2008, the
+ * structure members st_mode, st_ino, st_dev, st_uid, st_gid, st_atim,
+ * st_ctim, and st_mtim shall have meaningful values ...".
+ * Check that st_dev and st_ino are meaningful.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+
+int
+main(void)
+{
+ int pipefd[2];
+ struct stat st1, st2;
+
+ if (pipe(pipefd) == -1)
+ err(1, "FAIL: pipe");
+
+ if (fstat(pipefd[0], &st1) == -1)
+ err(1, "FAIL: fstat st1");
+ if (fstat(pipefd[1], &st2) == -1)
+ err(1, "FAIL: fstat st2");
+ if (st1.st_dev != st2.st_dev || st1.st_dev == 0 || st2.st_dev == 0)
+ errx(1, "FAIL: wrong dev number %d %d", st1.st_dev, st2.st_dev);
+ if (st1.st_ino == st2.st_ino)
+ errx(1, "FAIL: inode numbers are equal: %d", st1.st_ino);
+
+ close(pipefd[0]);
+ close(pipefd[1]);
+ printf("PASS\n");
+
+ return (0);
+}
diff --git a/tests/sys/kern/pipe/pipe_overcommit1_test.c b/tests/sys/kern/pipe/pipe_overcommit1_test.c
new file mode 100644
index 0000000..f8f881d
--- /dev/null
+++ b/tests/sys/kern/pipe/pipe_overcommit1_test.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (C) 2005 Michael J. Silbersack <silby@freebsd.org>
+ * 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(s), this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified other than the possible
+ * addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice(s), this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 THE COPYRIGHT HOLDER(S) 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/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * $FreeBSD$
+ * This program just allocates as many pipes as it can to ensure
+ * that using up all pipe memory doesn't cause a panic.
+ */
+
+int
+main(void)
+{
+ int pipes[10000], returnval;
+ unsigned int i;
+
+ for (i = 0; i < nitems(pipes); i++) {
+ returnval = pipe(&pipes[i]);
+ }
+ printf("PASS\n");
+
+ exit(0);
+}
diff --git a/tests/sys/kern/pipe/pipe_overcommit2_test.c b/tests/sys/kern/pipe/pipe_overcommit2_test.c
new file mode 100644
index 0000000..ee1e714
--- /dev/null
+++ b/tests/sys/kern/pipe/pipe_overcommit2_test.c
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (C) 2005 Michael J. Silbersack <silby@freebsd.org>
+ * 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(s), this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified other than the possible
+ * addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice(s), this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 THE COPYRIGHT HOLDER(S) 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/param.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * $FreeBSD$
+ * This program tests how sys_pipe.c handles the case where there
+ * is ample memory to allocate a pipe, but the file descriptor
+ * limit for that user has been exceeded.
+ */
+
+int
+main(void)
+{
+ char template[] = "pipe.XXXXXXXXXX";
+ int lastfd, pipes[10000], returnval;
+ unsigned int i;
+
+ lastfd = -1;
+
+ if (mkstemp(template) == -1)
+ err(1, "mkstemp failed");
+
+ for (i = 0; i < nitems(pipes); i++) {
+ returnval = open(template, O_RDONLY);
+ if (returnval == -1 && (errno == ENFILE || errno == EMFILE))
+ break; /* All descriptors exhausted. */
+ else
+ lastfd = returnval;
+ }
+
+ /* First falloc failure case in sys_pipe.c:pipe() */
+ for (i = 0; i < 1000; i++) {
+ returnval = pipe(&pipes[i]);
+ }
+
+ /*
+ * Free just one FD so that the second falloc failure
+ * case will occur.
+ */
+ close(lastfd);
+
+ for (i = 0; i < 1000; i++) {
+ returnval = pipe(&pipes[i]);
+ }
+ printf("PASS\n");
+
+ unlink(template);
+
+ exit(0);
+}
diff --git a/tests/sys/kern/pipe/pipe_reverse2_test.c b/tests/sys/kern/pipe/pipe_reverse2_test.c
new file mode 100644
index 0000000..4666d95
--- /dev/null
+++ b/tests/sys/kern/pipe/pipe_reverse2_test.c
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2010 Jilles Tjoelker
+ * 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 THE 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 THE 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/select.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/*
+ * Check that pipes can be selected for writing in the reverse direction.
+ */
+int
+main(void)
+{
+ int pip[2];
+ fd_set set;
+ int n;
+
+ if (pipe(pip) == -1)
+ err(1, "FAIL: pipe");
+
+ FD_ZERO(&set);
+ FD_SET(pip[0], &set);
+ n = select(pip[1] + 1, NULL, &set, NULL, &(struct timeval){ 0, 0 });
+ if (n != 1)
+ errx(1, "FAIL: select initial reverse direction");
+
+ n = write(pip[0], "x", 1);
+ if (n != 1)
+ err(1, "FAIL: write reverse direction");
+
+ FD_ZERO(&set);
+ FD_SET(pip[0], &set);
+ n = select(pip[1] + 1, NULL, &set, NULL, &(struct timeval){ 0, 0 });
+ if (n != 1)
+ errx(1, "FAIL: select reverse direction after write");
+
+ printf("PASS\n");
+
+ return (0);
+}
diff --git a/tests/sys/kern/pipe/pipe_reverse_test.c b/tests/sys/kern/pipe/pipe_reverse_test.c
new file mode 100644
index 0000000..fd4518d
--- /dev/null
+++ b/tests/sys/kern/pipe/pipe_reverse_test.c
@@ -0,0 +1,149 @@
+/*
+Copyright (C) 2004 Michael J. Silbersack. 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/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * $FreeBSD$
+ * This program simply tests writing through the reverse direction of
+ * a pipe. Nothing too fancy, it's only needed because most pipe-using
+ * programs never touch the reverse direction (it doesn't exist on
+ * Linux.)
+ */
+
+int
+main(void)
+{
+ char buffer[65535], buffer2[65535], go[] = "go", go2[] = "go2";
+ int desc[2], ipc_coord[2];
+ size_t i;
+ ssize_t total;
+ int buggy, error;
+ pid_t new_pid;
+
+ buggy = 0;
+ total = 0;
+
+ error = pipe(desc);
+ if (error == -1)
+ err(1, "Couldn't allocate data pipe");
+
+ error = pipe(ipc_coord);
+ if (error == -1)
+ err(1, "Couldn't allocate IPC coordination pipe");
+
+ buffer[0] = 'A';
+
+ for (i = 1; i < (int)sizeof(buffer); i++) {
+ buffer[i] = buffer[i - 1] + 1;
+ if (buffer[i] > 'Z')
+ buffer[i] = 'A';
+ }
+
+ new_pid = fork();
+ assert(new_pid != -1);
+
+#define SYNC_R(i, _buf) do { \
+ int _error = errno; \
+ warnx("%d: waiting for synchronization", __LINE__); \
+ if (read(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
+ err(1, "failed to synchronize (%s)", (i == 0 ? "parent" : "child")); \
+ errno = _error; \
+ } while(0)
+
+#define SYNC_W(i, _buf) do { \
+ int _error = errno; \
+ warnx("%d: sending synchronization", __LINE__); \
+ if (write(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
+ err(1, "failed to synchronize (%s)", (i == 0 ? "child" : "parent")); \
+ errno = _error; \
+ } while(0)
+
+#define WRITE(s) do { \
+ ssize_t _size; \
+ if ((_size = write(desc[1], &buffer[total], s)) != s) \
+ warn("short write; wrote %zd, expected %d", _size, s); \
+ total += _size; \
+ } while(0)
+
+ if (new_pid == 0) {
+ SYNC_R(0, go);
+ for (i = 0; i < 8; i++)
+ WRITE(4096);
+
+ SYNC_W(0, go2);
+ SYNC_R(0, go);
+
+ for (i = 0; i < 2; i++)
+ WRITE(4096);
+
+ SYNC_W(0, go2);
+
+ _exit(0);
+ }
+
+ SYNC_W(1, go);
+ SYNC_R(1, go2);
+
+ error = read(desc[0], &buffer2, 8 * 4096);
+ total += error;
+ printf("Read %d bytes\n", error);
+
+ SYNC_W(1, go);
+ SYNC_R(1, go2);
+
+ error = read(desc[0], &buffer2[total], 2 * 4096);
+ total += error;
+ printf("Read %d bytes, done\n", error);
+
+ if (memcmp(buffer, buffer2, total) != 0) {
+ for (i = 0; i < (size_t)total; i++) {
+ if (buffer[i] != buffer2[i]) {
+ buggy = 1;
+ printf("Location %zu input: %hhx "
+ "output: %hhx\n",
+ i, buffer[i], buffer2[i]);
+ }
+ }
+ }
+
+ waitpid(new_pid, NULL, 0);
+
+ if ((buggy == 1) || (total != 10 * 4096))
+ errx(1, "FAILED");
+ else
+ printf("SUCCESS\n");
+
+ exit(0);
+}
diff --git a/tests/sys/kern/pipe/pipe_wraparound_test.c b/tests/sys/kern/pipe/pipe_wraparound_test.c
new file mode 100644
index 0000000..1ee0203
--- /dev/null
+++ b/tests/sys/kern/pipe/pipe_wraparound_test.c
@@ -0,0 +1,140 @@
+/*
+Copyright (C) 2004 Michael J. Silbersack. 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/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * $FreeBSD$
+ * This program tests to make sure that wraparound writes and reads
+ * are working, assuming that 16K socket buffers are used. In order
+ * to really stress the pipe code with this test, kernel modifications
+ * nay be necessary.
+ */
+
+int main (void)
+{
+ char buffer[32768], buffer2[32768], go[] = "go", go2[] = "go2";
+ int desc[2], ipc_coord[2];
+ ssize_t error, total;
+ int buggy, i;
+ pid_t new_pid;
+
+ buggy = 0;
+ total = 0;
+
+ error = pipe(desc);
+ if (error == -1)
+ err(1, "Couldn't allocate data pipe");
+
+ error = pipe(ipc_coord);
+ if (error == -1)
+ err(1, "Couldn't allocate IPC coordination pipe");
+
+ buffer[0] = 'A';
+
+ for (i = 1; i < (int)sizeof(buffer); i++) {
+ buffer[i] = buffer[i - 1] + 1;
+ if (buffer[i] > 'Z')
+ buffer[i] = 'A';
+ }
+
+ new_pid = fork();
+ assert(new_pid != -1);
+
+#define SYNC_R(i, _buf) do { \
+ int _error = errno; \
+ warnx("%d: waiting for synchronization", __LINE__); \
+ if (read(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
+ err(1, "failed to synchronize (%s)", (i == 0 ? "parent" : "child")); \
+ errno = _error; \
+ } while(0)
+
+#define SYNC_W(i, _buf) do { \
+ int _error = errno; \
+ warnx("%d: sending synchronization", __LINE__); \
+ if (write(ipc_coord[i], &_buf, sizeof(_buf)) != sizeof(_buf)) \
+ err(1, "failed to synchronize (%s)", (i == 0 ? "child" : "parent")); \
+ errno = _error; \
+ } while(0)
+
+#define WRITE(s) do { \
+ ssize_t _size; \
+ if ((_size = write(desc[1], &buffer[total], s)) != s) \
+ warn("short write; wrote %zd, expected %d", _size, s); \
+ total += _size; \
+ } while(0)
+
+ if (new_pid == 0) {
+ WRITE(4096);
+ WRITE(4096);
+ WRITE(4000);
+ SYNC_W(0, go2);
+
+ SYNC_R(0, go);
+ WRITE(3000);
+ WRITE(3000);
+ SYNC_W(0, go2);
+
+ _exit(0);
+ }
+
+ SYNC_R(1, go2);
+ error = read(desc[0], &buffer2, 8192);
+ total += error;
+ printf("Read %zd bytes\n", error);
+ SYNC_W(1, go);
+ SYNC_R(1, go2);
+ error = read(desc[0], &buffer2[total], 16384);
+ total += error;
+ printf("Read %zd bytes, done\n", error);
+
+ if (memcmp(buffer, buffer2, total) != 0) {
+ for (i = 0; i < total; i++) {
+ if (buffer[i] != buffer2[i]) {
+ buggy = 1;
+ printf("Location %d input: %hhx output: %hhx\n",
+ i, buffer[i], buffer2[i]);
+ }
+ }
+ }
+
+ waitpid(new_pid, NULL, 0);
+
+ if (buggy)
+ errx(1, "FAILURE");
+
+ printf("SUCCESS\n");
+
+ exit(0);
+}
OpenPOWER on IntegriCloud