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:
ngie 2015-11-16 05:38:40 +00:00
parent 0def4f1e60
commit ac4414a9cd
17 changed files with 575 additions and 429 deletions

View File

@ -377,6 +377,8 @@
..
execve
..
pipe
..
..
kqueue
..

View File

@ -19,6 +19,7 @@ WARNS?= 5
TESTS_SUBDIRS+= acct
TESTS_SUBDIRS+= execve
TESTS_SUBDIRS+= pipe
.include <netbsd-tests.test.mk>

View 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>

View 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);
}

View 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);
}

View File

@ -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");

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;

View 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);
}

View 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);
}

View File

@ -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>

View File

@ -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);
}

View File

@ -1,10 +0,0 @@
#!/bin/sh
# $FreeBSD$
cd `dirname $0`
executable=`basename $0 .t`
make $executable 2>&1 > /dev/null
exec ./$executable

View File

@ -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);
}
}
}
}

View File

@ -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");
}
}

View File

@ -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");
}
}