Message ID | 20180405145015.7633-3-chrubis@suse.cz |
---|---|
State | Accepted |
Headers | show |
Series | [RFC,1/6] exit02: Rewrite to new library | expand |
----- Original Message ----- > + Check that the buffer read in the child is correct as well > > + We got rid of sleep(5) as a side effect > > Signed-off-by: Cyril Hrubis <chrubis@suse.cz> > --- > testcases/kernel/syscalls/pipe/pipe11.c | 289 > +++++++++----------------------- > 1 file changed, 77 insertions(+), 212 deletions(-) > > diff --git a/testcases/kernel/syscalls/pipe/pipe11.c > b/testcases/kernel/syscalls/pipe/pipe11.c > index e3b274128..6964f164d 100644 > --- a/testcases/kernel/syscalls/pipe/pipe11.c > +++ b/testcases/kernel/syscalls/pipe/pipe11.c > @@ -1,246 +1,111 @@ > /* > + * Copyright (c) International Business Machines Corp., 2001 > + * 07/2001 Ported by Wayne Boyer > + * Copyright (c) 2018 Cyril Hrubis <chrubis@suse.cz> > * > - * Copyright (c) International Business Machines Corp., 2001 > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > * > - * This program is free software; you can redistribute it and/or modify > - * it under the terms of the GNU General Public License as published by > - * the Free Software Foundation; either version 2 of the License, or > - * (at your option) any later version. > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > * > - * This program is distributed in the hope that it will be useful, > - * but WITHOUT ANY WARRANTY; without even the implied warranty of > - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > - * the GNU General Public License for more details. > - * > - * You should have received a copy of the GNU General Public License > - * along with this program; if not, write to the Free Software > - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > 02110-1301 USA > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 > USA > */ > > /* > - * NAME > - * pipe11.c > - * > - * DESCRIPTION > - * Check if many children can read what is written to a pipe by the > - * parent. > + * Check if many children can read what is written to a pipe by the parent. > * > * ALGORITHM > - * 1. Open a pipe and write to it > - * 2. Fork a large number of children > - * 3. Have the children read the pipe and check how many characters > - * each got > - * > - * USAGE: <for command-line> > - * pipe11 [-c n] [-f] [-i n] [-I x] [-P x] [-t] > - * where, -c n : Run n copies concurrently. > - * -f : Turn off functionality Testing. > - * -i n : Execute test n times. > - * -I x : Execute test for x seconds. > - * -P x : Pause for x seconds between iterations. > - * -t : Turn on syscall timing. > - * > - * HISTORY > - * 07/2001 Ported by Wayne Boyer > - * > - * RESTRICTIONS > - * None > + * For a different nchilds number: > + * 1. Open a pipe and write nchilds * (PIPE_BUF/nchilds) bytes into it > + * 2. Fork nchilds children > + * 3. Each child reads PIPE_BUF/nchilds characters and checks that the > + * bytes read are correct > */ > -#include <sys/types.h> > -#include <sys/wait.h> > -#include <errno.h> > -#include <stdio.h> > -#include <limits.h> > -#include "test.h" > - > -char *TCID = "pipe11"; > -int TST_TOTAL = 1; > - > -void do_child(void); > -void do_child_uclinux(void); > -void setup(void); > -void cleanup(void); > - > -#define NUMCHILD 50 > -#define NCPERCHILD 50 > -char rawchars[] = > - > "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; > -int kidid; > -int numchild; /* no of children to fork */ > -int ncperchild; /* no of chars child should read */ > -int szcharbuf; /* size of char buf */ > -int pipewrcnt; /* chars written to pipe */ > -char *wrbuf, *rdbuf; > -int fd[2]; /* fds for pipe read/write */ > - > -ssize_t do_read(int fd, void *buf, size_t count) > -{ > - ssize_t n; > - > - do { > - n = read(fd, buf, count); > - } while (n < 0 && errno == EINTR); > +#include <stdlib.h> > +#include "tst_test.h" > > - return n; > -} > +static int fd[2]; > +static unsigned char buf[PIPE_BUF]; > +static size_t read_per_child; > > -int main(int ac, char **av) > +void do_child(void) > { > - int lc; > - > - int i; > - int fork_ret, status; > - int written; /* no of chars read and written */ > - > - tst_parse_opts(ac, av, NULL, NULL); > -#ifdef UCLINUX > - maybe_run_child(&do_child_uclinux, "ddddd", &fd[0], &fd[1], &kidid, > - &ncperchild, &szcharbuf); > -#endif > - > - setup(); > - > - for (lc = 0; TEST_LOOPING(lc); lc++) { > - > - /* reset tst_count in case we are looping */ > - tst_count = 0; > + size_t nread; > + unsigned char rbuf[read_per_child]; > + unsigned int i; > > - TEST(pipe(fd)); > + SAFE_CLOSE(fd[1]); > > - if (TEST_RETURN != 0) { > - tst_resm(TFAIL, "pipe creation failed"); > - continue; > - } > - > - written = write(fd[1], wrbuf, szcharbuf); > - if (written != szcharbuf) { > - tst_brkm(TBROK, cleanup, "write to pipe failed"); > - } > - > -refork: > - ++kidid; > - fork_ret = FORK_OR_VFORK(); > - > - if (fork_ret < 0) { > - tst_brkm(TBROK, cleanup, "fork() failed"); > - } > - > - if ((fork_ret != 0) && (fork_ret != -1) && (kidid < numchild)) { > - goto refork; > - } > + nread = SAFE_READ(0, fd[0], rbuf, sizeof(rbuf)); > > - if (fork_ret == 0) { /* child */ > -#ifdef UCLINUX > - if (self_exec(av[0], "ddddd", fd[0], fd[1], kidid, > - ncperchild, szcharbuf) < 0) { > - tst_brkm(TBROK, cleanup, "self_exec failed"); > - } > -#else > - do_child(); > -#endif > - } > + if (nread != read_per_child) { > + tst_res(TFAIL, "Invalid read size child %i size %zu", > + getpid(), nread); > + return; > + } > > - /* parent */ > - sleep(5); > - tst_resm(TINFO, "There are %d children to wait for", kidid); > - for (i = 1; i <= kidid; ++i) { > - wait(&status); > - if (status == 0) { > - tst_resm(TPASS, "child %d exited successfully", > - i); > - } else { > - tst_resm(TFAIL, "child %d exited with bad " > - "status", i); > - } > + for (i = 0; i < read_per_child; i++) { > + if (rbuf[i] != (i % 256)) { > + tst_res(TFAIL, > + "Invalid byte read child %i byte %i have %i expected %i", > + getpid(), i, rbuf[i], i % 256); > + return; > } > } > - cleanup(); > - > - tst_exit(); > -} > - > -/* > - * do_child() > - */ > -void do_child(void) > -{ > - int nread; > > - if (close(fd[1])) { > - tst_resm(TINFO, "child %d " "could not close pipe", kidid); > - exit(0); > - } > - nread = do_read(fd[0], rdbuf, ncperchild); > - if (nread == ncperchild) { > - tst_resm(TINFO, "child %d " "got %d chars", kidid, nread); > - exit(0); > - } else { > - tst_resm(TFAIL, "child %d did not receive expected no of " > - "characters, got %d characters", kidid, nread); > - exit(1); > - } > + tst_res(TPASS, "Child %i read pipe buffer correctly", getpid()); > } > > -/* > - * do_child_uclinux() - as above, but mallocs rdbuf first > - */ > -void do_child_uclinux(void) > -{ > - if ((rdbuf = malloc(szcharbuf)) == NULL) { > - tst_brkm(TBROK, cleanup, "malloc of rdbuf failed"); > - } > - > - do_child(); > -} > +static unsigned int childs[] = { > + 1, > + 2, > + 3, > + 4, > + 10, > + 50 > +}; > > -/* > - * setup() - performs all ONE TIME setup for this test. > - */ > -void setup(void) > +static void run(unsigned int tcase) > { > - int i; > - unsigned int j; > + pid_t pid; > + unsigned int nchilds = childs[tcase]; > + read_per_child = PIPE_BUF/nchilds; > + unsigned int i, j; > > - tst_sig(FORK, DEF_HANDLER, cleanup); > + tst_res(TINFO, "Reading %zu per each of %u children", > + read_per_child, nchilds); > > - TEST_PAUSE; > - > - numchild = NUMCHILD; > - ncperchild = NCPERCHILD; > + for (i = 0; i < nchilds; i++) { > + for (j = 0; j < read_per_child; j++) { > + buf[i * read_per_child + j] = j % 256; > + } > + } > > - kidid = 0; > + SAFE_PIPE(fd); > > - /* allocate read and write buffers */ > - szcharbuf = numchild * ncperchild; > + SAFE_WRITE(1, fd[1], buf, read_per_child * nchilds); > > - /* make sure pipe write doesn't block */ > - if (szcharbuf == PIPE_BUF) { > - /* adjust number of characters per child */ > - ncperchild = szcharbuf / numchild; > - } > + for (i = 0; i < nchilds; i++) { > + pid = SAFE_FORK(); > > - if ((wrbuf = malloc(szcharbuf)) == NULL) { > - tst_brkm(TBROK, cleanup, "malloc failed"); > - } > - > - if ((rdbuf = malloc(szcharbuf)) == NULL) { > - tst_brkm(TBROK, cleanup, "malloc of rdbuf failed"); > + if (!pid) { > + do_child(); > + exit(0); > + } > } > > - /* initialize wrbuf */ > - j = 0; > - for (i = 0; i < szcharbuf;) { > - wrbuf[i++] = rawchars[j++]; > - if (j >= sizeof(rawchars)) > - j = 0; > - } > + tst_reap_children(); pipe fds are not closed, and this could in theory repeat many times. Other than that ACK. Regards, Jan > } > > -/* > - * cleanup() - performs all ONE TIME cleanup for this test at > - * completion or premature exit. > - */ > -void cleanup(void) > -{ > - > -} > +static struct tst_test test = { > + .forks_child = 1, > + .test = run, > + .tcnt = ARRAY_SIZE(childs), > +}; > -- > 2.13.6 > > > -- > Mailing list info: https://lists.linux.it/listinfo/ltp >
diff --git a/testcases/kernel/syscalls/pipe/pipe11.c b/testcases/kernel/syscalls/pipe/pipe11.c index e3b274128..6964f164d 100644 --- a/testcases/kernel/syscalls/pipe/pipe11.c +++ b/testcases/kernel/syscalls/pipe/pipe11.c @@ -1,246 +1,111 @@ /* + * Copyright (c) International Business Machines Corp., 2001 + * 07/2001 Ported by Wayne Boyer + * Copyright (c) 2018 Cyril Hrubis <chrubis@suse.cz> * - * Copyright (c) International Business Machines Corp., 2001 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* - * NAME - * pipe11.c - * - * DESCRIPTION - * Check if many children can read what is written to a pipe by the - * parent. + * Check if many children can read what is written to a pipe by the parent. * * ALGORITHM - * 1. Open a pipe and write to it - * 2. Fork a large number of children - * 3. Have the children read the pipe and check how many characters - * each got - * - * USAGE: <for command-line> - * pipe11 [-c n] [-f] [-i n] [-I x] [-P x] [-t] - * where, -c n : Run n copies concurrently. - * -f : Turn off functionality Testing. - * -i n : Execute test n times. - * -I x : Execute test for x seconds. - * -P x : Pause for x seconds between iterations. - * -t : Turn on syscall timing. - * - * HISTORY - * 07/2001 Ported by Wayne Boyer - * - * RESTRICTIONS - * None + * For a different nchilds number: + * 1. Open a pipe and write nchilds * (PIPE_BUF/nchilds) bytes into it + * 2. Fork nchilds children + * 3. Each child reads PIPE_BUF/nchilds characters and checks that the + * bytes read are correct */ -#include <sys/types.h> -#include <sys/wait.h> -#include <errno.h> -#include <stdio.h> -#include <limits.h> -#include "test.h" - -char *TCID = "pipe11"; -int TST_TOTAL = 1; - -void do_child(void); -void do_child_uclinux(void); -void setup(void); -void cleanup(void); - -#define NUMCHILD 50 -#define NCPERCHILD 50 -char rawchars[] = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890"; -int kidid; -int numchild; /* no of children to fork */ -int ncperchild; /* no of chars child should read */ -int szcharbuf; /* size of char buf */ -int pipewrcnt; /* chars written to pipe */ -char *wrbuf, *rdbuf; -int fd[2]; /* fds for pipe read/write */ - -ssize_t do_read(int fd, void *buf, size_t count) -{ - ssize_t n; - - do { - n = read(fd, buf, count); - } while (n < 0 && errno == EINTR); +#include <stdlib.h> +#include "tst_test.h" - return n; -} +static int fd[2]; +static unsigned char buf[PIPE_BUF]; +static size_t read_per_child; -int main(int ac, char **av) +void do_child(void) { - int lc; - - int i; - int fork_ret, status; - int written; /* no of chars read and written */ - - tst_parse_opts(ac, av, NULL, NULL); -#ifdef UCLINUX - maybe_run_child(&do_child_uclinux, "ddddd", &fd[0], &fd[1], &kidid, - &ncperchild, &szcharbuf); -#endif - - setup(); - - for (lc = 0; TEST_LOOPING(lc); lc++) { - - /* reset tst_count in case we are looping */ - tst_count = 0; + size_t nread; + unsigned char rbuf[read_per_child]; + unsigned int i; - TEST(pipe(fd)); + SAFE_CLOSE(fd[1]); - if (TEST_RETURN != 0) { - tst_resm(TFAIL, "pipe creation failed"); - continue; - } - - written = write(fd[1], wrbuf, szcharbuf); - if (written != szcharbuf) { - tst_brkm(TBROK, cleanup, "write to pipe failed"); - } - -refork: - ++kidid; - fork_ret = FORK_OR_VFORK(); - - if (fork_ret < 0) { - tst_brkm(TBROK, cleanup, "fork() failed"); - } - - if ((fork_ret != 0) && (fork_ret != -1) && (kidid < numchild)) { - goto refork; - } + nread = SAFE_READ(0, fd[0], rbuf, sizeof(rbuf)); - if (fork_ret == 0) { /* child */ -#ifdef UCLINUX - if (self_exec(av[0], "ddddd", fd[0], fd[1], kidid, - ncperchild, szcharbuf) < 0) { - tst_brkm(TBROK, cleanup, "self_exec failed"); - } -#else - do_child(); -#endif - } + if (nread != read_per_child) { + tst_res(TFAIL, "Invalid read size child %i size %zu", + getpid(), nread); + return; + } - /* parent */ - sleep(5); - tst_resm(TINFO, "There are %d children to wait for", kidid); - for (i = 1; i <= kidid; ++i) { - wait(&status); - if (status == 0) { - tst_resm(TPASS, "child %d exited successfully", - i); - } else { - tst_resm(TFAIL, "child %d exited with bad " - "status", i); - } + for (i = 0; i < read_per_child; i++) { + if (rbuf[i] != (i % 256)) { + tst_res(TFAIL, + "Invalid byte read child %i byte %i have %i expected %i", + getpid(), i, rbuf[i], i % 256); + return; } } - cleanup(); - - tst_exit(); -} - -/* - * do_child() - */ -void do_child(void) -{ - int nread; - if (close(fd[1])) { - tst_resm(TINFO, "child %d " "could not close pipe", kidid); - exit(0); - } - nread = do_read(fd[0], rdbuf, ncperchild); - if (nread == ncperchild) { - tst_resm(TINFO, "child %d " "got %d chars", kidid, nread); - exit(0); - } else { - tst_resm(TFAIL, "child %d did not receive expected no of " - "characters, got %d characters", kidid, nread); - exit(1); - } + tst_res(TPASS, "Child %i read pipe buffer correctly", getpid()); } -/* - * do_child_uclinux() - as above, but mallocs rdbuf first - */ -void do_child_uclinux(void) -{ - if ((rdbuf = malloc(szcharbuf)) == NULL) { - tst_brkm(TBROK, cleanup, "malloc of rdbuf failed"); - } - - do_child(); -} +static unsigned int childs[] = { + 1, + 2, + 3, + 4, + 10, + 50 +}; -/* - * setup() - performs all ONE TIME setup for this test. - */ -void setup(void) +static void run(unsigned int tcase) { - int i; - unsigned int j; + pid_t pid; + unsigned int nchilds = childs[tcase]; + read_per_child = PIPE_BUF/nchilds; + unsigned int i, j; - tst_sig(FORK, DEF_HANDLER, cleanup); + tst_res(TINFO, "Reading %zu per each of %u children", + read_per_child, nchilds); - TEST_PAUSE; - - numchild = NUMCHILD; - ncperchild = NCPERCHILD; + for (i = 0; i < nchilds; i++) { + for (j = 0; j < read_per_child; j++) { + buf[i * read_per_child + j] = j % 256; + } + } - kidid = 0; + SAFE_PIPE(fd); - /* allocate read and write buffers */ - szcharbuf = numchild * ncperchild; + SAFE_WRITE(1, fd[1], buf, read_per_child * nchilds); - /* make sure pipe write doesn't block */ - if (szcharbuf == PIPE_BUF) { - /* adjust number of characters per child */ - ncperchild = szcharbuf / numchild; - } + for (i = 0; i < nchilds; i++) { + pid = SAFE_FORK(); - if ((wrbuf = malloc(szcharbuf)) == NULL) { - tst_brkm(TBROK, cleanup, "malloc failed"); - } - - if ((rdbuf = malloc(szcharbuf)) == NULL) { - tst_brkm(TBROK, cleanup, "malloc of rdbuf failed"); + if (!pid) { + do_child(); + exit(0); + } } - /* initialize wrbuf */ - j = 0; - for (i = 0; i < szcharbuf;) { - wrbuf[i++] = rawchars[j++]; - if (j >= sizeof(rawchars)) - j = 0; - } + tst_reap_children(); } -/* - * cleanup() - performs all ONE TIME cleanup for this test at - * completion or premature exit. - */ -void cleanup(void) -{ - -} +static struct tst_test test = { + .forks_child = 1, + .test = run, + .tcnt = ARRAY_SIZE(childs), +};
+ Check that the buffer read in the child is correct as well + We got rid of sleep(5) as a side effect Signed-off-by: Cyril Hrubis <chrubis@suse.cz> --- testcases/kernel/syscalls/pipe/pipe11.c | 289 +++++++++----------------------- 1 file changed, 77 insertions(+), 212 deletions(-)