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 #include <errno.h>
27a8eb96d5SAlan Somers #include <fcntl.h>
28a8eb96d5SAlan Somers #include <pthread.h>
29a8eb96d5SAlan Somers #include <signal.h>
30a8eb96d5SAlan Somers #include <sys/socket.h>
31a8eb96d5SAlan Somers #include <sys/un.h>
32a8eb96d5SAlan Somers 
33a8eb96d5SAlan Somers #include <stdio.h>
34a8eb96d5SAlan Somers 
35a8eb96d5SAlan Somers #include <atf-c.h>
36a8eb96d5SAlan Somers 
37a8eb96d5SAlan Somers /*
38a8eb96d5SAlan Somers  * Helper functions
39a8eb96d5SAlan Somers  */
40a8eb96d5SAlan Somers 
41a8eb96d5SAlan Somers #define MIN(x, y)	((x) < (y) ? (x) : (y))
42a8eb96d5SAlan Somers #define MAX(x, y)	((x) > (y) ? (x) : (y))
43a8eb96d5SAlan Somers 
445d5b721aSAlan Somers static void
45a8eb96d5SAlan Somers do_socketpair(int *sv)
46a8eb96d5SAlan Somers {
47a8eb96d5SAlan Somers 	int s;
48a8eb96d5SAlan Somers 
49a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
50a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
51a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] >= 0);
52a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[1] >= 0);
53a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] != sv[1]);
54a8eb96d5SAlan Somers }
55a8eb96d5SAlan Somers 
565d5b721aSAlan Somers static void
57a8eb96d5SAlan Somers do_socketpair_nonblocking(int *sv)
58a8eb96d5SAlan Somers {
59a8eb96d5SAlan Somers 	int s;
60a8eb96d5SAlan Somers 
61a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
62a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
63a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] >= 0);
64a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[1] >= 0);
65a8eb96d5SAlan Somers 	ATF_REQUIRE(sv[0] != sv[1]);
66a8eb96d5SAlan Somers 	ATF_REQUIRE(-1 != fcntl(sv[0], F_SETFL, O_NONBLOCK));
67a8eb96d5SAlan Somers 	ATF_REQUIRE(-1 != fcntl(sv[1], F_SETFL, O_NONBLOCK));
68a8eb96d5SAlan Somers }
69a8eb96d5SAlan Somers 
70a8eb96d5SAlan Somers /*
711f46c32cSGleb Smirnoff  * Returns a bound and listening socket.
72a8eb96d5SAlan Somers  * @return	const char* The path to the socket
73a8eb96d5SAlan Somers  */
741f46c32cSGleb Smirnoff static const struct sockaddr_un *
751f46c32cSGleb Smirnoff mk_listening_socket(int *sv)
76a8eb96d5SAlan Somers {
77a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
781f46c32cSGleb Smirnoff 	static const struct sockaddr_un sun = {
791f46c32cSGleb Smirnoff 		.sun_family = AF_LOCAL,
801f46c32cSGleb Smirnoff 		.sun_len = sizeof(sun),
811f46c32cSGleb Smirnoff 		.sun_path = "sock",
821f46c32cSGleb Smirnoff 	};
831f46c32cSGleb Smirnoff 	int s, r, l;
84a8eb96d5SAlan Somers 
85a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
86a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
87a8eb96d5SAlan Somers 
881f46c32cSGleb Smirnoff 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
891f46c32cSGleb Smirnoff 	l = listen(s, -1);
901f46c32cSGleb Smirnoff 	ATF_CHECK_EQ(0, r);
911f46c32cSGleb Smirnoff 	ATF_CHECK_EQ(0, l);
921f46c32cSGleb Smirnoff 
931f46c32cSGleb Smirnoff 	if (sv != NULL)
941f46c32cSGleb Smirnoff 		*sv = s;
951f46c32cSGleb Smirnoff 
961f46c32cSGleb Smirnoff 	return (&sun);
971f46c32cSGleb Smirnoff }
981f46c32cSGleb Smirnoff 
991f46c32cSGleb Smirnoff /*
1001f46c32cSGleb Smirnoff  * Returns a pair of sockets made the hard way: bind, listen, connect & accept
1011f46c32cSGleb Smirnoff  * @return	const char* The path to the socket
1021f46c32cSGleb Smirnoff  */
1031f46c32cSGleb Smirnoff static const struct sockaddr_un *
1041f46c32cSGleb Smirnoff mk_pair_of_sockets(int *sv)
1051f46c32cSGleb Smirnoff {
1061f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
1071f46c32cSGleb Smirnoff 	int s, s2, err, s1;
1081f46c32cSGleb Smirnoff 
1091f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
110a8eb96d5SAlan Somers 
111a8eb96d5SAlan Somers 	/* Create the other socket */
112a8eb96d5SAlan Somers 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
113a8eb96d5SAlan Somers 	ATF_REQUIRE(s2 >= 0);
1141f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
115a8eb96d5SAlan Somers 	if (err != 0) {
116a8eb96d5SAlan Somers 		perror("connect");
117a8eb96d5SAlan Somers 		atf_tc_fail("connect(2) failed");
118a8eb96d5SAlan Somers 	}
119a8eb96d5SAlan Somers 
120a8eb96d5SAlan Somers 	/* Accept it */
121a8eb96d5SAlan Somers 	s1 = accept(s, NULL, NULL);
122a8eb96d5SAlan Somers 	if (s1 == -1) {
123a8eb96d5SAlan Somers 		perror("accept");
124a8eb96d5SAlan Somers 		atf_tc_fail("accept(2) failed");
125a8eb96d5SAlan Somers 	}
126a8eb96d5SAlan Somers 
1271f46c32cSGleb Smirnoff 	if (sv != NULL) {
128a8eb96d5SAlan Somers 		sv[0] = s1;
129a8eb96d5SAlan Somers 		sv[1] = s2;
1301f46c32cSGleb Smirnoff 	}
131e594026dSAlan Somers 
132e594026dSAlan Somers 	close(s);
133e594026dSAlan Somers 
1341f46c32cSGleb Smirnoff 	return (sun);
135a8eb96d5SAlan Somers }
136a8eb96d5SAlan Somers 
137a8eb96d5SAlan Somers static volatile sig_atomic_t got_sigpipe = 0;
138a8eb96d5SAlan Somers static void
1395d5b721aSAlan Somers shutdown_send_sigpipe_handler(int __unused x)
140a8eb96d5SAlan Somers {
141a8eb96d5SAlan Somers 	got_sigpipe = 1;
142a8eb96d5SAlan Somers }
143a8eb96d5SAlan Somers 
144a8eb96d5SAlan Somers /*
145a8eb96d5SAlan Somers  * Parameterized test function bodies
146a8eb96d5SAlan Somers  */
1475d5b721aSAlan Somers static void
148ea703329SBrooks Davis test_eagain(int sndbufsize, int rcvbufsize)
149a8eb96d5SAlan Somers {
150a8eb96d5SAlan Somers 	int i;
151a8eb96d5SAlan Somers 	int sv[2];
152a8eb96d5SAlan Somers 	const size_t totalsize = (sndbufsize + rcvbufsize) * 2;
153a8eb96d5SAlan Somers 	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
1545d5b721aSAlan Somers 	const int numpkts = totalsize / pktsize;
155a8eb96d5SAlan Somers 	char sndbuf[pktsize];
1565d5b721aSAlan Somers 	ssize_t ssize;
157a8eb96d5SAlan Somers 
158a8eb96d5SAlan Somers 	/* setup the socket pair */
159b9a9db10SAlan Somers 	do_socketpair_nonblocking(sv);
160a8eb96d5SAlan Somers 	/* Setup the buffers */
161a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
162a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
163a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
164a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
165a8eb96d5SAlan Somers 
166a8eb96d5SAlan Somers 	bzero(sndbuf, pktsize);
167a8eb96d5SAlan Somers 	/* Send data until we get EAGAIN */
1685d5b721aSAlan Somers 	for(i=0; i < numpkts; i++) {
169a8eb96d5SAlan Somers 		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
170a8eb96d5SAlan Somers 		if (ssize == -1) {
171e594026dSAlan Somers 			if (errno == EAGAIN) {
172e594026dSAlan Somers 				close(sv[0]);
173e594026dSAlan Somers 				close(sv[1]);
174a8eb96d5SAlan Somers 				atf_tc_pass();
175e594026dSAlan Somers 			}
176a8eb96d5SAlan Somers 			else {
177a8eb96d5SAlan Somers 				perror("send");
178a8eb96d5SAlan Somers 				atf_tc_fail("send returned < 0 but not EAGAIN");
179a8eb96d5SAlan Somers 			}
180a8eb96d5SAlan Somers 		}
181a8eb96d5SAlan Somers 	}
182a8eb96d5SAlan Somers 	atf_tc_fail("Never got EAGAIN");
183a8eb96d5SAlan Somers }
184a8eb96d5SAlan Somers 
1855d5b721aSAlan Somers static void
186ea703329SBrooks Davis test_sendrecv_symmetric_buffers(int bufsize, int blocking) {
187a8eb96d5SAlan Somers 	int s;
188a8eb96d5SAlan Somers 	int sv[2];
1895d5b721aSAlan Somers 	const ssize_t pktsize = bufsize / 2;
190a8eb96d5SAlan Somers 	char sndbuf[pktsize];
191a8eb96d5SAlan Somers 	char recv_buf[pktsize];
192a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
193a8eb96d5SAlan Somers 
194a8eb96d5SAlan Somers 	/* setup the socket pair */
195a8eb96d5SAlan Somers 	if (blocking)
196a8eb96d5SAlan Somers 		do_socketpair(sv);
197a8eb96d5SAlan Somers 	else
198a8eb96d5SAlan Somers 		do_socketpair_nonblocking(sv);
199a8eb96d5SAlan Somers 
200a8eb96d5SAlan Somers 	/* Setup the buffers */
201a8eb96d5SAlan Somers 	s = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
202a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
203a8eb96d5SAlan Somers 	s = setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
204a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, s);
205a8eb96d5SAlan Somers 
206a8eb96d5SAlan Somers 	/* Fill the send buffer */
207a8eb96d5SAlan Somers 	bzero(sndbuf, pktsize);
208a8eb96d5SAlan Somers 
209a8eb96d5SAlan Somers 	/* send and receive the packet */
210a8eb96d5SAlan Somers 	ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
211a8eb96d5SAlan Somers 	if (ssize < 0) {
212a8eb96d5SAlan Somers 		perror("send");
213a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
214a8eb96d5SAlan Somers 	}
215a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(pktsize, ssize, "expected %zd=send(...) but got %zd",
216a8eb96d5SAlan Somers 	    pktsize, ssize);
217a8eb96d5SAlan Somers 
218a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
219a8eb96d5SAlan Somers 	if (rsize < 0) {
220a8eb96d5SAlan Somers 		perror("recv");
221a8eb96d5SAlan Somers 		atf_tc_fail("recv returned < 0");
222a8eb96d5SAlan Somers 	}
223a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(pktsize, rsize, "expected %zd=send(...) but got %zd",
224a8eb96d5SAlan Somers 	    pktsize, rsize);
225e594026dSAlan Somers 	close(sv[0]);
226e594026dSAlan Somers 	close(sv[1]);
227a8eb96d5SAlan Somers }
228a8eb96d5SAlan Somers 
2295d5b721aSAlan Somers static void
230ea703329SBrooks Davis test_pipe_simulator(int sndbufsize, int rcvbufsize)
231a8eb96d5SAlan Somers {
2325d5b721aSAlan Somers 	int num_sent, num_received;
233a8eb96d5SAlan Somers 	int sv[2];
2345d5b721aSAlan Somers 	const ssize_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
235a8eb96d5SAlan Somers 	int numpkts;
236a8eb96d5SAlan Somers 	char sndbuf[pktsize];
237a8eb96d5SAlan Somers 	char rcvbuf[pktsize];
238a8eb96d5SAlan Somers 	char comparebuf[pktsize];
239a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
240a8eb96d5SAlan Somers 	bool currently_sending = true;
241a8eb96d5SAlan Somers 
242a8eb96d5SAlan Somers 	/* setup the socket pair */
243a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
244a8eb96d5SAlan Somers 	/* Setup the buffers */
245a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
246a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
247a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
248a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
249a8eb96d5SAlan Somers 
250a8eb96d5SAlan Somers 	/* Send a total amount of data comfortably greater than the buffers */
251a8eb96d5SAlan Somers 	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
252a8eb96d5SAlan Somers 	for (num_sent=0, num_received=0;
253a8eb96d5SAlan Somers 	     num_sent < numpkts || num_received < numpkts; ) {
254a8eb96d5SAlan Somers 		if (currently_sending && num_sent < numpkts) {
255a8eb96d5SAlan Somers 			/* The simulated sending process */
256a8eb96d5SAlan Somers 			/* fill the buffer */
257a8eb96d5SAlan Somers 			memset(sndbuf, num_sent, pktsize);
258a8eb96d5SAlan Somers 			ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
259a8eb96d5SAlan Somers 			if (ssize < 0) {
260a8eb96d5SAlan Somers 				/*
261a8eb96d5SAlan Somers 				 * XXX: This is bug-compatible with the kernel.
262a8eb96d5SAlan Somers 				 * The kernel returns EMSGSIZE when it should
263a8eb96d5SAlan Somers 				 * return EAGAIN
264a8eb96d5SAlan Somers 				 */
265a8eb96d5SAlan Somers 				if (errno == EAGAIN || errno == EMSGSIZE)
266a8eb96d5SAlan Somers 					currently_sending = false;
267a8eb96d5SAlan Somers 				else {
268a8eb96d5SAlan Somers 					perror("send");
269a8eb96d5SAlan Somers 					atf_tc_fail("send failed");
270a8eb96d5SAlan Somers 				}
271a8eb96d5SAlan Somers 			} else  {
272a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(pktsize, ssize,
273a8eb96d5SAlan Somers 				    "expected %zd=send(...) but got %zd",
274a8eb96d5SAlan Somers 				    pktsize, ssize);
275a8eb96d5SAlan Somers 				num_sent++;
276a8eb96d5SAlan Somers 			}
277a8eb96d5SAlan Somers 		} else {
278a8eb96d5SAlan Somers 			/* The simulated receiving process */
279a8eb96d5SAlan Somers 			rsize = recv(sv[1], rcvbuf, pktsize, MSG_WAITALL);
280a8eb96d5SAlan Somers 			if (rsize < 0) {
281a8eb96d5SAlan Somers 				if (errno == EAGAIN) {
282a8eb96d5SAlan Somers 					currently_sending = true;
283a8eb96d5SAlan Somers 					ATF_REQUIRE_MSG(num_sent < numpkts,
284a8eb96d5SAlan Somers 					    "Packets were lost!");
285a8eb96d5SAlan Somers 				}
286a8eb96d5SAlan Somers 				else {
287a8eb96d5SAlan Somers 					perror("recv");
288a8eb96d5SAlan Somers 					atf_tc_fail("recv failed");
289a8eb96d5SAlan Somers 				}
290a8eb96d5SAlan Somers 			} else  {
291a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(pktsize, rsize,
292a8eb96d5SAlan Somers 				    "expected %zd=recv(...) but got %zd",
293a8eb96d5SAlan Somers 				    pktsize, rsize);
294a8eb96d5SAlan Somers 				memset(comparebuf, num_received, pktsize);
295a8eb96d5SAlan Somers 				ATF_CHECK_EQ_MSG(0, memcmp(comparebuf, rcvbuf,
296a8eb96d5SAlan Somers 				    			   pktsize),
297a8eb96d5SAlan Somers 				    "Received data miscompare");
298a8eb96d5SAlan Somers 				num_received++;
299a8eb96d5SAlan Somers 			}
300a8eb96d5SAlan Somers 		}
301a8eb96d5SAlan Somers 	}
302e594026dSAlan Somers 	close(sv[0]);
303e594026dSAlan Somers 	close(sv[1]);
304a8eb96d5SAlan Somers }
305a8eb96d5SAlan Somers 
306a8eb96d5SAlan Somers typedef struct {
307a8eb96d5SAlan Somers 	ssize_t	pktsize;
308a8eb96d5SAlan Somers 	int	numpkts;
309a8eb96d5SAlan Somers 	int	so;
310a8eb96d5SAlan Somers } test_pipe_thread_data_t;
311a8eb96d5SAlan Somers 
312a8eb96d5SAlan Somers static void*
313a8eb96d5SAlan Somers test_pipe_writer(void* args)
314a8eb96d5SAlan Somers {
315a8eb96d5SAlan Somers 	test_pipe_thread_data_t* td = args;
316a8eb96d5SAlan Somers 	char sndbuf[td->pktsize];
317a8eb96d5SAlan Somers 	ssize_t ssize;
318a8eb96d5SAlan Somers 	int i;
319a8eb96d5SAlan Somers 
320a8eb96d5SAlan Somers 	for(i=0; i < td->numpkts; i++) {
321a8eb96d5SAlan Somers 			memset(sndbuf, i, td->pktsize);
322a8eb96d5SAlan Somers 			ssize = send(td->so, sndbuf, td->pktsize, MSG_EOR);
323a8eb96d5SAlan Somers 			if (ssize < 0) {
324a8eb96d5SAlan Somers 				perror("send");
325a8eb96d5SAlan Somers 				atf_tc_fail("send returned < 0");
326a8eb96d5SAlan Somers 			}
327a8eb96d5SAlan Somers 			ATF_CHECK_EQ_MSG(td->pktsize, ssize,
328a8eb96d5SAlan Somers 			    		 "expected %zd=send(...) but got %zd",
329a8eb96d5SAlan Somers 			    		  td->pktsize, ssize);
330a8eb96d5SAlan Somers 	}
331a8eb96d5SAlan Somers 	return (0);
332a8eb96d5SAlan Somers }
333a8eb96d5SAlan Somers 
334a8eb96d5SAlan Somers static void*
335a8eb96d5SAlan Somers test_pipe_reader(void* args)
336a8eb96d5SAlan Somers {
337a8eb96d5SAlan Somers 	test_pipe_thread_data_t* td = args;
338a8eb96d5SAlan Somers 	char rcvbuf[td->pktsize];
339a8eb96d5SAlan Somers 	char comparebuf[td->pktsize];
340a8eb96d5SAlan Somers 	ssize_t rsize;
341a8eb96d5SAlan Somers 	int i, d;
342a8eb96d5SAlan Somers 
343a8eb96d5SAlan Somers 	for(i=0; i < td->numpkts; i++) {
344a8eb96d5SAlan Somers 		memset(comparebuf, i, td->pktsize);
345a8eb96d5SAlan Somers 		rsize = recv(td->so, rcvbuf, td->pktsize, MSG_WAITALL);
346a8eb96d5SAlan Somers 		if (rsize < 0) {
347a8eb96d5SAlan Somers 			perror("recv");
348a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
349a8eb96d5SAlan Somers 		}
350a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(td->pktsize, rsize,
351a8eb96d5SAlan Somers 		    		 "expected %zd=send(...) but got %zd",
352a8eb96d5SAlan Somers 				 td->pktsize, rsize);
353a8eb96d5SAlan Somers 		d = memcmp(comparebuf, rcvbuf, td->pktsize);
354a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, d,
355a8eb96d5SAlan Somers 		    		 "Received data miscompare on packet %d", i);
356a8eb96d5SAlan Somers 	}
357a8eb96d5SAlan Somers 	return (0);
358a8eb96d5SAlan Somers }
359a8eb96d5SAlan Somers 
360a8eb96d5SAlan Somers 
3615d5b721aSAlan Somers static void
362ea703329SBrooks Davis test_pipe(int sndbufsize, int rcvbufsize)
363a8eb96d5SAlan Somers {
364a8eb96d5SAlan Somers 	test_pipe_thread_data_t writer_data, reader_data;
365a8eb96d5SAlan Somers 	pthread_t writer, reader;
366a8eb96d5SAlan Somers 	int sv[2];
367a8eb96d5SAlan Somers 	const size_t pktsize = MIN(sndbufsize, rcvbufsize) / 4;
368a8eb96d5SAlan Somers 	int numpkts;
369a8eb96d5SAlan Somers 
370a8eb96d5SAlan Somers 	/* setup the socket pair */
371a8eb96d5SAlan Somers 	do_socketpair(sv);
372a8eb96d5SAlan Somers 	/* Setup the buffers */
373a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
374a8eb96d5SAlan Somers 	    sizeof(sndbufsize)));
375a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
376a8eb96d5SAlan Somers 	    sizeof(rcvbufsize)));
377a8eb96d5SAlan Somers 
378a8eb96d5SAlan Somers 	/* Send a total amount of data comfortably greater than the buffers */
379a8eb96d5SAlan Somers 	numpkts = MAX(sndbufsize, rcvbufsize) * 8 / pktsize;
380a8eb96d5SAlan Somers 
381a8eb96d5SAlan Somers 	/* Start the child threads */
382a8eb96d5SAlan Somers 	writer_data.pktsize = pktsize;
383a8eb96d5SAlan Somers 	writer_data.numpkts = numpkts;
384a8eb96d5SAlan Somers 	writer_data.so = sv[0];
385a8eb96d5SAlan Somers 	reader_data.pktsize = pktsize;
386a8eb96d5SAlan Somers 	reader_data.numpkts = numpkts;
387a8eb96d5SAlan Somers 	reader_data.so = sv[1];
388a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_create(&writer, NULL, test_pipe_writer,
389a8eb96d5SAlan Somers 	    				 (void*)&writer_data));
3908de34a88SAlan Somers 	/*
3918de34a88SAlan Somers 	 * Give the writer time to start writing, and hopefully block, before
3928de34a88SAlan Somers 	 * starting the reader.  This increases the likelihood of the test case
3938de34a88SAlan Somers 	 * failing due to PR kern/185812
3948de34a88SAlan Somers 	 */
3958de34a88SAlan Somers 	usleep(1000);
396a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_create(&reader, NULL, test_pipe_reader,
397a8eb96d5SAlan Somers 	    				 (void*)&reader_data));
398a8eb96d5SAlan Somers 
399a8eb96d5SAlan Somers 	/* Join the children */
400a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_join(writer, NULL));
401a8eb96d5SAlan Somers 	ATF_REQUIRE_EQ(0, pthread_join(reader, NULL));
402e594026dSAlan Somers 	close(sv[0]);
403e594026dSAlan Somers 	close(sv[1]);
404a8eb96d5SAlan Somers }
405a8eb96d5SAlan Somers 
406a8eb96d5SAlan Somers 
407a8eb96d5SAlan Somers /*
408a8eb96d5SAlan Somers  * Test Cases
409a8eb96d5SAlan Somers  */
410a8eb96d5SAlan Somers 
411a8eb96d5SAlan Somers /* Create a SEQPACKET socket */
412a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(create_socket);
413a8eb96d5SAlan Somers ATF_TC_BODY(create_socket, tc)
414a8eb96d5SAlan Somers {
415a8eb96d5SAlan Somers 	int s;
416a8eb96d5SAlan Somers 
417a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
4186addc01eSAlan Somers 	ATF_REQUIRE(s >= 0);
419e594026dSAlan Somers 	close(s);
420a8eb96d5SAlan Somers }
421a8eb96d5SAlan Somers 
422a8eb96d5SAlan Somers /* Create SEQPACKET sockets using socketpair(2) */
423a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(create_socketpair);
424a8eb96d5SAlan Somers ATF_TC_BODY(create_socketpair, tc)
425a8eb96d5SAlan Somers {
426a8eb96d5SAlan Somers 	int sv[2];
427a8eb96d5SAlan Somers 	int s;
428a8eb96d5SAlan Somers 
429a8eb96d5SAlan Somers 	s = socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sv);
430a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, s);
431a8eb96d5SAlan Somers 	ATF_CHECK(sv[0] >= 0);
432a8eb96d5SAlan Somers 	ATF_CHECK(sv[1] >= 0);
433a8eb96d5SAlan Somers 	ATF_CHECK(sv[0] != sv[1]);
434e594026dSAlan Somers 	close(sv[0]);
435e594026dSAlan Somers 	close(sv[1]);
436a8eb96d5SAlan Somers }
437a8eb96d5SAlan Somers 
438a8eb96d5SAlan Somers /* Call listen(2) without first calling bind(2).  It should fail */
439a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(listen_unbound);
440a8eb96d5SAlan Somers ATF_TC_BODY(listen_unbound, tc)
441a8eb96d5SAlan Somers {
442a8eb96d5SAlan Somers 	int s, r;
443a8eb96d5SAlan Somers 
444a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
445a8eb96d5SAlan Somers 	ATF_REQUIRE(s > 0);
446a8eb96d5SAlan Somers 	r = listen(s, -1);
447a8eb96d5SAlan Somers 	/* expect listen to fail since we haven't called bind(2) */
448a8eb96d5SAlan Somers 	ATF_CHECK(r != 0);
449e594026dSAlan Somers 	close(s);
450a8eb96d5SAlan Somers }
451a8eb96d5SAlan Somers 
452a8eb96d5SAlan Somers /* Bind the socket to a file */
453a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(bind);
454a8eb96d5SAlan Somers ATF_TC_BODY(bind, tc)
455a8eb96d5SAlan Somers {
456a8eb96d5SAlan Somers 	struct sockaddr_un sun;
457a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
458a8eb96d5SAlan Somers 	const char *path = "sock";
459a8eb96d5SAlan Somers 	int s, r;
460a8eb96d5SAlan Somers 
461a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
462a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
463a8eb96d5SAlan Somers 
464a8eb96d5SAlan Somers 	bzero(&sun, sizeof(sun));
465a8eb96d5SAlan Somers 	sun.sun_family = AF_LOCAL;
466a8eb96d5SAlan Somers 	sun.sun_len = sizeof(sun);
467a8eb96d5SAlan Somers 	strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
468a8eb96d5SAlan Somers 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
469a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, r);
470e594026dSAlan Somers 	close(s);
471a8eb96d5SAlan Somers }
472a8eb96d5SAlan Somers 
473a8eb96d5SAlan Somers /* listen(2) a socket that is already bound(2) should succeed */
474a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(listen_bound);
475a8eb96d5SAlan Somers ATF_TC_BODY(listen_bound, tc)
476a8eb96d5SAlan Somers {
4771f46c32cSGleb Smirnoff 	int s;
478a8eb96d5SAlan Somers 
4791f46c32cSGleb Smirnoff 	(void)mk_listening_socket(&s);
480e594026dSAlan Somers 	close(s);
481a8eb96d5SAlan Somers }
482a8eb96d5SAlan Somers 
483a8eb96d5SAlan Somers /* connect(2) can make a connection */
484a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(connect);
485a8eb96d5SAlan Somers ATF_TC_BODY(connect, tc)
486a8eb96d5SAlan Somers {
4871f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
4881f46c32cSGleb Smirnoff 	int s, err, s2;
489a8eb96d5SAlan Somers 
4901f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
491a8eb96d5SAlan Somers 
492a8eb96d5SAlan Somers 	/* Create the other socket */
493a8eb96d5SAlan Somers 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
494a8eb96d5SAlan Somers 	ATF_REQUIRE(s2 >= 0);
4951f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
496a8eb96d5SAlan Somers 	if (err != 0) {
497a8eb96d5SAlan Somers 		perror("connect");
498a8eb96d5SAlan Somers 		atf_tc_fail("connect(2) failed");
499a8eb96d5SAlan Somers 	}
500e594026dSAlan Somers 	close(s);
501e594026dSAlan Somers 	close(s2);
502a8eb96d5SAlan Somers }
503a8eb96d5SAlan Somers 
5043bc122d2SGleb Smirnoff /*
5053bc122d2SGleb Smirnoff  * An undocumented feature that we probably want to preserve: sending to
5063bc122d2SGleb Smirnoff  * a socket that isn't yet accepted lands data on the socket.  It can be
5073bc122d2SGleb Smirnoff  * read after accept(2).
5083bc122d2SGleb Smirnoff  */
5093bc122d2SGleb Smirnoff ATF_TC_WITHOUT_HEAD(send_before_accept);
5103bc122d2SGleb Smirnoff ATF_TC_BODY(send_before_accept, tc)
5113bc122d2SGleb Smirnoff {
5123bc122d2SGleb Smirnoff 	const char buf[] = "hello";
5133bc122d2SGleb Smirnoff 	char repl[sizeof(buf)];
5143bc122d2SGleb Smirnoff 	const struct sockaddr_un *sun;
5153bc122d2SGleb Smirnoff 	int l, s, a;
5163bc122d2SGleb Smirnoff 
5173bc122d2SGleb Smirnoff 	sun = mk_listening_socket(&l);
5183bc122d2SGleb Smirnoff 
5193bc122d2SGleb Smirnoff 	ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0);
5203bc122d2SGleb Smirnoff 	ATF_REQUIRE(connect(s, (struct sockaddr *)sun, sizeof(*sun)) == 0);
5213bc122d2SGleb Smirnoff 	ATF_REQUIRE(send(s, &buf, sizeof(buf), 0) == sizeof(buf));
5223bc122d2SGleb Smirnoff 	ATF_REQUIRE((a = accept(l, NULL, NULL)) != 1);
5233bc122d2SGleb Smirnoff 	ATF_REQUIRE(recv(a, &repl, sizeof(repl), 0) == sizeof(buf));
5243bc122d2SGleb Smirnoff 	ATF_REQUIRE(strcmp(buf, repl) == 0);
5253bc122d2SGleb Smirnoff 	close(l);
5263bc122d2SGleb Smirnoff 	close(s);
5273bc122d2SGleb Smirnoff 	close(a);
5283bc122d2SGleb Smirnoff }
5293bc122d2SGleb Smirnoff 
530253d8a1fSGleb Smirnoff /* Implied connect is unix/dgram only feature. Fails on stream or seqpacket. */
531253d8a1fSGleb Smirnoff ATF_TC_WITHOUT_HEAD(implied_connect);
532253d8a1fSGleb Smirnoff ATF_TC_BODY(implied_connect, tc)
533253d8a1fSGleb Smirnoff {
534253d8a1fSGleb Smirnoff 	const struct sockaddr_un *sun;
535253d8a1fSGleb Smirnoff 	int l, s;
536253d8a1fSGleb Smirnoff 
537253d8a1fSGleb Smirnoff 	sun = mk_listening_socket(&l);
538253d8a1fSGleb Smirnoff 
539253d8a1fSGleb Smirnoff 	ATF_REQUIRE((s = socket(PF_LOCAL, SOCK_SEQPACKET, 0)) > 0);
540253d8a1fSGleb Smirnoff 	ATF_REQUIRE(sendto(s, &s, sizeof(s), 0, (struct sockaddr *)sun,
541253d8a1fSGleb Smirnoff 	    sizeof(*sun)) == -1);
542253d8a1fSGleb Smirnoff 	ATF_REQUIRE(errno == ENOTCONN);
543253d8a1fSGleb Smirnoff 	close(l);
544253d8a1fSGleb Smirnoff 	close(s);
545253d8a1fSGleb Smirnoff }
546253d8a1fSGleb Smirnoff 
547a8eb96d5SAlan Somers /* accept(2) can receive a connection */
548a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(accept);
549a8eb96d5SAlan Somers ATF_TC_BODY(accept, tc)
550a8eb96d5SAlan Somers {
551a8eb96d5SAlan Somers 	int sv[2];
552a8eb96d5SAlan Somers 
553a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
554e594026dSAlan Somers 	close(sv[0]);
555e594026dSAlan Somers 	close(sv[1]);
556a8eb96d5SAlan Somers }
557a8eb96d5SAlan Somers 
558a8eb96d5SAlan Somers 
559a8eb96d5SAlan Somers /* Set O_NONBLOCK on the socket */
560a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
561a8eb96d5SAlan Somers ATF_TC_BODY(fcntl_nonblock, tc)
562a8eb96d5SAlan Somers {
563a8eb96d5SAlan Somers 	int s;
564a8eb96d5SAlan Somers 
565a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
566a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
567a8eb96d5SAlan Somers 	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
568a8eb96d5SAlan Somers 		perror("fcntl");
569a8eb96d5SAlan Somers 		atf_tc_fail("fcntl failed");
570a8eb96d5SAlan Somers 	}
571e594026dSAlan Somers 	close(s);
572a8eb96d5SAlan Somers }
573a8eb96d5SAlan Somers 
574a8eb96d5SAlan Somers /* Resize the send and receive buffers */
575a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_buffers);
576a8eb96d5SAlan Somers ATF_TC_BODY(resize_buffers, tc)
577a8eb96d5SAlan Somers {
578a8eb96d5SAlan Somers 	int s;
579a8eb96d5SAlan Somers 	int sndbuf = 12345;
580a8eb96d5SAlan Somers 	int rcvbuf = 23456;
581a8eb96d5SAlan Somers 	int xs, xr;
582a8eb96d5SAlan Somers 	socklen_t sl = sizeof(xs);
583a8eb96d5SAlan Somers 
584a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
585a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
586a8eb96d5SAlan Somers 
587a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
588a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  |\n");
589a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
590a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
591a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d |\n", xs, xr);
592a8eb96d5SAlan Somers 
593a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
594a8eb96d5SAlan Somers 		perror("setsockopt");
595a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
596a8eb96d5SAlan Somers 	}
597a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
598a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
599a8eb96d5SAlan Somers 	printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
600a8eb96d5SAlan Somers 
601a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
602a8eb96d5SAlan Somers 		perror("setsockopt");
603a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
604a8eb96d5SAlan Somers 	}
605a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
606a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
607a8eb96d5SAlan Somers 	printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
608e594026dSAlan Somers 	close(s);
609a8eb96d5SAlan Somers }
610a8eb96d5SAlan Somers 
611a8eb96d5SAlan Somers /*
612a8eb96d5SAlan Somers  * Resize the send and receive buffers of a connected socketpair
613a8eb96d5SAlan Somers  * Print some useful debugging info too
614a8eb96d5SAlan Somers  */
615a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
616a8eb96d5SAlan Somers ATF_TC_BODY(resize_connected_buffers, tc)
617a8eb96d5SAlan Somers {
618a8eb96d5SAlan Somers 	int sv[2];
619a8eb96d5SAlan Somers 	int sndbuf = 12345;
620a8eb96d5SAlan Somers 	int rcvbuf = 23456;
621a8eb96d5SAlan Somers 	int err;
622a8eb96d5SAlan Somers 	int ls, lr, rs, rr;
623a8eb96d5SAlan Somers 	socklen_t sl = sizeof(ls);
624a8eb96d5SAlan Somers 
625a8eb96d5SAlan Somers 	/* setup the socket pair */
626a8eb96d5SAlan Somers 	do_socketpair(sv);
627a8eb96d5SAlan Somers 
628a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
629a8eb96d5SAlan Somers 	printf("                              | Left Socket       | Right Socket      |\n");
630a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | RCVBUF  |\n");
631a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
632a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
633a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
634a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
635a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d | %7d | %7d |\n",
636a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
637a8eb96d5SAlan Somers 
638a8eb96d5SAlan Somers 	/* Update one side's send buffer */
639a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
640a8eb96d5SAlan Somers 	if (err != 0){
641a8eb96d5SAlan Somers 		perror("setsockopt");
642a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
643a8eb96d5SAlan Somers 	}
644a8eb96d5SAlan Somers 
645a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
646a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
647a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
648a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
649a8eb96d5SAlan Somers 	printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
650a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
651a8eb96d5SAlan Somers 
652a8eb96d5SAlan Somers 	/* Update the same side's receive buffer */
653a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
654a8eb96d5SAlan Somers 	if (err != 0){
655a8eb96d5SAlan Somers 		perror("setsockopt");
656a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
657a8eb96d5SAlan Somers 	}
658a8eb96d5SAlan Somers 
659a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
660a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
661a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
662a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
663a8eb96d5SAlan Somers 	printf("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
664a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
665e594026dSAlan Somers 	close(sv[0]);
666e594026dSAlan Somers 	close(sv[1]);
667a8eb96d5SAlan Somers }
668a8eb96d5SAlan Somers 
669a8eb96d5SAlan Somers 
670a8eb96d5SAlan Somers /* send(2) and recv(2) a single short record */
671a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv);
672a8eb96d5SAlan Somers ATF_TC_BODY(send_recv, tc)
673a8eb96d5SAlan Somers {
674a8eb96d5SAlan Somers 	int sv[2];
675a8eb96d5SAlan Somers 	const int bufsize = 64;
676a8eb96d5SAlan Somers 	const char *data = "data";
677a8eb96d5SAlan Somers 	char recv_buf[bufsize];
6785d5b721aSAlan Somers 	ssize_t datalen;
679a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
680a8eb96d5SAlan Somers 
681a8eb96d5SAlan Somers 	/* setup the socket pair */
682a8eb96d5SAlan Somers 	do_socketpair(sv);
683a8eb96d5SAlan Somers 
684a8eb96d5SAlan Somers 	/* send and receive a small packet */
685a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
686a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
687a8eb96d5SAlan Somers 	if (ssize < 0) {
688a8eb96d5SAlan Somers 		perror("send");
689a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
690a8eb96d5SAlan Somers 	}
691a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
692a8eb96d5SAlan Somers 	    datalen, ssize);
693a8eb96d5SAlan Somers 
694a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
695a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
696e594026dSAlan Somers 	close(sv[0]);
697e594026dSAlan Somers 	close(sv[1]);
698a8eb96d5SAlan Somers }
699a8eb96d5SAlan Somers 
700a8eb96d5SAlan Somers /* sendto(2) and recvfrom(2) a single short record
701a8eb96d5SAlan Somers  * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
702a8eb96d5SAlan Somers  * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
703a8eb96d5SAlan Somers  *
704a8eb96d5SAlan Somers  * According to the same spec, not all protocols are required to provide the
705a8eb96d5SAlan Somers  * source addres in recvfrom(2).
706a8eb96d5SAlan Somers  */
707a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
708a8eb96d5SAlan Somers ATF_TC_BODY(sendto_recvfrom, tc)
709a8eb96d5SAlan Somers {
710983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
7111f46c32cSGleb Smirnoff 	const sockaddr_un *sun;
712983a2d91SEnji Cooper #endif
713a8eb96d5SAlan Somers 	struct sockaddr_storage from;
714a8eb96d5SAlan Somers 	int sv[2];
715a8eb96d5SAlan Somers 	const int bufsize = 64;
716a8eb96d5SAlan Somers 	const char *data = "data";
717a8eb96d5SAlan Somers 	char recv_buf[bufsize];
7185d5b721aSAlan Somers 	ssize_t datalen;
719a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
720a8eb96d5SAlan Somers 	socklen_t fromlen;
721a8eb96d5SAlan Somers 
722a8eb96d5SAlan Somers 	/* setup the socket pair */
723983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
7241f46c32cSGleb Smirnoff 	sun =
725983a2d91SEnji Cooper #endif
726983a2d91SEnji Cooper 		mk_pair_of_sockets(sv);
727a8eb96d5SAlan Somers 
728a8eb96d5SAlan Somers 	/* send and receive a small packet */
729a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
730a8eb96d5SAlan Somers 	ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
731a8eb96d5SAlan Somers 	if (ssize < 0) {
732a8eb96d5SAlan Somers 		perror("send");
733a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
734a8eb96d5SAlan Somers 	}
735a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
736a8eb96d5SAlan Somers 	    datalen, ssize);
737a8eb96d5SAlan Somers 
738a8eb96d5SAlan Somers 	fromlen = sizeof(from);
739a8eb96d5SAlan Somers 	rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
740a8eb96d5SAlan Somers 	    (struct sockaddr*)&from, &fromlen);
741a8eb96d5SAlan Somers 	if (ssize < 0) {
742a8eb96d5SAlan Somers 		perror("recvfrom");
743a8eb96d5SAlan Somers 		atf_tc_fail("recvfrom returned < 0");
744a8eb96d5SAlan Somers 	}
745a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
746a8eb96d5SAlan Somers 
747983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
748a8eb96d5SAlan Somers 	/*
749a8eb96d5SAlan Somers 	 * FreeBSD does not currently provide the source address for SEQ_PACKET
750a8eb96d5SAlan Somers 	 * AF_UNIX sockets, and POSIX does not require it, so these two checks
751a8eb96d5SAlan Somers 	 * are disabled.  If FreeBSD gains that feature in the future, then
752a8eb96d5SAlan Somers 	 * these checks may be reenabled
753a8eb96d5SAlan Somers 	 */
754983a2d91SEnji Cooper 	ATF_CHECK_EQ(PF_LOCAL, from.ss_family);
7551f46c32cSGleb Smirnoff 	ATF_CHECK_STREQ(sun->sun_path, ((struct sockaddr_un*)&from)->sun_path);
756983a2d91SEnji Cooper #endif
757e594026dSAlan Somers 	close(sv[0]);
758e594026dSAlan Somers 	close(sv[1]);
759a8eb96d5SAlan Somers }
760a8eb96d5SAlan Somers 
761a8eb96d5SAlan Somers /*
762a8eb96d5SAlan Somers  * send(2) and recv(2) a single short record with sockets created the
763a8eb96d5SAlan Somers  * traditional way, involving bind, listen, connect, and accept
764a8eb96d5SAlan Somers  */
765a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_with_connect);
766a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_with_connect, tc)
767a8eb96d5SAlan Somers {
768a8eb96d5SAlan Somers 	int sv[2];
769a8eb96d5SAlan Somers 	const int bufsize = 64;
770a8eb96d5SAlan Somers 	const char *data = "data";
771a8eb96d5SAlan Somers 	char recv_buf[bufsize];
7725d5b721aSAlan Somers 	ssize_t datalen;
773a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
774a8eb96d5SAlan Somers 
775a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
776a8eb96d5SAlan Somers 
777a8eb96d5SAlan Somers 	/* send and receive a small packet */
778a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
779a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
780a8eb96d5SAlan Somers 	if (ssize < 0) {
781a8eb96d5SAlan Somers 		perror("send");
782a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
783a8eb96d5SAlan Somers 	}
784a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
785a8eb96d5SAlan Somers 	    datalen, ssize);
786a8eb96d5SAlan Somers 
787a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
788a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
789e594026dSAlan Somers 	close(sv[0]);
790e594026dSAlan Somers 	close(sv[1]);
791a8eb96d5SAlan Somers }
792a8eb96d5SAlan Somers 
793a8eb96d5SAlan Somers /* send(2) should fail on a shutdown socket */
794a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send);
795a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send, tc)
796a8eb96d5SAlan Somers {
7971f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
7984446a47aSSergey Kandaurov 	const char *data = "data";
799fa5e5f53SEnji Cooper 	ssize_t datalen, ssize;
8004446a47aSSergey Kandaurov 	int s, err, s2;
801a8eb96d5SAlan Somers 
8021f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
8034446a47aSSergey Kandaurov 
8044446a47aSSergey Kandaurov 	/* Create the other socket */
8054446a47aSSergey Kandaurov 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
8064446a47aSSergey Kandaurov 	ATF_REQUIRE(s2 >= 0);
8071f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
8084446a47aSSergey Kandaurov 	if (err != 0) {
8094446a47aSSergey Kandaurov 		perror("connect");
8104446a47aSSergey Kandaurov 		atf_tc_fail("connect(2) failed");
8114446a47aSSergey Kandaurov 	}
8124446a47aSSergey Kandaurov 
8134446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
814fa5e5f53SEnji Cooper 	datalen = strlen(data) + 1;	/* +1 for the null */
815a8eb96d5SAlan Somers 	/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
816fa5e5f53SEnji Cooper 	ssize = send(s2, data, datalen, MSG_EOR | MSG_NOSIGNAL);
817a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EPIPE, errno);
818a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, ssize);
819e594026dSAlan Somers 	close(s);
8204446a47aSSergey Kandaurov 	close(s2);
821a8eb96d5SAlan Somers }
822a8eb96d5SAlan Somers 
823a8eb96d5SAlan Somers /* send(2) should cause SIGPIPE on a shutdown socket */
824a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
825a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send_sigpipe, tc)
826a8eb96d5SAlan Somers {
8271f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
8284446a47aSSergey Kandaurov 	const char *data = "data";
829fa5e5f53SEnji Cooper 	ssize_t datalen;
8304446a47aSSergey Kandaurov 	int s, err, s2;
831a8eb96d5SAlan Somers 
8321f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
8334446a47aSSergey Kandaurov 
8344446a47aSSergey Kandaurov 	/* Create the other socket */
8354446a47aSSergey Kandaurov 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
8364446a47aSSergey Kandaurov 	ATF_REQUIRE(s2 >= 0);
8371f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
8384446a47aSSergey Kandaurov 	if (err != 0) {
8394446a47aSSergey Kandaurov 		perror("connect");
8404446a47aSSergey Kandaurov 		atf_tc_fail("connect(2) failed");
8414446a47aSSergey Kandaurov 	}
8424446a47aSSergey Kandaurov 
8434446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
844a8eb96d5SAlan Somers 	ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
845fa5e5f53SEnji Cooper 	datalen = strlen(data) + 1;	/* +1 for the null */
8466dd202ceSJohn Baldwin 	(void)send(s2, data, datalen, MSG_EOR);
847a8eb96d5SAlan Somers 	ATF_CHECK_EQ(1, got_sigpipe);
848e594026dSAlan Somers 	close(s);
8494446a47aSSergey Kandaurov 	close(s2);
850a8eb96d5SAlan Somers }
851a8eb96d5SAlan Somers 
852a8eb96d5SAlan Somers /* nonblocking send(2) and recv(2) a single short record */
853a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
854a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_nonblocking, tc)
855a8eb96d5SAlan Somers {
856a8eb96d5SAlan Somers 	int sv[2];
857a8eb96d5SAlan Somers 	const int bufsize = 64;
858a8eb96d5SAlan Somers 	const char *data = "data";
859a8eb96d5SAlan Somers 	char recv_buf[bufsize];
8605d5b721aSAlan Somers 	ssize_t datalen;
861a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
862a8eb96d5SAlan Somers 
863a8eb96d5SAlan Somers 	/* setup the socket pair */
864a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
865a8eb96d5SAlan Somers 
866a8eb96d5SAlan Somers 	/* Verify that there is nothing to receive */
867a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
868a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
869a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
870a8eb96d5SAlan Somers 
871a8eb96d5SAlan Somers 	/* send and receive a small packet */
872a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
873a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
874a8eb96d5SAlan Somers 	if (ssize < 0) {
875a8eb96d5SAlan Somers 		perror("send");
876a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
877a8eb96d5SAlan Somers 	}
878a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
879a8eb96d5SAlan Somers 	    datalen, ssize);
880a8eb96d5SAlan Somers 
881a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
882a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
883e594026dSAlan Somers 	close(sv[0]);
884e594026dSAlan Somers 	close(sv[1]);
885a8eb96d5SAlan Somers }
886a8eb96d5SAlan Somers 
887a8eb96d5SAlan Somers /*
888a8eb96d5SAlan Somers  * We should get EAGAIN if we try to send a message larger than the socket
889a8eb96d5SAlan Somers  * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
890a8eb96d5SAlan Somers  */
891a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
892a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_8k, tc)
893a8eb96d5SAlan Somers {
894a8eb96d5SAlan Somers 	test_eagain(8192, 8192);
895a8eb96d5SAlan Somers }
896a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
897a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_128k, tc)
898a8eb96d5SAlan Somers {
899a8eb96d5SAlan Somers 	test_eagain(8192, 131072);
900a8eb96d5SAlan Somers }
901a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
902a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_8k, tc)
903a8eb96d5SAlan Somers {
904a8eb96d5SAlan Somers 	test_eagain(131072, 8192);
905a8eb96d5SAlan Somers }
906a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
907a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_128k, tc)
908a8eb96d5SAlan Somers {
909a8eb96d5SAlan Somers 	test_eagain(131072, 131072);
910a8eb96d5SAlan Somers }
911a8eb96d5SAlan Somers 
912a8eb96d5SAlan Somers 
913a8eb96d5SAlan Somers /*
914a8eb96d5SAlan Somers  * nonblocking send(2) and recv(2) of several records, which should collectively
915a8eb96d5SAlan Somers  * fill up the send buffer but not the receive buffer
916a8eb96d5SAlan Somers  */
917a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
918a8eb96d5SAlan Somers ATF_TC_BODY(rcvbuf_oversized, tc)
919a8eb96d5SAlan Somers {
9205d5b721aSAlan Somers 	int i;
921a8eb96d5SAlan Somers 	int sv[2];
9223be7751dSJulio Merino 	const ssize_t pktsize = 1024;
923ea703329SBrooks Davis 	const int sndbufsize = 8192;
924ea703329SBrooks Davis 	const int rcvbufsize = 131072;
9255d5b721aSAlan Somers 	const size_t geometric_mean_bufsize = 32768;
9265d5b721aSAlan Somers 	const int numpkts = geometric_mean_bufsize / pktsize;
927a8eb96d5SAlan Somers 	char sndbuf[pktsize];
928a8eb96d5SAlan Somers 	char recv_buf[pktsize];
929a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
930a8eb96d5SAlan Somers 
931a8eb96d5SAlan Somers 	/* setup the socket pair */
932a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
9335d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
9345d5b721aSAlan Somers 	    sizeof(sndbufsize)));
9355d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
9365d5b721aSAlan Somers 	    sizeof(rcvbufsize)));
937a8eb96d5SAlan Somers 
938a8eb96d5SAlan Somers 	/*
939a8eb96d5SAlan Somers 	 * Send and receive packets that are collectively greater than the send
940a8eb96d5SAlan Somers 	 * buffer, but less than the receive buffer
941a8eb96d5SAlan Somers 	 */
9425d5b721aSAlan Somers 	for (i=0; i < numpkts; i++) {
943a8eb96d5SAlan Somers 		/* Fill the buffer */
944a8eb96d5SAlan Somers 		memset(sndbuf, i, pktsize);
945a8eb96d5SAlan Somers 
946a8eb96d5SAlan Somers 		/* send the packet */
947a8eb96d5SAlan Somers 		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
948a8eb96d5SAlan Somers 		if (ssize < 0) {
949a8eb96d5SAlan Somers 			perror("send");
950a8eb96d5SAlan Somers 			atf_tc_fail("send returned < 0");
951a8eb96d5SAlan Somers 		}
952a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, ssize,
953a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, ssize);
954a8eb96d5SAlan Somers 
955a8eb96d5SAlan Somers 		/* Receive it */
956a8eb96d5SAlan Somers 
957a8eb96d5SAlan Somers 		rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
958a8eb96d5SAlan Somers 		if (rsize < 0) {
959a8eb96d5SAlan Somers 			perror("recv");
960a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
961a8eb96d5SAlan Somers 		}
962a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, rsize,
963a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, rsize);
964a8eb96d5SAlan Somers 
965a8eb96d5SAlan Somers 		/* Verify the contents */
966a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
967a8eb96d5SAlan Somers 		    "Received data miscompare");
968a8eb96d5SAlan Somers 	}
969a8eb96d5SAlan Somers 
970a8eb96d5SAlan Somers 	/* Trying to receive again should return EAGAIN */
971a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
972a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
973a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
974e594026dSAlan Somers 	close(sv[0]);
975e594026dSAlan Somers 	close(sv[1]);
976a8eb96d5SAlan Somers }
977a8eb96d5SAlan Somers 
978a8eb96d5SAlan Somers /*
979a8eb96d5SAlan Somers  * Simulate the behavior of a blocking pipe.  The sender will send until his
980a8eb96d5SAlan Somers  * buffer fills up, then we'll simulate a scheduler switch that will allow the
981a8eb96d5SAlan Somers  * receiver to read until his buffer empties.  Repeat the process until the
982a8eb96d5SAlan Somers  * transfer is complete.
983a8eb96d5SAlan Somers  * Repeat the test with multiple send and receive buffer sizes
984a8eb96d5SAlan Somers  */
985a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
986a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_8k, tc)
987a8eb96d5SAlan Somers {
988a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 8192);
989a8eb96d5SAlan Somers }
990a8eb96d5SAlan Somers 
991a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
992a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_128k, tc)
993a8eb96d5SAlan Somers {
994a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 131072);
995a8eb96d5SAlan Somers }
996a8eb96d5SAlan Somers 
997a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
998a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_8k, tc)
999a8eb96d5SAlan Somers {
1000a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 8192);
1001a8eb96d5SAlan Somers }
1002a8eb96d5SAlan Somers 
1003a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
1004a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_128k, tc)
1005a8eb96d5SAlan Somers {
1006a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 131072);
1007a8eb96d5SAlan Somers }
1008a8eb96d5SAlan Somers 
1009a8eb96d5SAlan Somers /*
1010a8eb96d5SAlan Somers  * Test blocking I/O by passing data between two threads.  The total amount of
1011a8eb96d5SAlan Somers  * data will be >> buffer size to force blocking.  Repeat the test with multiple
1012a8eb96d5SAlan Somers  * send and receive buffer sizes
1013a8eb96d5SAlan Somers  */
1014a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_8k);
1015a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_8k, tc)
1016a8eb96d5SAlan Somers {
1017a8eb96d5SAlan Somers 	test_pipe(8192, 8192);
1018a8eb96d5SAlan Somers }
1019a8eb96d5SAlan Somers 
1020a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_128k);
1021a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_128k, tc)
1022a8eb96d5SAlan Somers {
1023a8eb96d5SAlan Somers 	test_pipe(8192, 131072);
1024a8eb96d5SAlan Somers }
1025a8eb96d5SAlan Somers 
1026a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_8k);
1027a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_8k, tc)
1028a8eb96d5SAlan Somers {
1029a8eb96d5SAlan Somers 	test_pipe(131072, 8192);
1030a8eb96d5SAlan Somers }
1031a8eb96d5SAlan Somers 
1032a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_128k);
1033a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_128k, tc)
1034a8eb96d5SAlan Somers {
1035a8eb96d5SAlan Somers 	test_pipe(131072, 131072);
1036a8eb96d5SAlan Somers }
1037a8eb96d5SAlan Somers 
1038a8eb96d5SAlan Somers 
1039a8eb96d5SAlan Somers /*
1040a8eb96d5SAlan Somers  * Test single-packet I/O with and without blocking, with symmetric buffers of
1041a8eb96d5SAlan Somers  * various sizes
1042a8eb96d5SAlan Somers  */
1043a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k);
1044a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k, tc)
1045a8eb96d5SAlan Somers {
1046a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, true);
1047a8eb96d5SAlan Somers }
1048a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k);
1049a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k, tc)
1050a8eb96d5SAlan Somers {
1051a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, true);
1052a8eb96d5SAlan Somers }
1053a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k);
1054a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k, tc)
1055a8eb96d5SAlan Somers {
1056a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, true);
1057a8eb96d5SAlan Somers }
1058a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k);
1059a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k, tc)
1060a8eb96d5SAlan Somers {
1061a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, true);
1062a8eb96d5SAlan Somers }
1063a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k);
1064a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k, tc)
1065a8eb96d5SAlan Somers {
1066a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, true);
1067a8eb96d5SAlan Somers }
1068a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1069a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1070a8eb96d5SAlan Somers {
1071a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, false);
1072a8eb96d5SAlan Somers }
1073a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1074a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1075a8eb96d5SAlan Somers {
1076a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, false);
1077a8eb96d5SAlan Somers }
1078a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1079a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1080a8eb96d5SAlan Somers {
1081a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, false);
1082a8eb96d5SAlan Somers }
1083a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1084a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1085a8eb96d5SAlan Somers {
1086a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, false);
1087a8eb96d5SAlan Somers }
1088a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1089a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1090a8eb96d5SAlan Somers {
1091a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, false);
1092a8eb96d5SAlan Somers }
1093a8eb96d5SAlan Somers 
1094a8eb96d5SAlan Somers 
1095a8eb96d5SAlan Somers /*
1096a8eb96d5SAlan Somers  * Main.
1097a8eb96d5SAlan Somers  */
1098a8eb96d5SAlan Somers 
1099a8eb96d5SAlan Somers ATF_TP_ADD_TCS(tp)
1100a8eb96d5SAlan Somers {
1101a8eb96d5SAlan Somers 	/* Basic creation and connection tests */
1102a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socket);
1103a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socketpair);
1104a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_unbound);
1105a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, bind);
1106a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_bound);
1107a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, connect);
1108a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, accept);
1109a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, fcntl_nonblock);
1110a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_buffers);
1111a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_connected_buffers);
1112a8eb96d5SAlan Somers 
1113a8eb96d5SAlan Somers 	/* Unthreaded I/O tests */
1114a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv);
1115a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1116a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_with_connect);
1117a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendto_recvfrom);
11183bc122d2SGleb Smirnoff 	ATF_TP_ADD_TC(tp, send_before_accept);
1119253d8a1fSGleb Smirnoff 	ATF_TP_ADD_TC(tp, implied_connect);
1120a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send);
1121a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1122a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_8k);
1123a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_128k);
1124a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_8k);
1125a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_128k);
1126a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k);
1127a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k);
1128a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k);
1129a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k);
1130a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k);
1131a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1132a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1133a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1134a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1135a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1136a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1137a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1138a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1139a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1140a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1141a8eb96d5SAlan Somers 
1142a8eb96d5SAlan Somers 	/* Threaded I/O tests with blocking sockets */
1143a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_8k);
1144a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_128k);
1145a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_8k);
1146a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_128k);
1147a8eb96d5SAlan Somers 
1148a8eb96d5SAlan Somers 	return atf_no_error();
1149a8eb96d5SAlan Somers }
1150