xref: /openbsd/regress/sys/kern/pipe/test-ping-pong.c (revision 065bbfdc)
1*065bbfdcSanton /*	$OpenBSD: test-ping-pong.c,v 1.2 2021/10/22 05:03:57 anton Exp $	*/
279596596Santon 
379596596Santon /*
479596596Santon  * Copyright (c) 2019 Anton Lindqvist <anton@openbsd.org>
579596596Santon  *
679596596Santon  * Permission to use, copy, modify, and distribute this software for any
779596596Santon  * purpose with or without fee is hereby granted, provided that the above
879596596Santon  * copyright notice and this permission notice appear in all copies.
979596596Santon  *
1079596596Santon  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1179596596Santon  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1279596596Santon  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1379596596Santon  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1479596596Santon  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1579596596Santon  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1679596596Santon  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1779596596Santon  */
1879596596Santon 
1979596596Santon #include <err.h>
2079596596Santon #include <errno.h>
2179596596Santon #include <stdlib.h>
2279596596Santon #include <string.h>
2379596596Santon #include <unistd.h>
2479596596Santon 
2579596596Santon #include "pipe.h"
2679596596Santon 
2779596596Santon /*
2879596596Santon  * Basic read/write test invovling two processes, P1 and P2. P1 writes "ping" on
2979596596Santon  * the pipe which is received and verified by P2. P2 writes "pong" as a reply
3079596596Santon  * which is received and verified P1. After N rounds, P1 closes the pipe and
3179596596Santon  * SIGPIPE is expected to be delivered to P2.
3279596596Santon  */
3379596596Santon int
test_ping_pong(void)3479596596Santon test_ping_pong(void)
3579596596Santon {
3679596596Santon 	const char ping[] = "ping";
3779596596Santon 	const char pong[] = "pong";
3879596596Santon 	char buf[5];
3979596596Santon 	int pip[2][2], rp, wp;
4079596596Santon 	int nrounds = 10;
4179596596Santon 	ssize_t n;
4279596596Santon 	pid_t pid;
4379596596Santon 
4479596596Santon 	if (pipe(pip[0]) == -1)
4579596596Santon 		err(1, "pipe");
4679596596Santon 	if (pipe(pip[1]) == -1)
4779596596Santon 		err(1, "pipe");
4879596596Santon 
4979596596Santon 	pid = fork();
5079596596Santon 	if (pid == -1)
5179596596Santon 		err(1, "fork");
5279596596Santon 	if (pid == 0) {
5379596596Santon 		rp = pip[0][0];
5479596596Santon 		close(pip[0][1]);
5579596596Santon 
5679596596Santon 		wp = pip[1][1];
5779596596Santon 		close(pip[1][0]);
5879596596Santon 
5979596596Santon 		for (;;) {
6079596596Santon 			n = read(rp, buf, sizeof(buf));
6179596596Santon 			if (n == -1)
6279596596Santon 				err(1, "[c] read");
6379596596Santon 			if (n == 0)
6479596596Santon 				break;
6579596596Santon 			if (n != sizeof(buf))
6679596596Santon 				errx(1, "[c] read: %ld < %zu", n, sizeof(buf));
6779596596Santon 			if (strcmp(ping, buf))
6879596596Santon 				errx(1, "[c] read: %s != %s\n", ping, buf);
6979596596Santon 
7079596596Santon 			n = write(wp, pong, sizeof(pong));
7179596596Santon 			if (n == -1)
7279596596Santon 				err(1, "[c] write");
7379596596Santon 			if (n != sizeof(pong))
74*065bbfdcSanton 				errx(1, "[c] write: %ld < %zu",
75*065bbfdcSanton 				    n, sizeof(pong));
7679596596Santon 
7779596596Santon 			nrounds--;
7879596596Santon 		}
7979596596Santon 		if (nrounds != 0)
8079596596Santon 			errx(1, "[c] nrounds: %d > 0", nrounds);
8179596596Santon 
8279596596Santon 		/*
8379596596Santon 		 * Writing on the pipe must cause delivery of SIGPIPE at this
8479596596Santon 		 * point since the read end is gone.
8579596596Santon 		 */
8679596596Santon 		n = write(wp, pong, sizeof(pong));
8779596596Santon 		if (n != -1)
8879596596Santon 			errx(1, "[c] write: %ld != -1", n);
8979596596Santon 		else if (errno != EPIPE)
9079596596Santon 			errx(1, "[c] write: %d != %d", errno, EPIPE);
9179596596Santon 		else if (!gotsigpipe)
9279596596Santon 			errx(1, "[c] write: no SIGPIPE");
9379596596Santon 
9479596596Santon 		_exit(0);
9579596596Santon 	} else {
9679596596Santon 		rp = pip[1][0];
9779596596Santon 		close(pip[1][1]);
9879596596Santon 
9979596596Santon 		wp = pip[0][1];
10079596596Santon 		close(pip[0][0]);
10179596596Santon 
10279596596Santon 		for (;;) {
10379596596Santon 			n = write(wp, ping, sizeof(ping));
10479596596Santon 			if (n == -1)
10579596596Santon 				err(1, "[p] write");
10679596596Santon 			if (n != sizeof(ping))
107*065bbfdcSanton 				errx(1, "[p] write: %ld < %zu",
108*065bbfdcSanton 				    n, sizeof(ping));
10979596596Santon 
11079596596Santon 			n = read(rp, buf, sizeof(buf));
11179596596Santon 			if (n == -1)
11279596596Santon 				err(1, "[p] read");
11379596596Santon 			if (n != sizeof(buf))
11479596596Santon 				errx(1, "[p] read: %ld < %zu", n, sizeof(buf));
11579596596Santon 			if (strcmp(pong, buf))
11679596596Santon 				errx(1, "[p] read: %s != %s\n", pong, buf);
11779596596Santon 
11879596596Santon 			if (--nrounds == 0)
11979596596Santon 				break;
12079596596Santon 		}
12179596596Santon 
12279596596Santon 		/* Signal shutdown to the child. */
12379596596Santon 		close(rp);
12479596596Santon 		close(wp);
12579596596Santon 
12679596596Santon 		return xwaitpid(pid);
12779596596Santon 	}
12879596596Santon 
12979596596Santon 	return 0;
13079596596Santon }
131