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