1 /* $OpenBSD: test-ping-pong.c,v 1.2 2021/10/22 05:03:57 anton Exp $ */ 2 3 /* 4 * Copyright (c) 2019 Anton Lindqvist <anton@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <err.h> 20 #include <errno.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include <unistd.h> 24 25 #include "pipe.h" 26 27 /* 28 * Basic read/write test invovling two processes, P1 and P2. P1 writes "ping" on 29 * the pipe which is received and verified by P2. P2 writes "pong" as a reply 30 * which is received and verified P1. After N rounds, P1 closes the pipe and 31 * SIGPIPE is expected to be delivered to P2. 32 */ 33 int 34 test_ping_pong(void) 35 { 36 const char ping[] = "ping"; 37 const char pong[] = "pong"; 38 char buf[5]; 39 int pip[2][2], rp, wp; 40 int nrounds = 10; 41 ssize_t n; 42 pid_t pid; 43 44 if (pipe(pip[0]) == -1) 45 err(1, "pipe"); 46 if (pipe(pip[1]) == -1) 47 err(1, "pipe"); 48 49 pid = fork(); 50 if (pid == -1) 51 err(1, "fork"); 52 if (pid == 0) { 53 rp = pip[0][0]; 54 close(pip[0][1]); 55 56 wp = pip[1][1]; 57 close(pip[1][0]); 58 59 for (;;) { 60 n = read(rp, buf, sizeof(buf)); 61 if (n == -1) 62 err(1, "[c] read"); 63 if (n == 0) 64 break; 65 if (n != sizeof(buf)) 66 errx(1, "[c] read: %ld < %zu", n, sizeof(buf)); 67 if (strcmp(ping, buf)) 68 errx(1, "[c] read: %s != %s\n", ping, buf); 69 70 n = write(wp, pong, sizeof(pong)); 71 if (n == -1) 72 err(1, "[c] write"); 73 if (n != sizeof(pong)) 74 errx(1, "[c] write: %ld < %zu", 75 n, sizeof(pong)); 76 77 nrounds--; 78 } 79 if (nrounds != 0) 80 errx(1, "[c] nrounds: %d > 0", nrounds); 81 82 /* 83 * Writing on the pipe must cause delivery of SIGPIPE at this 84 * point since the read end is gone. 85 */ 86 n = write(wp, pong, sizeof(pong)); 87 if (n != -1) 88 errx(1, "[c] write: %ld != -1", n); 89 else if (errno != EPIPE) 90 errx(1, "[c] write: %d != %d", errno, EPIPE); 91 else if (!gotsigpipe) 92 errx(1, "[c] write: no SIGPIPE"); 93 94 _exit(0); 95 } else { 96 rp = pip[1][0]; 97 close(pip[1][1]); 98 99 wp = pip[0][1]; 100 close(pip[0][0]); 101 102 for (;;) { 103 n = write(wp, ping, sizeof(ping)); 104 if (n == -1) 105 err(1, "[p] write"); 106 if (n != sizeof(ping)) 107 errx(1, "[p] write: %ld < %zu", 108 n, sizeof(ping)); 109 110 n = read(rp, buf, sizeof(buf)); 111 if (n == -1) 112 err(1, "[p] read"); 113 if (n != sizeof(buf)) 114 errx(1, "[p] read: %ld < %zu", n, sizeof(buf)); 115 if (strcmp(pong, buf)) 116 errx(1, "[p] read: %s != %s\n", pong, buf); 117 118 if (--nrounds == 0) 119 break; 120 } 121 122 /* Signal shutdown to the child. */ 123 close(rp); 124 close(wp); 125 126 return xwaitpid(pid); 127 } 128 129 return 0; 130 } 131