diff options
author | ngie <ngie@FreeBSD.org> | 2015-11-23 09:26:53 +0000 |
---|---|---|
committer | ngie <ngie@FreeBSD.org> | 2015-11-23 09:26:53 +0000 |
commit | d84acbd961805440ae74bea28ca28cbbb121b871 (patch) | |
tree | 0d3602d114daa2514ee31e0404b5f954cbdf3b69 /tests | |
parent | 3cb0c7ddff092a0a02d788dde117fd0769018c4a (diff) | |
download | FreeBSD-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/Makefile | 1 | ||||
-rw-r--r-- | tests/sys/kern/pipe/Makefile | 16 | ||||
-rw-r--r-- | tests/sys/kern/pipe/big_pipe_test.c | 88 | ||||
-rw-r--r-- | tests/sys/kern/pipe/pipe_fstat_bug_test.c | 138 | ||||
-rw-r--r-- | tests/sys/kern/pipe/pipe_ino_test.c | 65 | ||||
-rw-r--r-- | tests/sys/kern/pipe/pipe_overcommit1_test.c | 52 | ||||
-rw-r--r-- | tests/sys/kern/pipe/pipe_overcommit2_test.c | 83 | ||||
-rw-r--r-- | tests/sys/kern/pipe/pipe_reverse2_test.c | 67 | ||||
-rw-r--r-- | tests/sys/kern/pipe/pipe_reverse_test.c | 149 | ||||
-rw-r--r-- | tests/sys/kern/pipe/pipe_wraparound_test.c | 140 |
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); +} |