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