Home | History | Annotate | Download | only in pipe
      1 /*
      2  * Copyright (c) International Business Machines  Corp., 2001
      3  *    07/2001 Ported by Wayne Boyer
      4  * Copyright (c) 2018 Cyril Hrubis <chrubis (at) suse.cz>
      5  *
      6  * This program is free software;  you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License as published by
      8  * the Free Software Foundation; either version 2 of the License, or
      9  * (at your option) any later version.
     10  *
     11  * This program is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY;  without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     14  * the GNU General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License
     17  * along with this program;  if not, write to the Free Software
     18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     19  */
     20 
     21 /*
     22  * Check if many children can read what is written to a pipe by the parent.
     23  *
     24  * ALGORITHM
     25  *   For a different nchilds number:
     26  *	1. Open a pipe and write nchilds * (PIPE_BUF/nchilds) bytes into it
     27  *	2. Fork nchilds children
     28  *	3. Each child reads PIPE_BUF/nchilds characters and checks that the
     29  *	   bytes read are correct
     30  */
     31 #include <stdlib.h>
     32 #include "tst_test.h"
     33 
     34 static int fds[2];
     35 static unsigned char buf[PIPE_BUF];
     36 static size_t read_per_child;
     37 
     38 void do_child(void)
     39 {
     40 	size_t nread;
     41 	unsigned char rbuf[read_per_child];
     42 	unsigned int i;
     43 
     44 	SAFE_CLOSE(fds[1]);
     45 
     46 	nread = SAFE_READ(0, fds[0], rbuf, sizeof(rbuf));
     47 
     48 	if (nread != read_per_child) {
     49 		tst_res(TFAIL, "Invalid read size child %i size %zu",
     50 		        getpid(), nread);
     51 		return;
     52 	}
     53 
     54 	for (i = 0; i < read_per_child; i++) {
     55 		if (rbuf[i] != (i % 256)) {
     56 			tst_res(TFAIL,
     57 			        "Invalid byte read child %i byte %i have %i expected %i",
     58 				getpid(), i, rbuf[i], i % 256);
     59 			return;
     60 		}
     61 	}
     62 
     63 	tst_res(TPASS, "Child %i read pipe buffer correctly", getpid());
     64 }
     65 
     66 static unsigned int childs[] = {
     67 	1,
     68 	2,
     69 	3,
     70 	4,
     71 	10,
     72 	50
     73 };
     74 
     75 static void run(unsigned int tcase)
     76 {
     77 	pid_t pid;
     78 	unsigned int nchilds = childs[tcase];
     79 	read_per_child = PIPE_BUF/nchilds;
     80 	unsigned int i, j;
     81 
     82 	tst_res(TINFO, "Reading %zu per each of %u children",
     83 	        read_per_child, nchilds);
     84 
     85 	for (i = 0; i < nchilds; i++) {
     86 		for (j = 0; j < read_per_child; j++) {
     87 			buf[i * read_per_child + j] = j % 256;
     88 		}
     89 	}
     90 
     91 	SAFE_PIPE(fds);
     92 
     93 	SAFE_WRITE(1, fds[1], buf, read_per_child * nchilds);
     94 
     95 	for (i = 0; i < nchilds; i++) {
     96 		pid = SAFE_FORK();
     97 
     98 		if (!pid) {
     99 			do_child();
    100 			exit(0);
    101 		}
    102 	}
    103 
    104 	tst_reap_children();
    105 
    106 	SAFE_CLOSE(fds[0]);
    107 	SAFE_CLOSE(fds[1]);
    108 }
    109 
    110 static struct tst_test test = {
    111 	.forks_child = 1,
    112 	.test = run,
    113 	.tcnt = ARRAY_SIZE(childs),
    114 };
    115