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