diff --git a/tests/fs/Makefile b/tests/fs/Makefile index 99b14abd8d3b..f2292590764d 100644 --- a/tests/fs/Makefile +++ b/tests/fs/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.21 2011/03/10 20:02:26 pooka Exp $ +# $NetBSD: Makefile,v 1.22 2011/12/21 00:17:06 christos Exp $ .include @@ -6,7 +6,7 @@ TESTSDIR= ${TESTSBASE}/fs SUBDIR+= common .WAIT -TESTS_SUBDIRS+= ffs hfs kernfs lfs msdosfs nfs nullfs psshfs ptyfs puffs +TESTS_SUBDIRS+= ffs fifofs hfs kernfs lfs msdosfs nfs nullfs psshfs ptyfs puffs TESTS_SUBDIRS+= tmpfs umapfs union TESTS_SUBDIRS+= vfs diff --git a/tests/fs/fifofs/Makefile b/tests/fs/fifofs/Makefile new file mode 100644 index 000000000000..d2c0c558f5f4 --- /dev/null +++ b/tests/fs/fifofs/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.1 2011/12/21 00:17:07 christos Exp $ +# + +TESTSDIR= ${TESTSBASE}/fs/fifo +WARNS= 4 + +TESTS_C= t_fifo + +.include diff --git a/tests/fs/fifofs/t_fifo.c b/tests/fs/fifofs/t_fifo.c new file mode 100644 index 000000000000..c4a2060a6ebc --- /dev/null +++ b/tests/fs/fifofs/t_fifo.c @@ -0,0 +1,237 @@ +/* Test case written by Bharat Joshi */ +#include +__RCSID("$NetBSD: t_fifo.c,v 1.1 2011/12/21 00:17:07 christos Exp $"); + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef STANDALONE +#include +#endif + +#define FIFO_FILE_PATH "./fifo_file" +#define NUM_MESSAGES 20 +#define MSG_SIZE 240 +#define MESSAGE "I am fine" + +static int verbose = 0; + +/* + * child_writer + * + * Function that runs in child context and opens and write to the FIFO. + */ +static void +child_writer(void) +{ + ssize_t rv; + int fd; + size_t count; + char message[MSG_SIZE] = MESSAGE; + static const struct timespec ts = { 0, 10000 }; + + /* Open the fifo in write-mode */ + for (;;) { + fd = open(FIFO_FILE_PATH, O_WRONLY, 0); + if (fd == -1) { + if (errno == EINTR) + continue; + err(1, "Child: can't open fifo in write mode"); + } + break; + } + + for (count = 0; count < NUM_MESSAGES; count++) { + rv = write(fd, message, MSG_SIZE); + if (rv == -1) { + warn("Child: Failed to write"); + break; + } + if (rv != MSG_SIZE) + warnx("Child: wrote only %zd", rv); + nanosleep(&ts, NULL); + } + + close(fd); + if (verbose) { + printf("Child: Closed the fifo file\n"); + fflush(stdout); + } +} + +/* + * _sigchild_handler + * + * Called when a sigchild is delivered + */ +static void +sigchild_handler(int signo) +{ + if (verbose) { + if (signo == SIGCHLD) { + printf("Got sigchild\n"); + } else { + printf("Got %d signal\n", signo); + } + fflush(stdout); + } + +} + +static int +run(void) +{ + pid_t pid; + ssize_t rv; + int fd, status; + size_t buf_size = MSG_SIZE; + char buf[MSG_SIZE]; + struct sigaction action; + static const struct timespec ts = { 0, 500000000 }; + + /* Catch sigchild Signal */ + memset(&action, 0, sizeof(action)); + action.sa_handler = sigchild_handler; + sigemptyset(&action.sa_mask); + + if (sigaction(SIGCHLD, &action, NULL) == -1) + err(1, "sigaction"); + + (void)unlink(FIFO_FILE_PATH); + /* First create a fifo */ + if (mkfifo(FIFO_FILE_PATH, S_IRUSR | S_IWUSR) == -1) + err(1, "mkfifo"); + + switch ((pid = fork())) { + case -1: + err(1, "fork"); + case 0: + /* Open the file in write mode so that subsequent read + * from parent side does not block the parent.. + */ + if ((fd = open(FIFO_FILE_PATH, O_WRONLY, 0)) == -1) + err(1, "failed to open fifo"); + + /* In child */ + child_writer(); + return 0; + + default: + break; + } + + if (verbose) { + printf("Child pid is %d\n", pid ); + fflush(stdout); + } + + /* In parent */ + for (;;) { + if ((fd = open(FIFO_FILE_PATH, O_RDONLY, 0)) == -1) { + if (errno == EINTR) + continue; + else + err(1, "Failed to open the fifo in read mode"); + } + /* Read mode is opened */ + break; + + } + + nanosleep(&ts, NULL); + if (verbose) { + printf("Was sleeping...\n"); + fflush(stdout); + } + + for (;;) { + rv = read(fd, buf, buf_size); + + if (rv == -1) { + warn("Failed to read"); + if (errno == EINTR) { + if (verbose) { + printf("Parent interrupted, " + "continuing...\n"); + fflush(stdout); + } + continue; + } + + break; + } + + if (rv == 0) { + if (verbose) { + printf("Writers have closed, looks like we " + "are done\n"); + fflush(stdout); + } + break; + } + + if (verbose) { + printf("Received %zd bytes message '%s'\n", rv, buf); + fflush(stdout); + } + } + + close(fd); + + if (verbose) { + printf("We are done.. now reap the child"); + fflush(stdout); + } + + // Read the child... + while (waitpid(pid, &status, 0) == -1) + if (errno != EINTR) { + warn("Failed to reap the child"); + return 1; + } + + if (verbose) { + printf("We are done completely\n"); + fflush(stdout); + } + return 0; +} + +#ifndef STANDALONE +ATF_TC(parent_child); + +ATF_TC_HEAD(parent_child, tc) +{ + atf_tc_set_md_var(tc, "descr", "Checks that when a fifo is shared " + "between a reader parent and a writer child, that read will " + "return EOF, and not get stuck after the child exits"); +} + +ATF_TC_BODY(parent_child, tc) +{ + ATF_REQUIRE(run() == 0); +} + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, parent_child); + + return atf_no_error(); +} +#else +int +main(void) +{ + verbose = 1; + return run(); +} +#endif