1a8eb96d5SAlan Somers /*-
2a8eb96d5SAlan Somers  * Copyright (c) 2014 Spectra Logic Corporation. All rights reserved.
3a8eb96d5SAlan Somers  * Redistribution and use in source and binary forms, with or without
4a8eb96d5SAlan Somers  * modification, are permitted provided that the following conditions
5a8eb96d5SAlan Somers  * are met:
6a8eb96d5SAlan Somers  * 1. Redistributions of source code must retain the above copyright
7a8eb96d5SAlan Somers  *    notice, this list of conditions and the following disclaimer.
8a8eb96d5SAlan Somers  * 2. Redistributions in binary form must reproduce the above copyright
9a8eb96d5SAlan Somers  *    notice, this list of conditions and the following disclaimer in the
10a8eb96d5SAlan Somers  *    documentation and/or other materials provided with the distribution.
11a8eb96d5SAlan Somers  *
12a8eb96d5SAlan Somers  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13a8eb96d5SAlan Somers  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14a8eb96d5SAlan Somers  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15a8eb96d5SAlan Somers  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
16a8eb96d5SAlan Somers  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17a8eb96d5SAlan Somers  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18a8eb96d5SAlan Somers  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19a8eb96d5SAlan Somers  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20a8eb96d5SAlan Somers  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21a8eb96d5SAlan Somers  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22a8eb96d5SAlan Somers  * SUCH DAMAGE.
23a8eb96d5SAlan Somers  */
24a8eb96d5SAlan Somers 
25a8eb96d5SAlan Somers #include <sys/cdefs.h>
26a8eb96d5SAlan Somers __FBSDID("$FreeBSD$");
27a8eb96d5SAlan Somers 
28a8eb96d5SAlan Somers #include <errno.h>
29a8eb96d5SAlan Somers #include <fcntl.h>
30a8eb96d5SAlan Somers #include <pthread.h>
31a8eb96d5SAlan Somers #include <signal.h>
32a8eb96d5SAlan Somers #include <sys/socket.h>
33a8eb96d5SAlan Somers #include <sys/un.h>
34a8eb96d5SAlan Somers 
35a8eb96d5SAlan Somers #include <stdio.h>
36a8eb96d5SAlan Somers 
37a8eb96d5SAlan Somers #include <atf-c.h>
38a8eb96d5SAlan Somers 
39a8eb96d5SAlan Somers /*
40a8eb96d5SAlan Somers  * Helper functions
41a8eb96d5SAlan Somers  */
42a8eb96d5SAlan Somers 
43a8eb96d5SAlan Somers #define MIN(x, y)	((x) < (y) ? (x) : (y))
44a8eb96d5SAlan Somers #define MAX(x, y)	((x) > (y) ? (x) : (y))
45a8eb96d5SAlan Somers 
465d5b721aSAlan Somers static void
47a8eb96d5SAlan Somers do_socketpair(int *sv)
48a8eb96d5SAlan Somers {
49a8eb96d5SAlan Somers 	int s;
50a8eb96d5SAlan Somers 
51a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
52a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
53a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] >= 0);
54a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[1] >= 0);
55a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] != sv[1]);
56a8eb96d5SAlan Somers }
57a8eb96d5SAlan Somers 
585d5b721aSAlan Somers static void
59a8eb96d5SAlan Somers do_socketpair_nonblocking(int *sv)
60a8eb96d5SAlan Somers {
61a8eb96d5SAlan Somers 	int s;
62a8eb96d5SAlan Somers 
63a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
64a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
65a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] >= 0);
66a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[1] >= 0);
67a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] != sv[1]);
68a8eb96d5SAlan Somers 	ATF_REQUIRE(-1 != fcntl(sv[0], F_SETFL, O_NONBLOCK));
69a8eb96d5SAlan Somers 	ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK));
70a8eb96d5SAlan Somers }
71a8eb96d5SAlan Somers 
72a8eb96d5SAlan Somers /*
73a8eb96d5SAlan Somers  * Returns a pair of sockets made the hard way: bind, listen, connect & accept
74a8eb96d5SAlan Somers  * @return	const char* The path to the socket
75a8eb96d5SAlan Somers  */
765d5b721aSAlan Somers static const char*
77a8eb96d5SAlan Somers mk_pair_of_sockets(int *sv)
78a8eb96d5SAlan Somers {
79a8eb96d5SAlan Somers 	struct sockaddr_un sun;
80a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
81a8eb96d5SAlan Somers 	const char *path = "sock";
82a8eb96d5SAlan Somers 	int s, err, s2, s1;
83a8eb96d5SAlan Somers 
84a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
85a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
86a8eb96d5SAlan Somers 
87a8eb96d5SAlan Somers 	bzero(&sun, sizeof(sun));
88a8eb96d5SAlan Somers 	sun.sun_family = AF_LOCAL;
89a8eb96d5SAlan Somers 	sun.sun_len = sizeof(sun);
90a8eb96d5SAlan Somers 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
91a8eb96d5SAlan Somers 	err = bind(s, (struct sockaddr *)&sun, sizeof(sun));
92a8eb96d5SAlan Somers 	err = listen(s, -1);
93a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, err);
94a8eb96d5SAlan Somers 
95a8eb96d5SAlan Somers 	/* Create the other socket */
96a8eb96d5SAlan Somers 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
97a8eb96d5SAlan Somers 	ATF_REQUIRE(s2 >= 0);
98a8eb96d5SAlan Somers 	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
99a8eb96d5SAlan Somers 	if (err != 0) {
100a8eb96d5SAlan Somers 		perror("connect");
101a8eb96d5SAlan Somers 		atf_tc_fail("connect(2) failed");
102a8eb96d5SAlan Somers 	}
103a8eb96d5SAlan Somers 
104a8eb96d5SAlan Somers 	/* Accept it */
105a8eb96d5SAlan Somers 	s1 = accept(s, NULL, NULL);
106a8eb96d5SAlan Somers 	if (s1 == -1) {
107a8eb96d5SAlan Somers 		perror("accept");
108a8eb96d5SAlan Somers 		atf_tc_fail("accept(2) failed");
109a8eb96d5SAlan Somers 	}
110a8eb96d5SAlan Somers 
111a8eb96d5SAlan Somers 	sv[0] = s1;
112a8eb96d5SAlan Somers 	sv[1] = s2;
113e594026dSAlan Somers 
114e594026dSAlan Somers 	close(s);
115e594026dSAlan Somers 
116a8eb96d5SAlan Somers 	return (path);
117a8eb96d5SAlan Somers }
118a8eb96d5SAlan Somers 
119a8eb96d5SAlan Somers static volatile sig_atomic_t got_sigpipe = 0;
120a8eb96d5SAlan Somers static void
1215d5b721aSAlan Somers shutdown_send_sigpipe_handler(int __unused x)
122a8eb96d5SAlan Somers {
123a8eb96d5SAlan Somers 	got_sigpipe = 1;
124a8eb96d5SAlan Somers }
125a8eb96d5SAlan Somers 
126a8eb96d5SAlan Somers /*
127a8eb96d5SAlan Somers  * Parameterized test function bodies
128a8eb96d5SAlan Somers  */
1295d5b721aSAlan Somers static void
130a8eb96d5SAlan Somers test_eagain(size_t sndbufsize, size_t rcvbufsize)
131a8eb96d5SAlan Somers {
132a8eb96d5SAlan Somers 	int i;
133a8eb96d5SAlan Somers 	int sv[2];
134a8eb96d5SAlan Somers 	const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
135a8eb96d5SAlan Somers 	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
1365d5b721aSAlan Somers 	const int numpkts = totalsize / pktsize;
137a8eb96d5SAlan Somers 	char sndbuf[pktsize];
1385d5b721aSAlan Somers 	ssize_t ssize;
139a8eb96d5SAlan Somers 
140a8eb96d5SAlan Somers 	/* setup the socket pair */
141b9a9db10SAlan Somers 	do_socketpair_nonblocking(sv);
142a8eb96d5SAlan Somers 	/* Setup the buffers */
143a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
144a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
145a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
146a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
147a8eb96d5SAlan Somers 
148a8eb96d5SAlan Somers 	bzero(sndbuf, pktsize);
149a8eb96d5SAlan Somers 	/* Send data until we get EAGAIN */
1505d5b721aSAlan Somers 	for(i=0; i < numpkts; i++) {
151a8eb96d5SAlan Somers 		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
152a8eb96d5SAlan Somers 		if (ssize == -1) {
153e594026dSAlan Somers 			if (errno == EAGAIN) {
154e594026dSAlan Somers 				close(sv[0]);
155e594026dSAlan Somers 				close(sv[1]);
156a8eb96d5SAlan Somers 				atf_tc_pass();
157e594026dSAlan Somers 			}
158a8eb96d5SAlan Somers 			else {
159a8eb96d5SAlan Somers 				perror("send");
160a8eb96d5SAlan Somers 				atf_tc_fail("send returned < 0 but not EAGAIN");
161a8eb96d5SAlan Somers 			}
162a8eb96d5SAlan Somers 		}
163a8eb96d5SAlan Somers 	}
164a8eb96d5SAlan Somers 	atf_tc_fail("Never got EAGAIN");
165a8eb96d5SAlan Somers }
166a8eb96d5SAlan Somers 
1675d5b721aSAlan Somers static void
168a8eb96d5SAlan Somers test_sendrecv_symmetric_buffers(size_t bufsize, int blocking) {
169a8eb96d5SAlan Somers 	int s;
170a8eb96d5SAlan Somers 	int sv[2];
1715d5b721aSAlan Somers 	const ssize_t pktsize = bufsize / 2;
172a8eb96d5SAlan Somers 	char sndbuf[pktsize];
173a8eb96d5SAlan Somers 	char recv_buf[pktsize];
174a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
175a8eb96d5SAlan Somers 
176a8eb96d5SAlan Somers 	/* setup the socket pair */
177a8eb96d5SAlan Somers 	if (blocking)
178a8eb96d5SAlan Somers 		do_socketpair(sv);
179a8eb96d5SAlan Somers 	else
180a8eb96d5SAlan Somers 		do_socketpair_nonblocking(sv);
181a8eb96d5SAlan Somers 
182a8eb96d5SAlan Somers 	/* Setup the buffers */
183a8eb96d5SAlan Somers 	s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
184a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
185a8eb96d5SAlan Somers 	s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
186a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
187a8eb96d5SAlan Somers 
188a8eb96d5SAlan Somers 	/* Fill the send buffer */
189a8eb96d5SAlan Somers 	bzero(sndbuf, pktsize);
190a8eb96d5SAlan Somers 
191a8eb96d5SAlan Somers 	/* send and receive the packet */
192a8eb96d5SAlan Somers 	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
193a8eb96d5SAlan Somers 	if (ssize < 0) {
194a8eb96d5SAlan Somers 		perror("send");
195a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
196a8eb96d5SAlan Somers 	}
197a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
198a8eb96d5SAlan Somers 	    pktsize, ssize);
199a8eb96d5SAlan Somers 
200a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
201a8eb96d5SAlan Somers 	if (rsize < 0) {
202a8eb96d5SAlan Somers 		perror("recv");
203a8eb96d5SAlan Somers 		atf_tc_fail("recv returned < 0");
204a8eb96d5SAlan Somers 	}
205a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
206a8eb96d5SAlan Somers 	    pktsize, rsize);
207e594026dSAlan Somers 	close(sv[0]);
208e594026dSAlan Somers 	close(sv[1]);
209a8eb96d5SAlan Somers }
210a8eb96d5SAlan Somers 
2115d5b721aSAlan Somers static void
212a8eb96d5SAlan Somers test_pipe_simulator(size_t sndbufsize, size_t rcvbufsize)
213a8eb96d5SAlan Somers {
2145d5b721aSAlan Somers 	int num_sent, num_received;
215a8eb96d5SAlan Somers 	int sv[2];
2165d5b721aSAlan Somers 	const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
217a8eb96d5SAlan Somers 	int numpkts;
218a8eb96d5SAlan Somers 	char sndbuf[pktsize];
219a8eb96d5SAlan Somers 	char rcvbuf[pktsize];
220a8eb96d5SAlan Somers 	char comparebuf[pktsize];
221a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
222a8eb96d5SAlan Somers 	bool currently_sending = true;
223a8eb96d5SAlan Somers 
224a8eb96d5SAlan Somers 	/* setup the socket pair */
225a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
226a8eb96d5SAlan Somers 	/* Setup the buffers */
227a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
228a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
229a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
230a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
231a8eb96d5SAlan Somers 
232a8eb96d5SAlan Somers 	/* Send a total amount of data comfortably greater than the buffers */
233a8eb96d5SAlan Somers 	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
234a8eb96d5SAlan Somers 	for (num_sent=0, num_received=0;
235a8eb96d5SAlan Somers 	     num_sent < numpkts || num_received < numpkts; ) {
236a8eb96d5SAlan Somers 		if (currently_sending && num_sent < numpkts) {
237a8eb96d5SAlan Somers 			/* The simulated sending process */
238a8eb96d5SAlan Somers 			/* fill the buffer */
239a8eb96d5SAlan Somers 			memset(sndbuf, num_sent, pktsize);
240a8eb96d5SAlan Somers 			ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
241a8eb96d5SAlan Somers 			if (ssize < 0) {
242a8eb96d5SAlan Somers 				/*
243a8eb96d5SAlan Somers 				 * XXX: This is bug-compatible with the kernel.
244a8eb96d5SAlan Somers 				 * The kernel returns EMSGSIZE when it should
245a8eb96d5SAlan Somers 				 * return EAGAIN
246a8eb96d5SAlan Somers 				 */
247a8eb96d5SAlan Somers 				if (errno == EAGAIN || errno == EMSGSIZE)
248a8eb96d5SAlan Somers 					currently_sending = false;
249a8eb96d5SAlan Somers 				else {
250a8eb96d5SAlan Somers 					perror("send");
251a8eb96d5SAlan Somers 					atf_tc_fail("send failed");
252a8eb96d5SAlan Somers 				}
253a8eb96d5SAlan Somers 			} else  {
254a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(pktsize, ssize,
255a8eb96d5SAlan Somers 				    "expected %zd=send(...) but got %zd",
256a8eb96d5SAlan Somers 				    pktsize, ssize);
257a8eb96d5SAlan Somers 				num_sent++;
258a8eb96d5SAlan Somers 			}
259a8eb96d5SAlan Somers 		} else {
260a8eb96d5SAlan Somers 			/* The simulated receiving process */
261a8eb96d5SAlan Somers 			rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
262a8eb96d5SAlan Somers 			if (rsize < 0) {
263a8eb96d5SAlan Somers 				if (errno == EAGAIN) {
264a8eb96d5SAlan Somers 					currently_sending = true;
265a8eb96d5SAlan Somers 					ATF_REQUIRE_MSG(num_sent < numpkts,
266a8eb96d5SAlan Somers 					    "Packets were lost!");
267a8eb96d5SAlan Somers 				}
268a8eb96d5SAlan Somers 				else {
269a8eb96d5SAlan Somers 					perror("recv");
270a8eb96d5SAlan Somers 					atf_tc_fail("recv failed");
271a8eb96d5SAlan Somers 				}
272a8eb96d5SAlan Somers 			} else  {
273a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(pktsize, rsize,
274a8eb96d5SAlan Somers 				    "expected %zd=recv(...) but got %zd",
275a8eb96d5SAlan Somers 				    pktsize, rsize);
276a8eb96d5SAlan Somers 				memset(comparebuf, num_received, pktsize);
277a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
278a8eb96d5SAlan Somers 				    			   pktsize),
279a8eb96d5SAlan Somers 				    "Received data miscompare");
280a8eb96d5SAlan Somers 				num_received++;
281a8eb96d5SAlan Somers 			}
282a8eb96d5SAlan Somers 		}
283a8eb96d5SAlan Somers 	}
284e594026dSAlan Somers 	close(sv[0]);
285e594026dSAlan Somers 	close(sv[1]);
286a8eb96d5SAlan Somers }
287a8eb96d5SAlan Somers 
288a8eb96d5SAlan Somers typedef struct {
289a8eb96d5SAlan Somers 	ssize_t	pktsize;
290a8eb96d5SAlan Somers 	int	numpkts;
291a8eb96d5SAlan Somers 	int	so;
292a8eb96d5SAlan Somers } test_pipe_thread_data_t;
293a8eb96d5SAlan Somers 
294a8eb96d5SAlan Somers static void*
295a8eb96d5SAlan Somers test_pipe_writer(void* args)
296a8eb96d5SAlan Somers {
297a8eb96d5SAlan Somers 	test_pipe_thread_data_t* td = args;
298a8eb96d5SAlan Somers 	char sndbuf[td->pktsize];
299a8eb96d5SAlan Somers 	ssize_t ssize;
300a8eb96d5SAlan Somers 	int i;
301a8eb96d5SAlan Somers 
302a8eb96d5SAlan Somers 	for(i=0; i < td->numpkts; i++) {
303a8eb96d5SAlan Somers 			memset(sndbuf, i, td->pktsize);
304a8eb96d5SAlan Somers 			ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
305a8eb96d5SAlan Somers 			if (ssize < 0) {
306a8eb96d5SAlan Somers 				perror("send");
307a8eb96d5SAlan Somers 				atf_tc_fail("send returned < 0");
308a8eb96d5SAlan Somers 			}
309a8eb96d5SAlan Somers 			ATF_CHECK_EQ_MSG(td->pktsize, ssize,
310a8eb96d5SAlan Somers 			    		 "expected %zd=send(...) but got %zd",
311a8eb96d5SAlan Somers 			    		  td->pktsize, ssize);
312a8eb96d5SAlan Somers 	}
313a8eb96d5SAlan Somers 	return (0);
314a8eb96d5SAlan Somers }
315a8eb96d5SAlan Somers 
316a8eb96d5SAlan Somers static void*
317a8eb96d5SAlan Somers test_pipe_reader(void* args)
318a8eb96d5SAlan Somers {
319a8eb96d5SAlan Somers 	test_pipe_thread_data_t* td = args;
320a8eb96d5SAlan Somers 	char rcvbuf[td->pktsize];
321a8eb96d5SAlan Somers 	char comparebuf[td->pktsize];
322a8eb96d5SAlan Somers 	ssize_t rsize;
323a8eb96d5SAlan Somers 	int i, d;
324a8eb96d5SAlan Somers 
325a8eb96d5SAlan Somers 	for(i=0; i < td->numpkts; i++) {
326a8eb96d5SAlan Somers 		memset(comparebuf, i, td->pktsize);
327a8eb96d5SAlan Somers 		rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
328a8eb96d5SAlan Somers 		if (rsize < 0) {
329a8eb96d5SAlan Somers 			perror("recv");
330a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
331a8eb96d5SAlan Somers 		}
332a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(td->pktsize, rsize,
333a8eb96d5SAlan Somers 		    		 "expected %zd=send(...) but got %zd",
334a8eb96d5SAlan Somers 				 td->pktsize, rsize);
335a8eb96d5SAlan Somers 		d = memcmp(comparebuf, rcvbuf, td->pktsize);
336a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, d,
337a8eb96d5SAlan Somers 		    		 "Received data miscompare on packet %d", i);
338a8eb96d5SAlan Somers 	}
339a8eb96d5SAlan Somers 	return (0);
340a8eb96d5SAlan Somers }
341a8eb96d5SAlan Somers 
342a8eb96d5SAlan Somers 
3435d5b721aSAlan Somers static void
344a8eb96d5SAlan Somers test_pipe(size_t sndbufsize, size_t rcvbufsize)
345a8eb96d5SAlan Somers {
346a8eb96d5SAlan Somers 	test_pipe_thread_data_t writer_data, reader_data;
347a8eb96d5SAlan Somers 	pthread_t writer, reader;
348a8eb96d5SAlan Somers 	int sv[2];
349a8eb96d5SAlan Somers 	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
350a8eb96d5SAlan Somers 	int numpkts;
351a8eb96d5SAlan Somers 
352a8eb96d5SAlan Somers 	/* setup the socket pair */
353a8eb96d5SAlan Somers 	do_socketpair(sv);
354a8eb96d5SAlan Somers 	/* Setup the buffers */
355a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
356a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
357a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
358a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
359a8eb96d5SAlan Somers 
360a8eb96d5SAlan Somers 	/* Send a total amount of data comfortably greater than the buffers */
361a8eb96d5SAlan Somers 	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
362a8eb96d5SAlan Somers 
363a8eb96d5SAlan Somers 	/* Start the child threads */
364a8eb96d5SAlan Somers 	writer_data.pktsize = pktsize;
365a8eb96d5SAlan Somers 	writer_data.numpkts = numpkts;
366a8eb96d5SAlan Somers 	writer_data.so = sv[0];
367a8eb96d5SAlan Somers 	reader_data.pktsize = pktsize;
368a8eb96d5SAlan Somers 	reader_data.numpkts = numpkts;
369a8eb96d5SAlan Somers 	reader_data.so = sv[1];
370a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
371a8eb96d5SAlan Somers 	    				 (void*)&writer_data));
3728de34a88SAlan Somers 	/*
3738de34a88SAlan Somers 	 * Give the writer time to start writing, and hopefully block, before
3748de34a88SAlan Somers 	 * starting the reader.  This increases the likelihood of the test case
3758de34a88SAlan Somers 	 * failing due to PR kern/185812
3768de34a88SAlan Somers 	 */
3778de34a88SAlan Somers 	usleep(1000);
378a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
379a8eb96d5SAlan Somers 	    				 (void*)&reader_data));
380a8eb96d5SAlan Somers 
381a8eb96d5SAlan Somers 	/* Join the children */
382a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
383a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
384e594026dSAlan Somers 	close(sv[0]);
385e594026dSAlan Somers 	close(sv[1]);
386a8eb96d5SAlan Somers }
387a8eb96d5SAlan Somers 
388a8eb96d5SAlan Somers 
389a8eb96d5SAlan Somers /*
390a8eb96d5SAlan Somers  * Test Cases
391a8eb96d5SAlan Somers  */
392a8eb96d5SAlan Somers 
393a8eb96d5SAlan Somers /* Create a SEQPACKET socket */
394a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(create_socket);
395a8eb96d5SAlan Somers ATF_TC_BODY(create_socket, tc)
396a8eb96d5SAlan Somers {
397a8eb96d5SAlan Somers 	int s;
398a8eb96d5SAlan Somers 
399a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
4006addc01eSAlan Somers 	ATF_REQUIRE(s >= 0);
401e594026dSAlan Somers 	close(s);
402a8eb96d5SAlan Somers }
403a8eb96d5SAlan Somers 
404a8eb96d5SAlan Somers /* Create SEQPACKET sockets using socketpair(2) */
405a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(create_socketpair);
406a8eb96d5SAlan Somers ATF_TC_BODY(create_socketpair, tc)
407a8eb96d5SAlan Somers {
408a8eb96d5SAlan Somers 	int sv[2];
409a8eb96d5SAlan Somers 	int s;
410a8eb96d5SAlan Somers 
411a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
412a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, s);
413a8eb96d5SAlan Somers 	ATF_CHECK(sv[0] >= 0);
414a8eb96d5SAlan Somers 	ATF_CHECK(sv[1] >= 0);
415a8eb96d5SAlan Somers 	ATF_CHECK(sv[0] != sv[1]);
416e594026dSAlan Somers 	close(sv[0]);
417e594026dSAlan Somers 	close(sv[1]);
418a8eb96d5SAlan Somers }
419a8eb96d5SAlan Somers 
420a8eb96d5SAlan Somers /* Call listen(2) without first calling bind(2).  It should fail */
421a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(listen_unbound);
422a8eb96d5SAlan Somers ATF_TC_BODY(listen_unbound, tc)
423a8eb96d5SAlan Somers {
424a8eb96d5SAlan Somers 	int s, r;
425a8eb96d5SAlan Somers 
426a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
427a8eb96d5SAlan Somers 	ATF_REQUIRE(s > 0);
428a8eb96d5SAlan Somers 	r = listen(s, -1);
429a8eb96d5SAlan Somers 	/* expect listen to fail since we haven't called bind(2) */
430a8eb96d5SAlan Somers 	ATF_CHECK(r != 0);
431e594026dSAlan Somers 	close(s);
432a8eb96d5SAlan Somers }
433a8eb96d5SAlan Somers 
434a8eb96d5SAlan Somers /* Bind the socket to a file */
435a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(bind);
436a8eb96d5SAlan Somers ATF_TC_BODY(bind, tc)
437a8eb96d5SAlan Somers {
438a8eb96d5SAlan Somers 	struct sockaddr_un sun;
439a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
440a8eb96d5SAlan Somers 	const char *path = "sock";
441a8eb96d5SAlan Somers 	int s, r;
442a8eb96d5SAlan Somers 
443a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
444a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
445a8eb96d5SAlan Somers 
446a8eb96d5SAlan Somers 	bzero(&sun, sizeof(sun));
447a8eb96d5SAlan Somers 	sun.sun_family = AF_LOCAL;
448a8eb96d5SAlan Somers 	sun.sun_len = sizeof(sun);
449a8eb96d5SAlan Somers 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
450a8eb96d5SAlan Somers 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
451a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, r);
452e594026dSAlan Somers 	close(s);
453a8eb96d5SAlan Somers }
454a8eb96d5SAlan Somers 
455a8eb96d5SAlan Somers /* listen(2) a socket that is already bound(2) should succeed */
456a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(listen_bound);
457a8eb96d5SAlan Somers ATF_TC_BODY(listen_bound, tc)
458a8eb96d5SAlan Somers {
459a8eb96d5SAlan Somers 	struct sockaddr_un sun;
460a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
461a8eb96d5SAlan Somers 	const char *path = "sock";
462a8eb96d5SAlan Somers 	int s, r, l;
463a8eb96d5SAlan Somers 
464a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
465a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
466a8eb96d5SAlan Somers 
467a8eb96d5SAlan Somers 	bzero(&sun, sizeof(sun));
468a8eb96d5SAlan Somers 	sun.sun_family = AF_LOCAL;
469a8eb96d5SAlan Somers 	sun.sun_len = sizeof(sun);
470a8eb96d5SAlan Somers 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
471a8eb96d5SAlan Somers 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
472a8eb96d5SAlan Somers 	l = listen(s, -1);
473a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, r);
474a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, l);
475e594026dSAlan Somers 	close(s);
476a8eb96d5SAlan Somers }
477a8eb96d5SAlan Somers 
478a8eb96d5SAlan Somers /* connect(2) can make a connection */
479a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(connect);
480a8eb96d5SAlan Somers ATF_TC_BODY(connect, tc)
481a8eb96d5SAlan Somers {
482a8eb96d5SAlan Somers 	struct sockaddr_un sun;
483a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
484a8eb96d5SAlan Somers 	const char *path = "sock";
485a8eb96d5SAlan Somers 	int s, r, err, l, s2;
486a8eb96d5SAlan Somers 
487a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
488a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
489a8eb96d5SAlan Somers 
490a8eb96d5SAlan Somers 	bzero(&sun, sizeof(sun));
491a8eb96d5SAlan Somers 	sun.sun_family = AF_LOCAL;
492a8eb96d5SAlan Somers 	sun.sun_len = sizeof(sun);
493a8eb96d5SAlan Somers 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
494a8eb96d5SAlan Somers 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
495a8eb96d5SAlan Somers 	l = listen(s, -1);
496a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, r);
497a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, l);
498a8eb96d5SAlan Somers 
499a8eb96d5SAlan Somers 	/* Create the other socket */
500a8eb96d5SAlan Somers 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
501a8eb96d5SAlan Somers 	ATF_REQUIRE(s2 >= 0);
502a8eb96d5SAlan Somers 	err = connect(s2, (struct sockaddr*)&sun, sizeof(sun));
503a8eb96d5SAlan Somers 	if (err != 0) {
504a8eb96d5SAlan Somers 		perror("connect");
505a8eb96d5SAlan Somers 		atf_tc_fail("connect(2) failed");
506a8eb96d5SAlan Somers 	}
507e594026dSAlan Somers 	close(s);
508e594026dSAlan Somers 	close(s2);
509a8eb96d5SAlan Somers }
510a8eb96d5SAlan Somers 
511a8eb96d5SAlan Somers /* accept(2) can receive a connection */
512a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(accept);
513a8eb96d5SAlan Somers ATF_TC_BODY(accept, tc)
514a8eb96d5SAlan Somers {
515a8eb96d5SAlan Somers 	int sv[2];
516a8eb96d5SAlan Somers 
517a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
518e594026dSAlan Somers 	close(sv[0]);
519e594026dSAlan Somers 	close(sv[1]);
520a8eb96d5SAlan Somers }
521a8eb96d5SAlan Somers 
522a8eb96d5SAlan Somers 
523a8eb96d5SAlan Somers /* Set O_NONBLOCK on the socket */
524a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
525a8eb96d5SAlan Somers ATF_TC_BODY(fcntl_nonblock, tc)
526a8eb96d5SAlan Somers {
527a8eb96d5SAlan Somers 	int s;
528a8eb96d5SAlan Somers 
529a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
530a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
531a8eb96d5SAlan Somers 	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
532a8eb96d5SAlan Somers 		perror("fcntl");
533a8eb96d5SAlan Somers 		atf_tc_fail("fcntl failed");
534a8eb96d5SAlan Somers 	}
535e594026dSAlan Somers 	close(s);
536a8eb96d5SAlan Somers }
537a8eb96d5SAlan Somers 
538a8eb96d5SAlan Somers /* Resize the send and receive buffers */
539a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_buffers);
540a8eb96d5SAlan Somers ATF_TC_BODY(resize_buffers, tc)
541a8eb96d5SAlan Somers {
542a8eb96d5SAlan Somers 	int s;
543a8eb96d5SAlan Somers 	int sndbuf = 12345;
544a8eb96d5SAlan Somers 	int rcvbuf = 23456;
545a8eb96d5SAlan Somers 	int xs, xr;
546a8eb96d5SAlan Somers 	socklen_t sl = sizeof(xs);
547a8eb96d5SAlan Somers 
548a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
549a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
550a8eb96d5SAlan Somers 
551a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
552a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  |\n");
553a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
554a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
555a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d |\n", xs, xr);
556a8eb96d5SAlan Somers 
557a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
558a8eb96d5SAlan Somers 		perror("setsockopt");
559a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
560a8eb96d5SAlan Somers 	}
561a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
562a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
563a8eb96d5SAlan Somers 	printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
564a8eb96d5SAlan Somers 
565a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
566a8eb96d5SAlan Somers 		perror("setsockopt");
567a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
568a8eb96d5SAlan Somers 	}
569a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
570a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
571a8eb96d5SAlan Somers 	printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
572e594026dSAlan Somers 	close(s);
573a8eb96d5SAlan Somers }
574a8eb96d5SAlan Somers 
575a8eb96d5SAlan Somers /*
576a8eb96d5SAlan Somers  * Resize the send and receive buffers of a connected socketpair
577a8eb96d5SAlan Somers  * Print some useful debugging info too
578a8eb96d5SAlan Somers  */
579a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
580a8eb96d5SAlan Somers ATF_TC_BODY(resize_connected_buffers, tc)
581a8eb96d5SAlan Somers {
582a8eb96d5SAlan Somers 	int sv[2];
583a8eb96d5SAlan Somers 	int sndbuf = 12345;
584a8eb96d5SAlan Somers 	int rcvbuf = 23456;
585a8eb96d5SAlan Somers 	int err;
586a8eb96d5SAlan Somers 	int ls, lr, rs, rr;
587a8eb96d5SAlan Somers 	socklen_t sl = sizeof(ls);
588a8eb96d5SAlan Somers 
589a8eb96d5SAlan Somers 	/* setup the socket pair */
590a8eb96d5SAlan Somers 	do_socketpair(sv);
591a8eb96d5SAlan Somers 
592a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
593a8eb96d5SAlan Somers 	printf("                              | Left Socket       | Right Socket      |\n");
594a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | RCVBUF  |\n");
595a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
596a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
597a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
598a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
599a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d | %7d | %7d |\n",
600a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
601a8eb96d5SAlan Somers 
602a8eb96d5SAlan Somers 	/* Update one side's send buffer */
603a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
604a8eb96d5SAlan Somers 	if (err != 0){
605a8eb96d5SAlan Somers 		perror("setsockopt");
606a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
607a8eb96d5SAlan Somers 	}
608a8eb96d5SAlan Somers 
609a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
610a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
611a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
612a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
613a8eb96d5SAlan Somers 	printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
614a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
615a8eb96d5SAlan Somers 
616a8eb96d5SAlan Somers 	/* Update the same side's receive buffer */
617a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
618a8eb96d5SAlan Somers 	if (err != 0){
619a8eb96d5SAlan Somers 		perror("setsockopt");
620a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
621a8eb96d5SAlan Somers 	}
622a8eb96d5SAlan Somers 
623a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
624a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
625a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
626a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
627a8eb96d5SAlan Somers 	printf("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
628a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
629e594026dSAlan Somers 	close(sv[0]);
630e594026dSAlan Somers 	close(sv[1]);
631a8eb96d5SAlan Somers }
632a8eb96d5SAlan Somers 
633a8eb96d5SAlan Somers 
634a8eb96d5SAlan Somers /* send(2) and recv(2) a single short record */
635a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv);
636a8eb96d5SAlan Somers ATF_TC_BODY(send_recv, tc)
637a8eb96d5SAlan Somers {
638a8eb96d5SAlan Somers 	int sv[2];
639a8eb96d5SAlan Somers 	const int bufsize = 64;
640a8eb96d5SAlan Somers 	const char *data = "data";
641a8eb96d5SAlan Somers 	char recv_buf[bufsize];
6425d5b721aSAlan Somers 	ssize_t datalen;
643a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
644a8eb96d5SAlan Somers 
645a8eb96d5SAlan Somers 	/* setup the socket pair */
646a8eb96d5SAlan Somers 	do_socketpair(sv);
647a8eb96d5SAlan Somers 
648a8eb96d5SAlan Somers 	/* send and receive a small packet */
649a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
650a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
651a8eb96d5SAlan Somers 	if (ssize < 0) {
652a8eb96d5SAlan Somers 		perror("send");
653a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
654a8eb96d5SAlan Somers 	}
655a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
656a8eb96d5SAlan Somers 	    datalen, ssize);
657a8eb96d5SAlan Somers 
658a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
659a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
660e594026dSAlan Somers 	close(sv[0]);
661e594026dSAlan Somers 	close(sv[1]);
662a8eb96d5SAlan Somers }
663a8eb96d5SAlan Somers 
664a8eb96d5SAlan Somers /* sendto(2) and recvfrom(2) a single short record
665a8eb96d5SAlan Somers  * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
666a8eb96d5SAlan Somers  * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
667a8eb96d5SAlan Somers  *
668a8eb96d5SAlan Somers  * According to the same spec, not all protocols are required to provide the
669a8eb96d5SAlan Somers  * source addres in recvfrom(2).
670a8eb96d5SAlan Somers  */
671a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
672a8eb96d5SAlan Somers ATF_TC_BODY(sendto_recvfrom, tc)
673a8eb96d5SAlan Somers {
674a8eb96d5SAlan Somers 	const char* path;
675a8eb96d5SAlan Somers 	struct sockaddr_storage from;
676a8eb96d5SAlan Somers 	int sv[2];
677a8eb96d5SAlan Somers 	const int bufsize = 64;
678a8eb96d5SAlan Somers 	const char *data = "data";
679a8eb96d5SAlan Somers 	char recv_buf[bufsize];
6805d5b721aSAlan Somers 	ssize_t datalen;
681a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
682a8eb96d5SAlan Somers 	socklen_t fromlen;
683a8eb96d5SAlan Somers 
684a8eb96d5SAlan Somers 	/* setup the socket pair */
685a8eb96d5SAlan Somers 	path = mk_pair_of_sockets(sv);
686a8eb96d5SAlan Somers 
687a8eb96d5SAlan Somers 	/* send and receive a small packet */
688a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
689a8eb96d5SAlan Somers 	ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
690a8eb96d5SAlan Somers 	if (ssize < 0) {
691a8eb96d5SAlan Somers 		perror("send");
692a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
693a8eb96d5SAlan Somers 	}
694a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
695a8eb96d5SAlan Somers 	    datalen, ssize);
696a8eb96d5SAlan Somers 
697a8eb96d5SAlan Somers 	fromlen = sizeof(from);
698a8eb96d5SAlan Somers 	rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
699a8eb96d5SAlan Somers 	    (struct sockaddr*)&from, &fromlen);
700a8eb96d5SAlan Somers 	if (ssize < 0) {
701a8eb96d5SAlan Somers 		perror("recvfrom");
702a8eb96d5SAlan Somers 		atf_tc_fail("recvfrom returned < 0");
703a8eb96d5SAlan Somers 	}
704a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
705a8eb96d5SAlan Somers 
706a8eb96d5SAlan Somers 	/*
707a8eb96d5SAlan Somers 	 * FreeBSD does not currently provide the source address for SEQ_PACKET
708a8eb96d5SAlan Somers 	 * AF_UNIX sockets, and POSIX does not require it, so these two checks
709a8eb96d5SAlan Somers 	 * are disabled.  If FreeBSD gains that feature in the future, then
710a8eb96d5SAlan Somers 	 * these checks may be reenabled
711a8eb96d5SAlan Somers 	 */
712a8eb96d5SAlan Somers 	/* ATF_CHECK_EQ(PF_LOCAL, from.ss_family); */
713a8eb96d5SAlan Somers 	/* ATF_CHECK_STREQ(path, ((struct sockaddr_un*)&from)->sun_path); */
714e594026dSAlan Somers 	close(sv[0]);
715e594026dSAlan Somers 	close(sv[1]);
716a8eb96d5SAlan Somers }
717a8eb96d5SAlan Somers 
718a8eb96d5SAlan Somers /*
719a8eb96d5SAlan Somers  * send(2) and recv(2) a single short record with sockets created the
720a8eb96d5SAlan Somers  * traditional way, involving bind, listen, connect, and accept
721a8eb96d5SAlan Somers  */
722a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_with_connect);
723a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_with_connect, tc)
724a8eb96d5SAlan Somers {
725a8eb96d5SAlan Somers 	int sv[2];
726a8eb96d5SAlan Somers 	const int bufsize = 64;
727a8eb96d5SAlan Somers 	const char *data = "data";
728a8eb96d5SAlan Somers 	char recv_buf[bufsize];
7295d5b721aSAlan Somers 	ssize_t datalen;
730a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
731a8eb96d5SAlan Somers 
732a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
733a8eb96d5SAlan Somers 
734a8eb96d5SAlan Somers 	/* send and receive a small packet */
735a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
736a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
737a8eb96d5SAlan Somers 	if (ssize < 0) {
738a8eb96d5SAlan Somers 		perror("send");
739a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
740a8eb96d5SAlan Somers 	}
741a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
742a8eb96d5SAlan Somers 	    datalen, ssize);
743a8eb96d5SAlan Somers 
744a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
745a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
746e594026dSAlan Somers 	close(sv[0]);
747e594026dSAlan Somers 	close(sv[1]);
748a8eb96d5SAlan Somers }
749a8eb96d5SAlan Somers 
750a8eb96d5SAlan Somers /* send(2) should fail on a shutdown socket */
751a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send);
752a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send, tc)
753a8eb96d5SAlan Somers {
754a8eb96d5SAlan Somers 	int s;
755e594026dSAlan Somers 	const char data[] = "data";
756a8eb96d5SAlan Somers 	ssize_t ssize;
757a8eb96d5SAlan Somers 
758a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
759e594026dSAlan Somers 	ATF_REQUIRE(s >= 0);
760a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
761a8eb96d5SAlan Somers 	/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
762a8eb96d5SAlan Somers 	ssize = send(s, data, sizeof(data), MSG_EOR | MSG_NOSIGNAL);
763a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EPIPE, errno);
764a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, ssize);
765e594026dSAlan Somers 	close(s);
766a8eb96d5SAlan Somers }
767a8eb96d5SAlan Somers 
768a8eb96d5SAlan Somers /* send(2) should cause SIGPIPE on a shutdown socket */
769a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
770a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send_sigpipe, tc)
771a8eb96d5SAlan Somers {
772a8eb96d5SAlan Somers 	int s;
773e594026dSAlan Somers 	const char data[] = "data";
774a8eb96d5SAlan Somers 	ssize_t ssize;
775a8eb96d5SAlan Somers 
776a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
777e594026dSAlan Somers 	ATF_REQUIRE(s >= 0);
778a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, shutdown(s, SHUT_RDWR));
779a8eb96d5SAlan Somers 	ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
780a8eb96d5SAlan Somers 	ssize = send(s, data, sizeof(data), MSG_EOR);
781a8eb96d5SAlan Somers 	ATF_CHECK_EQ(1, got_sigpipe);
782e594026dSAlan Somers 	close(s);
783a8eb96d5SAlan Somers }
784a8eb96d5SAlan Somers 
785a8eb96d5SAlan Somers /* nonblocking send(2) and recv(2) a single short record */
786a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
787a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_nonblocking, tc)
788a8eb96d5SAlan Somers {
789a8eb96d5SAlan Somers 	int sv[2];
790a8eb96d5SAlan Somers 	const int bufsize = 64;
791a8eb96d5SAlan Somers 	const char *data = "data";
792a8eb96d5SAlan Somers 	char recv_buf[bufsize];
7935d5b721aSAlan Somers 	ssize_t datalen;
794a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
795a8eb96d5SAlan Somers 
796a8eb96d5SAlan Somers 	/* setup the socket pair */
797a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
798a8eb96d5SAlan Somers 
799a8eb96d5SAlan Somers 	/* Verify that there is nothing to receive */
800a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
801a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
802a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
803a8eb96d5SAlan Somers 
804a8eb96d5SAlan Somers 	/* send and receive a small packet */
805a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
806a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
807a8eb96d5SAlan Somers 	if (ssize < 0) {
808a8eb96d5SAlan Somers 		perror("send");
809a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
810a8eb96d5SAlan Somers 	}
811a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
812a8eb96d5SAlan Somers 	    datalen, ssize);
813a8eb96d5SAlan Somers 
814a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
815a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
816e594026dSAlan Somers 	close(sv[0]);
817e594026dSAlan Somers 	close(sv[1]);
818a8eb96d5SAlan Somers }
819a8eb96d5SAlan Somers 
820a8eb96d5SAlan Somers /*
821a8eb96d5SAlan Somers  * We should get EMSGSIZE if we try to send a message larger than the socket
822a8eb96d5SAlan Somers  * buffer, with blocking sockets
823a8eb96d5SAlan Somers  */
824a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(emsgsize);
825a8eb96d5SAlan Somers ATF_TC_BODY(emsgsize, tc)
826a8eb96d5SAlan Somers {
827a8eb96d5SAlan Somers 	int sv[2];
828a8eb96d5SAlan Somers 	const size_t sndbufsize = 8192;
829a8eb96d5SAlan Somers 	const size_t rcvbufsize = 8192;
830a8eb96d5SAlan Somers 	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
831a8eb96d5SAlan Somers 	char sndbuf[pktsize];
8325d5b721aSAlan Somers 	ssize_t ssize;
833a8eb96d5SAlan Somers 
834a8eb96d5SAlan Somers 	/* setup the socket pair */
835a8eb96d5SAlan Somers 	do_socketpair(sv);
836a8eb96d5SAlan Somers 	/* Setup the buffers */
837a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
838a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
839a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
840a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
841a8eb96d5SAlan Somers 
842a8eb96d5SAlan Somers 	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
843a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EMSGSIZE, errno);
844a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, ssize);
845e594026dSAlan Somers 	close(sv[0]);
846e594026dSAlan Somers 	close(sv[1]);
847a8eb96d5SAlan Somers }
848a8eb96d5SAlan Somers 
849a8eb96d5SAlan Somers /*
850a8eb96d5SAlan Somers  * We should get EMSGSIZE if we try to send a message larger than the socket
851a8eb96d5SAlan Somers  * buffer, with nonblocking sockets
852a8eb96d5SAlan Somers  */
853a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(emsgsize_nonblocking);
854a8eb96d5SAlan Somers ATF_TC_BODY(emsgsize_nonblocking, tc)
855a8eb96d5SAlan Somers {
856a8eb96d5SAlan Somers 	int sv[2];
857a8eb96d5SAlan Somers 	const size_t sndbufsize = 8192;
858a8eb96d5SAlan Somers 	const size_t rcvbufsize = 8192;
859a8eb96d5SAlan Somers 	const size_t pktsize = (sndbufsize + rcvbufsize) * 2;
860a8eb96d5SAlan Somers 	char sndbuf[pktsize];
8615d5b721aSAlan Somers 	ssize_t ssize;
862a8eb96d5SAlan Somers 
863a8eb96d5SAlan Somers 	/* setup the socket pair */
864a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
865a8eb96d5SAlan Somers 	/* Setup the buffers */
866a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
867a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
868a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
869a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
870a8eb96d5SAlan Somers 
871a8eb96d5SAlan Somers 	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
872a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EMSGSIZE, errno);
873a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, ssize);
874e594026dSAlan Somers 	close(sv[0]);
875e594026dSAlan Somers 	close(sv[1]);
876a8eb96d5SAlan Somers }
877a8eb96d5SAlan Somers 
878a8eb96d5SAlan Somers 
879a8eb96d5SAlan Somers /*
880a8eb96d5SAlan Somers  * We should get EAGAIN if we try to send a message larger than the socket
881a8eb96d5SAlan Somers  * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
882a8eb96d5SAlan Somers  */
883a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
884a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_8k, tc)
885a8eb96d5SAlan Somers {
886a8eb96d5SAlan Somers 	test_eagain(8192, 8192);
887a8eb96d5SAlan Somers }
888a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
889a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_128k, tc)
890a8eb96d5SAlan Somers {
891a8eb96d5SAlan Somers 	test_eagain(8192, 131072);
892a8eb96d5SAlan Somers }
893a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
894a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_8k, tc)
895a8eb96d5SAlan Somers {
896a8eb96d5SAlan Somers 	test_eagain(131072, 8192);
897a8eb96d5SAlan Somers }
898a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
899a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_128k, tc)
900a8eb96d5SAlan Somers {
901a8eb96d5SAlan Somers 	test_eagain(131072, 131072);
902a8eb96d5SAlan Somers }
903a8eb96d5SAlan Somers 
904a8eb96d5SAlan Somers 
905a8eb96d5SAlan Somers /*
906a8eb96d5SAlan Somers  * nonblocking send(2) and recv(2) of several records, which should collectively
907a8eb96d5SAlan Somers  * fill up the send buffer but not the receive buffer
908a8eb96d5SAlan Somers  */
909a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
910a8eb96d5SAlan Somers ATF_TC_BODY(rcvbuf_oversized, tc)
911a8eb96d5SAlan Somers {
9125d5b721aSAlan Somers 	int i;
913a8eb96d5SAlan Somers 	int sv[2];
9143be7751dSJulio Merino 	const ssize_t pktsize = 1024;
915a8eb96d5SAlan Somers 	const size_t sndbufsize = 8192;
916a8eb96d5SAlan Somers 	const size_t rcvbufsize = 131072;
9175d5b721aSAlan Somers 	const size_t geometric_mean_bufsize = 32768;
9185d5b721aSAlan Somers 	const int numpkts = geometric_mean_bufsize / pktsize;
919a8eb96d5SAlan Somers 	char sndbuf[pktsize];
920a8eb96d5SAlan Somers 	char recv_buf[pktsize];
921a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
922a8eb96d5SAlan Somers 
923a8eb96d5SAlan Somers 	/* setup the socket pair */
924a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
9255d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
9265d5b721aSAlan Somers 	    sizeof(sndbufsize)));
9275d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
9285d5b721aSAlan Somers 	    sizeof(rcvbufsize)));
929a8eb96d5SAlan Somers 
930a8eb96d5SAlan Somers 	/*
931a8eb96d5SAlan Somers 	 * Send and receive packets that are collectively greater than the send
932a8eb96d5SAlan Somers 	 * buffer, but less than the receive buffer
933a8eb96d5SAlan Somers 	 */
9345d5b721aSAlan Somers 	for (i=0; i < numpkts; i++) {
935a8eb96d5SAlan Somers 		/* Fill the buffer */
936a8eb96d5SAlan Somers 		memset(sndbuf, i, pktsize);
937a8eb96d5SAlan Somers 
938a8eb96d5SAlan Somers 		/* send the packet */
939a8eb96d5SAlan Somers 		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
940a8eb96d5SAlan Somers 		if (ssize < 0) {
941a8eb96d5SAlan Somers 			perror("send");
942a8eb96d5SAlan Somers 			atf_tc_fail("send returned < 0");
943a8eb96d5SAlan Somers 		}
944a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, ssize,
945a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, ssize);
946a8eb96d5SAlan Somers 
947a8eb96d5SAlan Somers 		/* Receive it */
948a8eb96d5SAlan Somers 
949a8eb96d5SAlan Somers 		rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
950a8eb96d5SAlan Somers 		if (rsize < 0) {
951a8eb96d5SAlan Somers 			perror("recv");
952a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
953a8eb96d5SAlan Somers 		}
954a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, rsize,
955a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, rsize);
956a8eb96d5SAlan Somers 
957a8eb96d5SAlan Somers 		/* Verify the contents */
958a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
959a8eb96d5SAlan Somers 		    "Received data miscompare");
960a8eb96d5SAlan Somers 	}
961a8eb96d5SAlan Somers 
962a8eb96d5SAlan Somers 	/* Trying to receive again should return EAGAIN */
963a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
964a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
965a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
966e594026dSAlan Somers 	close(sv[0]);
967e594026dSAlan Somers 	close(sv[1]);
968a8eb96d5SAlan Somers }
969a8eb96d5SAlan Somers 
970a8eb96d5SAlan Somers /*
971a8eb96d5SAlan Somers  * Simulate the behavior of a blocking pipe.  The sender will send until his
972a8eb96d5SAlan Somers  * buffer fills up, then we'll simulate a scheduler switch that will allow the
973a8eb96d5SAlan Somers  * receiver to read until his buffer empties.  Repeat the process until the
974a8eb96d5SAlan Somers  * transfer is complete.
975a8eb96d5SAlan Somers  * Repeat the test with multiple send and receive buffer sizes
976a8eb96d5SAlan Somers  */
977a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
978a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_8k, tc)
979a8eb96d5SAlan Somers {
980a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 8192);
981a8eb96d5SAlan Somers }
982a8eb96d5SAlan Somers 
983a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
984a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_128k, tc)
985a8eb96d5SAlan Somers {
986a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 131072);
987a8eb96d5SAlan Somers }
988a8eb96d5SAlan Somers 
989a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
990a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_8k, tc)
991a8eb96d5SAlan Somers {
992a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 8192);
993a8eb96d5SAlan Somers }
994a8eb96d5SAlan Somers 
995a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
996a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_128k, tc)
997a8eb96d5SAlan Somers {
998a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 131072);
999a8eb96d5SAlan Somers }
1000a8eb96d5SAlan Somers 
1001a8eb96d5SAlan Somers /*
1002a8eb96d5SAlan Somers  * Test blocking I/O by passing data between two threads.  The total amount of
1003a8eb96d5SAlan Somers  * data will be >> buffer size to force blocking.  Repeat the test with multiple
1004a8eb96d5SAlan Somers  * send and receive buffer sizes
1005a8eb96d5SAlan Somers  */
1006a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_8k);
1007a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_8k, tc)
1008a8eb96d5SAlan Somers {
1009a8eb96d5SAlan Somers 	test_pipe(8192, 8192);
1010a8eb96d5SAlan Somers }
1011a8eb96d5SAlan Somers 
1012a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_128k);
1013a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_128k, tc)
1014a8eb96d5SAlan Somers {
1015a8eb96d5SAlan Somers 	test_pipe(8192, 131072);
1016a8eb96d5SAlan Somers }
1017a8eb96d5SAlan Somers 
1018a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_8k);
1019a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_8k, tc)
1020a8eb96d5SAlan Somers {
1021a8eb96d5SAlan Somers 	test_pipe(131072, 8192);
1022a8eb96d5SAlan Somers }
1023a8eb96d5SAlan Somers 
1024a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_128k);
1025a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_128k, tc)
1026a8eb96d5SAlan Somers {
1027a8eb96d5SAlan Somers 	test_pipe(131072, 131072);
1028a8eb96d5SAlan Somers }
1029a8eb96d5SAlan Somers 
1030a8eb96d5SAlan Somers 
1031a8eb96d5SAlan Somers /*
1032a8eb96d5SAlan Somers  * Test single-packet I/O with and without blocking, with symmetric buffers of
1033a8eb96d5SAlan Somers  * various sizes
1034a8eb96d5SAlan Somers  */
1035a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k);
1036a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k, tc)
1037a8eb96d5SAlan Somers {
1038a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, true);
1039a8eb96d5SAlan Somers }
1040a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k);
1041a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k, tc)
1042a8eb96d5SAlan Somers {
1043a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, true);
1044a8eb96d5SAlan Somers }
1045a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k);
1046a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k, tc)
1047a8eb96d5SAlan Somers {
1048a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, true);
1049a8eb96d5SAlan Somers }
1050a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k);
1051a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k, tc)
1052a8eb96d5SAlan Somers {
1053a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, true);
1054a8eb96d5SAlan Somers }
1055a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k);
1056a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k, tc)
1057a8eb96d5SAlan Somers {
1058a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, true);
1059a8eb96d5SAlan Somers }
1060a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1061a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1062a8eb96d5SAlan Somers {
1063a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, false);
1064a8eb96d5SAlan Somers }
1065a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1066a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1067a8eb96d5SAlan Somers {
1068a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, false);
1069a8eb96d5SAlan Somers }
1070a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1071a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1072a8eb96d5SAlan Somers {
1073a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, false);
1074a8eb96d5SAlan Somers }
1075a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1076a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1077a8eb96d5SAlan Somers {
1078a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, false);
1079a8eb96d5SAlan Somers }
1080a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1081a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1082a8eb96d5SAlan Somers {
1083a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, false);
1084a8eb96d5SAlan Somers }
1085a8eb96d5SAlan Somers 
1086a8eb96d5SAlan Somers 
1087a8eb96d5SAlan Somers /*
1088a8eb96d5SAlan Somers  * Main.
1089a8eb96d5SAlan Somers  */
1090a8eb96d5SAlan Somers 
1091a8eb96d5SAlan Somers ATF_TP_ADD_TCS(tp)
1092a8eb96d5SAlan Somers {
1093a8eb96d5SAlan Somers 	/* Basic creation and connection tests */
1094a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socket);
1095a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socketpair);
1096a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_unbound);
1097a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, bind);
1098a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_bound);
1099a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, connect);
1100a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, accept);
1101a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, fcntl_nonblock);
1102a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_buffers);
1103a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_connected_buffers);
1104a8eb96d5SAlan Somers 
1105a8eb96d5SAlan Somers 	/* Unthreaded I/O tests */
1106a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv);
1107a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1108a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_with_connect);
1109a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendto_recvfrom);
1110a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send);
1111a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1112a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, emsgsize);
1113a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, emsgsize_nonblocking);
1114a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_8k);
1115a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_128k);
1116a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_8k);
1117a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_128k);
1118a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k);
1119a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k);
1120a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k);
1121a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k);
1122a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k);
1123a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1124a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1125a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1126a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1127a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1128a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1129a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1130a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1131a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1132a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1133a8eb96d5SAlan Somers 
1134a8eb96d5SAlan Somers 	/* Threaded I/O tests with blocking sockets */
1135a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_8k);
1136a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_128k);
1137a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_8k);
1138a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_128k);
1139a8eb96d5SAlan Somers 
1140a8eb96d5SAlan Somers 	return atf_no_error();
1141a8eb96d5SAlan Somers }
1142