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 MFC after: 1 week Sponsored by: EMC / Isilon Storage Division
This commit is contained in:
parent
0def4f1e60
commit
ac4414a9cd
@ -377,6 +377,8 @@
|
||||
..
|
||||
execve
|
||||
..
|
||||
pipe
|
||||
..
|
||||
..
|
||||
kqueue
|
||||
..
|
||||
|
@ -19,6 +19,7 @@ WARNS?= 5
|
||||
|
||||
TESTS_SUBDIRS+= acct
|
||||
TESTS_SUBDIRS+= execve
|
||||
TESTS_SUBDIRS+= pipe
|
||||
|
||||
.include <netbsd-tests.test.mk>
|
||||
|
||||
|
16
tests/sys/kern/pipe/Makefile
Normal file
16
tests/sys/kern/pipe/Makefile
Normal file
@ -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>
|
88
tests/sys/kern/pipe/big_pipe_test.c
Normal file
88
tests/sys/kern/pipe/big_pipe_test.c
Normal file
@ -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);
|
||||
}
|
138
tests/sys/kern/pipe/pipe_fstat_bug_test.c
Normal file
138
tests/sys/kern/pipe/pipe_fstat_bug_test.c
Normal file
@ -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);
|
||||
}
|
@ -40,7 +40,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
main(void)
|
||||
{
|
||||
int pipefd[2];
|
||||
struct stat st1, st2;
|
||||
@ -52,12 +52,11 @@ main(int argc, char **argv)
|
||||
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_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");
|
@ -26,8 +26,10 @@
|
||||
* DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* $FreeBSD$
|
||||
@ -35,13 +37,16 @@
|
||||
* that using up all pipe memory doesn't cause a panic.
|
||||
*/
|
||||
|
||||
int main (void)
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int i, returnval;
|
||||
int pipes[10000];
|
||||
for (i = 0; i < 10000; i++) {
|
||||
int pipes[10000], returnval;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < nitems(pipes); i++) {
|
||||
returnval = pipe(&pipes[i]);
|
||||
}
|
||||
printf("PASS\n");
|
||||
|
||||
exit(0);
|
||||
}
|
@ -26,9 +26,13 @@
|
||||
* DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* $FreeBSD$
|
||||
@ -37,15 +41,21 @@
|
||||
* limit for that user has been exceeded.
|
||||
*/
|
||||
|
||||
int main (int argc, void *argv[])
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
int i, returnval, lastfd;
|
||||
int pipes[10000];
|
||||
char template[] = "pipe.XXXXXXXXXX";
|
||||
int lastfd, pipes[10000], returnval;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 100000; i++) {
|
||||
returnval = open(argv[0], O_RDONLY);
|
||||
if (returnval < 1)
|
||||
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;
|
||||
@ -66,4 +76,8 @@ int main (int argc, void *argv[])
|
||||
returnval = pipe(&pipes[i]);
|
||||
}
|
||||
printf("PASS\n");
|
||||
|
||||
unlink(template);
|
||||
|
||||
exit(0);
|
||||
}
|
@ -26,17 +26,17 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* Check that pipes can be selected for writing in the reverse direction.
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
main(void)
|
||||
{
|
||||
int pip[2];
|
||||
fd_set set;
|
149
tests/sys/kern/pipe/pipe_reverse_test.c
Normal file
149
tests/sys/kern/pipe/pipe_reverse_test.c
Normal file
@ -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);
|
||||
}
|
140
tests/sys/kern/pipe/pipe_wraparound_test.c
Normal file
140
tests/sys/kern/pipe/pipe_wraparound_test.c
Normal file
@ -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);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
#
|
||||
# $FreeBSD$
|
||||
#
|
||||
# "make" then "make regress".
|
||||
#
|
||||
PROG= bigpipetest
|
||||
MAN=
|
||||
|
||||
regress:
|
||||
@if ./bigpipetest; then \
|
||||
echo "PASS"; \
|
||||
else \
|
||||
echo "FAIL"; \
|
||||
fi
|
||||
|
||||
.include <bsd.prog.mk>
|
@ -1,82 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/select.h>
|
||||
#include <string.h>
|
||||
#include <errno.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$
|
||||
*/
|
||||
|
||||
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) {
|
||||
perror("select");
|
||||
exit(1);
|
||||
}
|
||||
if (i != 1) {
|
||||
fprintf(stderr, "select returned unexpected value %d\n", i);
|
||||
exit(1);
|
||||
}
|
||||
i = write(fd, buf, buflen);
|
||||
if (i < 0) {
|
||||
if (errno != EAGAIN)
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
buf += i;
|
||||
buflen -= i;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char buf[BIG_PIPE_SIZE]; /* any value over PIPE_SIZE should do */
|
||||
int i, flags, fd[2];
|
||||
|
||||
printf("1..1\n");
|
||||
|
||||
if (pipe(fd) < 0) { perror("pipe"); exit(1); }
|
||||
|
||||
flags = fcntl(fd[1], F_GETFL);
|
||||
if (flags == -1 || fcntl(fd[1], F_SETFL, flags|O_NONBLOCK) == -1) {
|
||||
perror("fcntl");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
close(fd[1]);
|
||||
for (;;) {
|
||||
i = read(fd[0], buf, 256); /* any small size should do */
|
||||
if (i == 0) break;
|
||||
if (i < 0) { perror("read"); exit(1); }
|
||||
}
|
||||
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 1\n");
|
||||
exit(0);
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#!/bin/sh
|
||||
# $FreeBSD$
|
||||
|
||||
cd `dirname $0`
|
||||
|
||||
executable=`basename $0 .t`
|
||||
|
||||
make $executable 2>&1 > /dev/null
|
||||
|
||||
exec ./$executable
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
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 <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.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];
|
||||
int desc[2];
|
||||
int error, successes = 0;
|
||||
struct stat status;
|
||||
pid_t new_pid;
|
||||
|
||||
error = pipe(desc);
|
||||
|
||||
if (error)
|
||||
err(0, "Couldn't allocate fds\n");
|
||||
|
||||
new_pid = fork();
|
||||
|
||||
if (new_pid == 0) {
|
||||
write(desc[1], &buffer, 145);
|
||||
usleep(1000000);
|
||||
write(desc[1], &buffer, 2048);
|
||||
usleep(1000000);
|
||||
write(desc[1], &buffer, 4096);
|
||||
usleep(1000000);
|
||||
write(desc[1], &buffer, 8191);
|
||||
usleep(1000000);
|
||||
write(desc[1], &buffer, 8192);
|
||||
usleep(1000000);
|
||||
} else {
|
||||
while (successes < 5) {
|
||||
usleep(3000);
|
||||
fstat(desc[0], &status);
|
||||
error = read(desc[0], &buffer2, 32768);
|
||||
if (status.st_size != error)
|
||||
err(0, "FAILURE: stat size %d read size %d\n", (int)status.st_size, error);
|
||||
if (error > 0) {
|
||||
printf("SUCCESS at stat size %d read size %d\n", (int)status.st_size, error);
|
||||
successes++;
|
||||
/* Sleep to avoid the natural race in reading st_size. */
|
||||
usleep(1000000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
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 <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.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];
|
||||
int desc[2];
|
||||
int buggy, error, i, successes, total;
|
||||
struct stat status;
|
||||
pid_t new_pid;
|
||||
|
||||
buggy = 0;
|
||||
total = 0;
|
||||
|
||||
error = pipe(desc);
|
||||
|
||||
if (error)
|
||||
err(0, "Couldn't allocate fds\n");
|
||||
|
||||
buffer[0] = 'A';
|
||||
|
||||
for (i = 1; i < 65535; i++) {
|
||||
buffer[i] = buffer[i - 1] + 1;
|
||||
if (buffer[i] > 'Z')
|
||||
buffer[i] = 'A';
|
||||
}
|
||||
|
||||
new_pid = fork();
|
||||
|
||||
if (new_pid == 0) {
|
||||
error = write(desc[0], &buffer, 4096);
|
||||
total += error;
|
||||
error = write(desc[0], &buffer[total], 4096);
|
||||
total += error;
|
||||
error = write(desc[0], &buffer[total], 4096);
|
||||
total += error;
|
||||
error = write(desc[0], &buffer[total], 4096);
|
||||
total += error;
|
||||
error = write(desc[0], &buffer[total], 4096);
|
||||
total += error;
|
||||
error = write(desc[0], &buffer[total], 4096);
|
||||
total += error;
|
||||
error = write(desc[0], &buffer[total], 4096);
|
||||
total += error;
|
||||
error = write(desc[0], &buffer[total], 4096);
|
||||
total += error;
|
||||
printf("Wrote %d bytes, sleeping\n", total);
|
||||
usleep(1000000);
|
||||
error = write(desc[0], &buffer[total], 4096);
|
||||
total += error;
|
||||
error = write(desc[0], &buffer[total], 4096);
|
||||
total += error;
|
||||
printf("Wrote another 8192 bytes, %d total, done\n", total);
|
||||
} else {
|
||||
usleep(500000);
|
||||
error = read(desc[1], &buffer2, 32768);
|
||||
total += error;
|
||||
printf("Read %d bytes, going back to sleep\n", error);
|
||||
usleep(1000000);
|
||||
error = read(desc[1], &buffer2[total], 8192);
|
||||
total += error;
|
||||
printf("Read %d bytes, done\n", error);
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
if ((buggy == 1) || (total != 40960))
|
||||
printf("FAILURE\n");
|
||||
else
|
||||
printf("SUCCESS\n");
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
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 <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.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];
|
||||
int desc[2];
|
||||
int buggy, error, i, successes, total;
|
||||
struct stat status;
|
||||
pid_t new_pid;
|
||||
|
||||
buggy = 0;
|
||||
total = 0;
|
||||
|
||||
error = pipe(desc);
|
||||
|
||||
if (error)
|
||||
err(0, "Couldn't allocate fds\n");
|
||||
|
||||
buffer[0] = 'A';
|
||||
|
||||
for (i = 1; i < 32768; i++) {
|
||||
buffer[i] = buffer[i - 1] + 1;
|
||||
if (buffer[i] > 'Z')
|
||||
buffer[i] = 'A';
|
||||
}
|
||||
|
||||
new_pid = fork();
|
||||
|
||||
if (new_pid == 0) {
|
||||
error = write(desc[1], &buffer, 4096);
|
||||
total += error;
|
||||
error = write(desc[1], &buffer[total], 4096);
|
||||
total += error;
|
||||
error = write(desc[1], &buffer[total], 4000);
|
||||
total += error;
|
||||
printf("Wrote %d bytes, sleeping\n", total);
|
||||
usleep(1000000);
|
||||
error = write(desc[1], &buffer[total], 3000);
|
||||
total += error;
|
||||
error = write(desc[1], &buffer[total], 3000);
|
||||
total += error;
|
||||
printf("Wrote another 6000 bytes, %d total, done\n", total);
|
||||
} else {
|
||||
usleep(500000);
|
||||
error = read(desc[0], &buffer2, 8192);
|
||||
total += error;
|
||||
printf("Read %d bytes, going back to sleep\n", error);
|
||||
usleep(1000000);
|
||||
error = read(desc[0], &buffer2[total], 16384);
|
||||
total += error;
|
||||
printf("Read %d bytes, done\n", error);
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
if (buggy)
|
||||
printf("FAILURE\n");
|
||||
else
|
||||
printf("SUCCESS\n");
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user