xref: /freebsd/tests/sys/kern/unix_seqpacket_test.c (revision 1f46c32c1f3d0ea2a4c748a24aad06329cfb5f5a)
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 /*
71*1f46c32cSGleb Smirnoff  * Returns a bound and listening socket.
72a8eb96d5SAlan Somers  * @return	const char* The path to the socket
73a8eb96d5SAlan Somers  */
74*1f46c32cSGleb Smirnoff static const struct sockaddr_un *
75*1f46c32cSGleb Smirnoff mk_listening_socket(int *sv)
76a8eb96d5SAlan Somers {
77a8eb96d5SAlan Somers 	/* ATF's isolation mechanisms will guarantee uniqueness of this file */
78*1f46c32cSGleb Smirnoff 	static const struct sockaddr_un sun = {
79*1f46c32cSGleb Smirnoff 		.sun_family = AF_LOCAL,
80*1f46c32cSGleb Smirnoff 		.sun_len = sizeof(sun),
81*1f46c32cSGleb Smirnoff 		.sun_path = "sock",
82*1f46c32cSGleb Smirnoff 	};
83*1f46c32cSGleb Smirnoff 	int s, r, l;
84a8eb96d5SAlan Somers 
85a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
86a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
87a8eb96d5SAlan Somers 
88*1f46c32cSGleb Smirnoff 	r = bind(s, (struct sockaddr *)&sun, sizeof(sun));
89*1f46c32cSGleb Smirnoff 	l = listen(s, -1);
90*1f46c32cSGleb Smirnoff 	ATF_CHECK_EQ(0, r);
91*1f46c32cSGleb Smirnoff 	ATF_CHECK_EQ(0, l);
92*1f46c32cSGleb Smirnoff 
93*1f46c32cSGleb Smirnoff 	if (sv != NULL)
94*1f46c32cSGleb Smirnoff 		*sv = s;
95*1f46c32cSGleb Smirnoff 
96*1f46c32cSGleb Smirnoff 	return (&sun);
97*1f46c32cSGleb Smirnoff }
98*1f46c32cSGleb Smirnoff 
99*1f46c32cSGleb Smirnoff /*
100*1f46c32cSGleb Smirnoff  * Returns a pair of sockets made the hard way: bind, listen, connect & accept
101*1f46c32cSGleb Smirnoff  * @return	const char* The path to the socket
102*1f46c32cSGleb Smirnoff  */
103*1f46c32cSGleb Smirnoff static const struct sockaddr_un *
104*1f46c32cSGleb Smirnoff mk_pair_of_sockets(int *sv)
105*1f46c32cSGleb Smirnoff {
106*1f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
107*1f46c32cSGleb Smirnoff 	int s, s2, err, s1;
108*1f46c32cSGleb Smirnoff 
109*1f46c32cSGleb 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);
114*1f46c32cSGleb 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 
127*1f46c32cSGleb Smirnoff 	if (sv != NULL) {
128a8eb96d5SAlan Somers 		sv[0] = s1;
129a8eb96d5SAlan Somers 		sv[1] = s2;
130*1f46c32cSGleb Smirnoff 	}
131e594026dSAlan Somers 
132e594026dSAlan Somers 	close(s);
133e594026dSAlan Somers 
134*1f46c32cSGleb 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 {
477*1f46c32cSGleb Smirnoff 	int s;
478a8eb96d5SAlan Somers 
479*1f46c32cSGleb 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 {
487*1f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
488*1f46c32cSGleb Smirnoff 	int s, err, s2;
489a8eb96d5SAlan Somers 
490*1f46c32cSGleb 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);
495*1f46c32cSGleb 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 
504a8eb96d5SAlan Somers /* accept(2) can receive a connection */
505a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(accept);
506a8eb96d5SAlan Somers ATF_TC_BODY(accept, tc)
507a8eb96d5SAlan Somers {
508a8eb96d5SAlan Somers 	int sv[2];
509a8eb96d5SAlan Somers 
510a8eb96d5SAlan Somers 	mk_pair_of_sockets(sv);
511e594026dSAlan Somers 	close(sv[0]);
512e594026dSAlan Somers 	close(sv[1]);
513a8eb96d5SAlan Somers }
514a8eb96d5SAlan Somers 
515a8eb96d5SAlan Somers 
516a8eb96d5SAlan Somers /* Set O_NONBLOCK on the socket */
517a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(fcntl_nonblock);
518a8eb96d5SAlan Somers ATF_TC_BODY(fcntl_nonblock, tc)
519a8eb96d5SAlan Somers {
520a8eb96d5SAlan Somers 	int s;
521a8eb96d5SAlan Somers 
522a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
523a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
524a8eb96d5SAlan Somers 	if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
525a8eb96d5SAlan Somers 		perror("fcntl");
526a8eb96d5SAlan Somers 		atf_tc_fail("fcntl failed");
527a8eb96d5SAlan Somers 	}
528e594026dSAlan Somers 	close(s);
529a8eb96d5SAlan Somers }
530a8eb96d5SAlan Somers 
531a8eb96d5SAlan Somers /* Resize the send and receive buffers */
532a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_buffers);
533a8eb96d5SAlan Somers ATF_TC_BODY(resize_buffers, tc)
534a8eb96d5SAlan Somers {
535a8eb96d5SAlan Somers 	int s;
536a8eb96d5SAlan Somers 	int sndbuf = 12345;
537a8eb96d5SAlan Somers 	int rcvbuf = 23456;
538a8eb96d5SAlan Somers 	int xs, xr;
539a8eb96d5SAlan Somers 	socklen_t sl = sizeof(xs);
540a8eb96d5SAlan Somers 
541a8eb96d5SAlan Somers 	s = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
542a8eb96d5SAlan Somers 	ATF_REQUIRE(s >= 0);
543a8eb96d5SAlan Somers 
544a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
545a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  |\n");
546a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
547a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
548a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d |\n", xs, xr);
549a8eb96d5SAlan Somers 
550a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) != 0){
551a8eb96d5SAlan Somers 		perror("setsockopt");
552a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
553a8eb96d5SAlan Somers 	}
554a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
555a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
556a8eb96d5SAlan Somers 	printf("After changing SNDBUF         | %7d | %7d |\n", xs, xr);
557a8eb96d5SAlan Somers 
558a8eb96d5SAlan Somers 	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) != 0){
559a8eb96d5SAlan Somers 		perror("setsockopt");
560a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
561a8eb96d5SAlan Somers 	}
562a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_SNDBUF, &xs, &sl));
563a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(s, SOL_SOCKET, SO_RCVBUF, &xr, &sl));
564a8eb96d5SAlan Somers 	printf("After changing RCVBUF         | %7d | %7d |\n", xs, xr);
565e594026dSAlan Somers 	close(s);
566a8eb96d5SAlan Somers }
567a8eb96d5SAlan Somers 
568a8eb96d5SAlan Somers /*
569a8eb96d5SAlan Somers  * Resize the send and receive buffers of a connected socketpair
570a8eb96d5SAlan Somers  * Print some useful debugging info too
571a8eb96d5SAlan Somers  */
572a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(resize_connected_buffers);
573a8eb96d5SAlan Somers ATF_TC_BODY(resize_connected_buffers, tc)
574a8eb96d5SAlan Somers {
575a8eb96d5SAlan Somers 	int sv[2];
576a8eb96d5SAlan Somers 	int sndbuf = 12345;
577a8eb96d5SAlan Somers 	int rcvbuf = 23456;
578a8eb96d5SAlan Somers 	int err;
579a8eb96d5SAlan Somers 	int ls, lr, rs, rr;
580a8eb96d5SAlan Somers 	socklen_t sl = sizeof(ls);
581a8eb96d5SAlan Somers 
582a8eb96d5SAlan Somers 	/* setup the socket pair */
583a8eb96d5SAlan Somers 	do_socketpair(sv);
584a8eb96d5SAlan Somers 
585a8eb96d5SAlan Somers 	printf("                       Socket Buffer Sizes\n");
586a8eb96d5SAlan Somers 	printf("                              | Left Socket       | Right Socket      |\n");
587a8eb96d5SAlan Somers 	printf("                              | SNDBUF  | RCVBUF  | SNDBUF  | RCVBUF  |\n");
588a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
589a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
590a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
591a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
592a8eb96d5SAlan Somers 	printf("Default                       | %7d | %7d | %7d | %7d |\n",
593a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
594a8eb96d5SAlan Somers 
595a8eb96d5SAlan Somers 	/* Update one side's send buffer */
596a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
597a8eb96d5SAlan Somers 	if (err != 0){
598a8eb96d5SAlan Somers 		perror("setsockopt");
599a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_SNDBUF) failed");
600a8eb96d5SAlan Somers 	}
601a8eb96d5SAlan Somers 
602a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
603a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
604a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
605a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
606a8eb96d5SAlan Somers 	printf("After changing Left's SNDBUF  | %7d | %7d | %7d | %7d |\n",
607a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
608a8eb96d5SAlan Somers 
609a8eb96d5SAlan Somers 	/* Update the same side's receive buffer */
610a8eb96d5SAlan Somers 	err = setsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
611a8eb96d5SAlan Somers 	if (err != 0){
612a8eb96d5SAlan Somers 		perror("setsockopt");
613a8eb96d5SAlan Somers 		atf_tc_fail("setsockopt(SO_RCVBUF) failed");
614a8eb96d5SAlan Somers 	}
615a8eb96d5SAlan Somers 
616a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &ls, &sl));
617a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[0], SOL_SOCKET, SO_RCVBUF, &lr, &sl));
618a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_SNDBUF, &rs, &sl));
619a8eb96d5SAlan Somers 	ATF_CHECK_EQ(0, getsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rr, &sl));
620a8eb96d5SAlan Somers 	printf("After changing Left's RCVBUF  | %7d | %7d | %7d | %7d |\n",
621a8eb96d5SAlan Somers 	    ls, lr, rs, rr);
622e594026dSAlan Somers 	close(sv[0]);
623e594026dSAlan Somers 	close(sv[1]);
624a8eb96d5SAlan Somers }
625a8eb96d5SAlan Somers 
626a8eb96d5SAlan Somers 
627a8eb96d5SAlan Somers /* send(2) and recv(2) a single short record */
628a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv);
629a8eb96d5SAlan Somers ATF_TC_BODY(send_recv, tc)
630a8eb96d5SAlan Somers {
631a8eb96d5SAlan Somers 	int sv[2];
632a8eb96d5SAlan Somers 	const int bufsize = 64;
633a8eb96d5SAlan Somers 	const char *data = "data";
634a8eb96d5SAlan Somers 	char recv_buf[bufsize];
6355d5b721aSAlan Somers 	ssize_t datalen;
636a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
637a8eb96d5SAlan Somers 
638a8eb96d5SAlan Somers 	/* setup the socket pair */
639a8eb96d5SAlan Somers 	do_socketpair(sv);
640a8eb96d5SAlan Somers 
641a8eb96d5SAlan Somers 	/* send and receive a small packet */
642a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
643a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
644a8eb96d5SAlan Somers 	if (ssize < 0) {
645a8eb96d5SAlan Somers 		perror("send");
646a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
647a8eb96d5SAlan Somers 	}
648a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
649a8eb96d5SAlan Somers 	    datalen, ssize);
650a8eb96d5SAlan Somers 
651a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
652a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
653e594026dSAlan Somers 	close(sv[0]);
654e594026dSAlan Somers 	close(sv[1]);
655a8eb96d5SAlan Somers }
656a8eb96d5SAlan Somers 
657a8eb96d5SAlan Somers /* sendto(2) and recvfrom(2) a single short record
658a8eb96d5SAlan Somers  * According to The Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004
659a8eb96d5SAlan Somers  * Edition, sendto(2) is exactly the same as send(2) on a connection-mode socket
660a8eb96d5SAlan Somers  *
661a8eb96d5SAlan Somers  * According to the same spec, not all protocols are required to provide the
662a8eb96d5SAlan Somers  * source addres in recvfrom(2).
663a8eb96d5SAlan Somers  */
664a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendto_recvfrom);
665a8eb96d5SAlan Somers ATF_TC_BODY(sendto_recvfrom, tc)
666a8eb96d5SAlan Somers {
667983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
668*1f46c32cSGleb Smirnoff 	const sockaddr_un *sun;
669983a2d91SEnji Cooper #endif
670a8eb96d5SAlan Somers 	struct sockaddr_storage from;
671a8eb96d5SAlan Somers 	int sv[2];
672a8eb96d5SAlan Somers 	const int bufsize = 64;
673a8eb96d5SAlan Somers 	const char *data = "data";
674a8eb96d5SAlan Somers 	char recv_buf[bufsize];
6755d5b721aSAlan Somers 	ssize_t datalen;
676a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
677a8eb96d5SAlan Somers 	socklen_t fromlen;
678a8eb96d5SAlan Somers 
679a8eb96d5SAlan Somers 	/* setup the socket pair */
680983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
681*1f46c32cSGleb Smirnoff 	sun =
682983a2d91SEnji Cooper #endif
683983a2d91SEnji Cooper 		mk_pair_of_sockets(sv);
684a8eb96d5SAlan Somers 
685a8eb96d5SAlan Somers 	/* send and receive a small packet */
686a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
687a8eb96d5SAlan Somers 	ssize = sendto(sv[0], data, datalen, MSG_EOR, NULL, 0);
688a8eb96d5SAlan Somers 	if (ssize < 0) {
689a8eb96d5SAlan Somers 		perror("send");
690a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
691a8eb96d5SAlan Somers 	}
692a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
693a8eb96d5SAlan Somers 	    datalen, ssize);
694a8eb96d5SAlan Somers 
695a8eb96d5SAlan Somers 	fromlen = sizeof(from);
696a8eb96d5SAlan Somers 	rsize = recvfrom(sv[1], recv_buf, bufsize, MSG_WAITALL,
697a8eb96d5SAlan Somers 	    (struct sockaddr*)&from, &fromlen);
698a8eb96d5SAlan Somers 	if (ssize < 0) {
699a8eb96d5SAlan Somers 		perror("recvfrom");
700a8eb96d5SAlan Somers 		atf_tc_fail("recvfrom returned < 0");
701a8eb96d5SAlan Somers 	}
702a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
703a8eb96d5SAlan Somers 
704983a2d91SEnji Cooper #ifdef TEST_SEQ_PACKET_SOURCE_ADDRESS
705a8eb96d5SAlan Somers 	/*
706a8eb96d5SAlan Somers 	 * FreeBSD does not currently provide the source address for SEQ_PACKET
707a8eb96d5SAlan Somers 	 * AF_UNIX sockets, and POSIX does not require it, so these two checks
708a8eb96d5SAlan Somers 	 * are disabled.  If FreeBSD gains that feature in the future, then
709a8eb96d5SAlan Somers 	 * these checks may be reenabled
710a8eb96d5SAlan Somers 	 */
711983a2d91SEnji Cooper 	ATF_CHECK_EQ(PF_LOCAL, from.ss_family);
712*1f46c32cSGleb Smirnoff 	ATF_CHECK_STREQ(sun->sun_path, ((struct sockaddr_un*)&from)->sun_path);
713983a2d91SEnji Cooper #endif
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 {
754*1f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
7554446a47aSSergey Kandaurov 	const char *data = "data";
756fa5e5f53SEnji Cooper 	ssize_t datalen, ssize;
7574446a47aSSergey Kandaurov 	int s, err, s2;
758a8eb96d5SAlan Somers 
759*1f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
7604446a47aSSergey Kandaurov 
7614446a47aSSergey Kandaurov 	/* Create the other socket */
7624446a47aSSergey Kandaurov 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
7634446a47aSSergey Kandaurov 	ATF_REQUIRE(s2 >= 0);
764*1f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
7654446a47aSSergey Kandaurov 	if (err != 0) {
7664446a47aSSergey Kandaurov 		perror("connect");
7674446a47aSSergey Kandaurov 		atf_tc_fail("connect(2) failed");
7684446a47aSSergey Kandaurov 	}
7694446a47aSSergey Kandaurov 
7704446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
771fa5e5f53SEnji Cooper 	datalen = strlen(data) + 1;	/* +1 for the null */
772a8eb96d5SAlan Somers 	/* USE MSG_NOSIGNAL so we don't get SIGPIPE */
773fa5e5f53SEnji Cooper 	ssize = send(s2, data, datalen, MSG_EOR | MSG_NOSIGNAL);
774a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EPIPE, errno);
775a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, ssize);
776e594026dSAlan Somers 	close(s);
7774446a47aSSergey Kandaurov 	close(s2);
778a8eb96d5SAlan Somers }
779a8eb96d5SAlan Somers 
780a8eb96d5SAlan Somers /* send(2) should cause SIGPIPE on a shutdown socket */
781a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(shutdown_send_sigpipe);
782a8eb96d5SAlan Somers ATF_TC_BODY(shutdown_send_sigpipe, tc)
783a8eb96d5SAlan Somers {
784*1f46c32cSGleb Smirnoff 	const struct sockaddr_un *sun;
7854446a47aSSergey Kandaurov 	const char *data = "data";
786fa5e5f53SEnji Cooper 	ssize_t datalen;
7874446a47aSSergey Kandaurov 	int s, err, s2;
788a8eb96d5SAlan Somers 
789*1f46c32cSGleb Smirnoff 	sun = mk_listening_socket(&s);
7904446a47aSSergey Kandaurov 
7914446a47aSSergey Kandaurov 	/* Create the other socket */
7924446a47aSSergey Kandaurov 	s2 = socket(PF_LOCAL, SOCK_SEQPACKET, 0);
7934446a47aSSergey Kandaurov 	ATF_REQUIRE(s2 >= 0);
794*1f46c32cSGleb Smirnoff 	err = connect(s2, (struct sockaddr *)sun, sizeof(*sun));
7954446a47aSSergey Kandaurov 	if (err != 0) {
7964446a47aSSergey Kandaurov 		perror("connect");
7974446a47aSSergey Kandaurov 		atf_tc_fail("connect(2) failed");
7984446a47aSSergey Kandaurov 	}
7994446a47aSSergey Kandaurov 
8004446a47aSSergey Kandaurov 	ATF_CHECK_EQ(0, shutdown(s2, SHUT_RDWR));
801a8eb96d5SAlan Somers 	ATF_REQUIRE(SIG_ERR != signal(SIGPIPE, shutdown_send_sigpipe_handler));
802fa5e5f53SEnji Cooper 	datalen = strlen(data) + 1;	/* +1 for the null */
8036dd202ceSJohn Baldwin 	(void)send(s2, data, datalen, MSG_EOR);
804a8eb96d5SAlan Somers 	ATF_CHECK_EQ(1, got_sigpipe);
805e594026dSAlan Somers 	close(s);
8064446a47aSSergey Kandaurov 	close(s2);
807a8eb96d5SAlan Somers }
808a8eb96d5SAlan Somers 
809a8eb96d5SAlan Somers /* nonblocking send(2) and recv(2) a single short record */
810a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(send_recv_nonblocking);
811a8eb96d5SAlan Somers ATF_TC_BODY(send_recv_nonblocking, tc)
812a8eb96d5SAlan Somers {
813a8eb96d5SAlan Somers 	int sv[2];
814a8eb96d5SAlan Somers 	const int bufsize = 64;
815a8eb96d5SAlan Somers 	const char *data = "data";
816a8eb96d5SAlan Somers 	char recv_buf[bufsize];
8175d5b721aSAlan Somers 	ssize_t datalen;
818a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
819a8eb96d5SAlan Somers 
820a8eb96d5SAlan Somers 	/* setup the socket pair */
821a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
822a8eb96d5SAlan Somers 
823a8eb96d5SAlan Somers 	/* Verify that there is nothing to receive */
824a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
825a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
826a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
827a8eb96d5SAlan Somers 
828a8eb96d5SAlan Somers 	/* send and receive a small packet */
829a8eb96d5SAlan Somers 	datalen = strlen(data) + 1;	/* +1 for the null */
830a8eb96d5SAlan Somers 	ssize = send(sv[0], data, datalen, MSG_EOR);
831a8eb96d5SAlan Somers 	if (ssize < 0) {
832a8eb96d5SAlan Somers 		perror("send");
833a8eb96d5SAlan Somers 		atf_tc_fail("send returned < 0");
834a8eb96d5SAlan Somers 	}
835a8eb96d5SAlan Somers 	ATF_CHECK_EQ_MSG(datalen, ssize, "expected %zd=send(...) but got %zd",
836a8eb96d5SAlan Somers 	    datalen, ssize);
837a8eb96d5SAlan Somers 
838a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, bufsize, MSG_WAITALL);
839a8eb96d5SAlan Somers 	ATF_CHECK_EQ(datalen, rsize);
840e594026dSAlan Somers 	close(sv[0]);
841e594026dSAlan Somers 	close(sv[1]);
842a8eb96d5SAlan Somers }
843a8eb96d5SAlan Somers 
844a8eb96d5SAlan Somers /*
845a8eb96d5SAlan Somers  * We should get EAGAIN if we try to send a message larger than the socket
846a8eb96d5SAlan Somers  * buffer, with nonblocking sockets.  Test with several different sockbuf sizes
847a8eb96d5SAlan Somers  */
848a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_8k);
849a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_8k, tc)
850a8eb96d5SAlan Somers {
851a8eb96d5SAlan Somers 	test_eagain(8192, 8192);
852a8eb96d5SAlan Somers }
853a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_8k_128k);
854a8eb96d5SAlan Somers ATF_TC_BODY(eagain_8k_128k, tc)
855a8eb96d5SAlan Somers {
856a8eb96d5SAlan Somers 	test_eagain(8192, 131072);
857a8eb96d5SAlan Somers }
858a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_8k);
859a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_8k, tc)
860a8eb96d5SAlan Somers {
861a8eb96d5SAlan Somers 	test_eagain(131072, 8192);
862a8eb96d5SAlan Somers }
863a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(eagain_128k_128k);
864a8eb96d5SAlan Somers ATF_TC_BODY(eagain_128k_128k, tc)
865a8eb96d5SAlan Somers {
866a8eb96d5SAlan Somers 	test_eagain(131072, 131072);
867a8eb96d5SAlan Somers }
868a8eb96d5SAlan Somers 
869a8eb96d5SAlan Somers 
870a8eb96d5SAlan Somers /*
871a8eb96d5SAlan Somers  * nonblocking send(2) and recv(2) of several records, which should collectively
872a8eb96d5SAlan Somers  * fill up the send buffer but not the receive buffer
873a8eb96d5SAlan Somers  */
874a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(rcvbuf_oversized);
875a8eb96d5SAlan Somers ATF_TC_BODY(rcvbuf_oversized, tc)
876a8eb96d5SAlan Somers {
8775d5b721aSAlan Somers 	int i;
878a8eb96d5SAlan Somers 	int sv[2];
8793be7751dSJulio Merino 	const ssize_t pktsize = 1024;
880ea703329SBrooks Davis 	const int sndbufsize = 8192;
881ea703329SBrooks Davis 	const int rcvbufsize = 131072;
8825d5b721aSAlan Somers 	const size_t geometric_mean_bufsize = 32768;
8835d5b721aSAlan Somers 	const int numpkts = geometric_mean_bufsize / pktsize;
884a8eb96d5SAlan Somers 	char sndbuf[pktsize];
885a8eb96d5SAlan Somers 	char recv_buf[pktsize];
886a8eb96d5SAlan Somers 	ssize_t ssize, rsize;
887a8eb96d5SAlan Somers 
888a8eb96d5SAlan Somers 	/* setup the socket pair */
889a8eb96d5SAlan Somers 	do_socketpair_nonblocking(sv);
8905d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[0], SOL_SOCKET, SO_SNDBUF, &sndbufsize,
8915d5b721aSAlan Somers 	    sizeof(sndbufsize)));
8925d5b721aSAlan Somers 	ATF_REQUIRE_EQ(0, setsockopt(sv[1], SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
8935d5b721aSAlan Somers 	    sizeof(rcvbufsize)));
894a8eb96d5SAlan Somers 
895a8eb96d5SAlan Somers 	/*
896a8eb96d5SAlan Somers 	 * Send and receive packets that are collectively greater than the send
897a8eb96d5SAlan Somers 	 * buffer, but less than the receive buffer
898a8eb96d5SAlan Somers 	 */
8995d5b721aSAlan Somers 	for (i=0; i < numpkts; i++) {
900a8eb96d5SAlan Somers 		/* Fill the buffer */
901a8eb96d5SAlan Somers 		memset(sndbuf, i, pktsize);
902a8eb96d5SAlan Somers 
903a8eb96d5SAlan Somers 		/* send the packet */
904a8eb96d5SAlan Somers 		ssize = send(sv[0], sndbuf, pktsize, MSG_EOR);
905a8eb96d5SAlan Somers 		if (ssize < 0) {
906a8eb96d5SAlan Somers 			perror("send");
907a8eb96d5SAlan Somers 			atf_tc_fail("send returned < 0");
908a8eb96d5SAlan Somers 		}
909a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, ssize,
910a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, ssize);
911a8eb96d5SAlan Somers 
912a8eb96d5SAlan Somers 		/* Receive it */
913a8eb96d5SAlan Somers 
914a8eb96d5SAlan Somers 		rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
915a8eb96d5SAlan Somers 		if (rsize < 0) {
916a8eb96d5SAlan Somers 			perror("recv");
917a8eb96d5SAlan Somers 			atf_tc_fail("recv returned < 0");
918a8eb96d5SAlan Somers 		}
919a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(pktsize, rsize,
920a8eb96d5SAlan Somers 		    "expected %zd=send(...) but got %zd", pktsize, rsize);
921a8eb96d5SAlan Somers 
922a8eb96d5SAlan Somers 		/* Verify the contents */
923a8eb96d5SAlan Somers 		ATF_CHECK_EQ_MSG(0, memcmp(sndbuf, recv_buf, pktsize),
924a8eb96d5SAlan Somers 		    "Received data miscompare");
925a8eb96d5SAlan Somers 	}
926a8eb96d5SAlan Somers 
927a8eb96d5SAlan Somers 	/* Trying to receive again should return EAGAIN */
928a8eb96d5SAlan Somers 	rsize = recv(sv[1], recv_buf, pktsize, MSG_WAITALL);
929a8eb96d5SAlan Somers 	ATF_CHECK_EQ(EAGAIN, errno);
930a8eb96d5SAlan Somers 	ATF_CHECK_EQ(-1, rsize);
931e594026dSAlan Somers 	close(sv[0]);
932e594026dSAlan Somers 	close(sv[1]);
933a8eb96d5SAlan Somers }
934a8eb96d5SAlan Somers 
935a8eb96d5SAlan Somers /*
936a8eb96d5SAlan Somers  * Simulate the behavior of a blocking pipe.  The sender will send until his
937a8eb96d5SAlan Somers  * buffer fills up, then we'll simulate a scheduler switch that will allow the
938a8eb96d5SAlan Somers  * receiver to read until his buffer empties.  Repeat the process until the
939a8eb96d5SAlan Somers  * transfer is complete.
940a8eb96d5SAlan Somers  * Repeat the test with multiple send and receive buffer sizes
941a8eb96d5SAlan Somers  */
942a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_8k);
943a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_8k, tc)
944a8eb96d5SAlan Somers {
945a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 8192);
946a8eb96d5SAlan Somers }
947a8eb96d5SAlan Somers 
948a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_8k_128k);
949a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_8k_128k, tc)
950a8eb96d5SAlan Somers {
951a8eb96d5SAlan Somers 	test_pipe_simulator(8192, 131072);
952a8eb96d5SAlan Somers }
953a8eb96d5SAlan Somers 
954a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_8k);
955a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_8k, tc)
956a8eb96d5SAlan Somers {
957a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 8192);
958a8eb96d5SAlan Somers }
959a8eb96d5SAlan Somers 
960a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_simulator_128k_128k);
961a8eb96d5SAlan Somers ATF_TC_BODY(pipe_simulator_128k_128k, tc)
962a8eb96d5SAlan Somers {
963a8eb96d5SAlan Somers 	test_pipe_simulator(131072, 131072);
964a8eb96d5SAlan Somers }
965a8eb96d5SAlan Somers 
966a8eb96d5SAlan Somers /*
967a8eb96d5SAlan Somers  * Test blocking I/O by passing data between two threads.  The total amount of
968a8eb96d5SAlan Somers  * data will be >> buffer size to force blocking.  Repeat the test with multiple
969a8eb96d5SAlan Somers  * send and receive buffer sizes
970a8eb96d5SAlan Somers  */
971a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_8k);
972a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_8k, tc)
973a8eb96d5SAlan Somers {
974a8eb96d5SAlan Somers 	test_pipe(8192, 8192);
975a8eb96d5SAlan Somers }
976a8eb96d5SAlan Somers 
977a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_8k_128k);
978a8eb96d5SAlan Somers ATF_TC_BODY(pipe_8k_128k, tc)
979a8eb96d5SAlan Somers {
980a8eb96d5SAlan Somers 	test_pipe(8192, 131072);
981a8eb96d5SAlan Somers }
982a8eb96d5SAlan Somers 
983a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_8k);
984a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_8k, tc)
985a8eb96d5SAlan Somers {
986a8eb96d5SAlan Somers 	test_pipe(131072, 8192);
987a8eb96d5SAlan Somers }
988a8eb96d5SAlan Somers 
989a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(pipe_128k_128k);
990a8eb96d5SAlan Somers ATF_TC_BODY(pipe_128k_128k, tc)
991a8eb96d5SAlan Somers {
992a8eb96d5SAlan Somers 	test_pipe(131072, 131072);
993a8eb96d5SAlan Somers }
994a8eb96d5SAlan Somers 
995a8eb96d5SAlan Somers 
996a8eb96d5SAlan Somers /*
997a8eb96d5SAlan Somers  * Test single-packet I/O with and without blocking, with symmetric buffers of
998a8eb96d5SAlan Somers  * various sizes
999a8eb96d5SAlan Somers  */
1000a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k);
1001a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k, tc)
1002a8eb96d5SAlan Somers {
1003a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, true);
1004a8eb96d5SAlan Somers }
1005a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k);
1006a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k, tc)
1007a8eb96d5SAlan Somers {
1008a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, true);
1009a8eb96d5SAlan Somers }
1010a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k);
1011a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k, tc)
1012a8eb96d5SAlan Somers {
1013a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, true);
1014a8eb96d5SAlan Somers }
1015a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k);
1016a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k, tc)
1017a8eb96d5SAlan Somers {
1018a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, true);
1019a8eb96d5SAlan Somers }
1020a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k);
1021a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k, tc)
1022a8eb96d5SAlan Somers {
1023a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, true);
1024a8eb96d5SAlan Somers }
1025a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_8k_nonblocking);
1026a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_8k_nonblocking, tc)
1027a8eb96d5SAlan Somers {
1028a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(8 * 1024, false);
1029a8eb96d5SAlan Somers }
1030a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_16k_nonblocking);
1031a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_16k_nonblocking, tc)
1032a8eb96d5SAlan Somers {
1033a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(16 * 1024, false);
1034a8eb96d5SAlan Somers }
1035a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_32k_nonblocking);
1036a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_32k_nonblocking, tc)
1037a8eb96d5SAlan Somers {
1038a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(32 * 1024, false);
1039a8eb96d5SAlan Somers }
1040a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_64k_nonblocking);
1041a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_64k_nonblocking, tc)
1042a8eb96d5SAlan Somers {
1043a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(64 * 1024, false);
1044a8eb96d5SAlan Somers }
1045a8eb96d5SAlan Somers ATF_TC_WITHOUT_HEAD(sendrecv_128k_nonblocking);
1046a8eb96d5SAlan Somers ATF_TC_BODY(sendrecv_128k_nonblocking, tc)
1047a8eb96d5SAlan Somers {
1048a8eb96d5SAlan Somers 	test_sendrecv_symmetric_buffers(128 * 1024, false);
1049a8eb96d5SAlan Somers }
1050a8eb96d5SAlan Somers 
1051a8eb96d5SAlan Somers 
1052a8eb96d5SAlan Somers /*
1053a8eb96d5SAlan Somers  * Main.
1054a8eb96d5SAlan Somers  */
1055a8eb96d5SAlan Somers 
1056a8eb96d5SAlan Somers ATF_TP_ADD_TCS(tp)
1057a8eb96d5SAlan Somers {
1058a8eb96d5SAlan Somers 	/* Basic creation and connection tests */
1059a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socket);
1060a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, create_socketpair);
1061a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_unbound);
1062a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, bind);
1063a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, listen_bound);
1064a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, connect);
1065a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, accept);
1066a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, fcntl_nonblock);
1067a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_buffers);
1068a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, resize_connected_buffers);
1069a8eb96d5SAlan Somers 
1070a8eb96d5SAlan Somers 	/* Unthreaded I/O tests */
1071a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv);
1072a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_nonblocking);
1073a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, send_recv_with_connect);
1074a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendto_recvfrom);
1075a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send);
1076a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, shutdown_send_sigpipe);
1077a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_8k);
1078a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_8k_128k);
1079a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_8k);
1080a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, eagain_128k_128k);
1081a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k);
1082a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k);
1083a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k);
1084a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k);
1085a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k);
1086a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_8k_nonblocking);
1087a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_16k_nonblocking);
1088a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_32k_nonblocking);
1089a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_64k_nonblocking);
1090a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, sendrecv_128k_nonblocking);
1091a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, rcvbuf_oversized);
1092a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_8k);
1093a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_8k_128k);
1094a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_8k);
1095a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_simulator_128k_128k);
1096a8eb96d5SAlan Somers 
1097a8eb96d5SAlan Somers 	/* Threaded I/O tests with blocking sockets */
1098a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_8k);
1099a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_8k_128k);
1100a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_8k);
1101a8eb96d5SAlan Somers 	ATF_TP_ADD_TC(tp, pipe_128k_128k);
1102a8eb96d5SAlan Somers 
1103a8eb96d5SAlan Somers 	return atf_no_error();
1104a8eb96d5SAlan Somers }
1105