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