source: rtems-libbsd/testsuite/selectpollkqueue01/test_main.c @ 666a568

5-freebsd-12
Last change on this file since 666a568 was 666a568, checked in by Sebastian Huber <sebastian.huber@…>, on Aug 25, 2017 at 12:23:18 PM

Include missing <string.h> and <limits.h>

Fix warnings.

Update #2132.
Update #2133.

  • Property mode set to 100755
File size: 21.9 KB
Line 
1/*
2 * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/types.h>
34#include <sys/event.h>
35#include <sys/filio.h>
36#include <sys/select.h>
37#include <sys/socket.h>
38#include <sys/stat.h>
39#include <sys/time.h>
40#include <arpa/inet.h>
41#include <netinet/in.h>
42#include <assert.h>
43#include <errno.h>
44#include <fcntl.h>
45#include <inttypes.h>
46#include <poll.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <sysexits.h>
51#include <unistd.h>
52
53#include <machine/rtems-bsd-commands.h>
54
55#include <rtems/libcsupport.h>
56#include <rtems.h>
57
58#define TEST_NAME "LIBBSD SELECT AND POLL AND KQUEUE AND PIPE 1"
59
60#define PRIO_MASTER 1
61
62#define PRIO_WORKER 2
63
64#define EVENT_READ RTEMS_EVENT_0
65
66#define EVENT_WRITE RTEMS_EVENT_1
67
68#define EVENT_CONNECT RTEMS_EVENT_2
69
70#define EVENT_CLOSE RTEMS_EVENT_3
71
72#define EVENT_SHUTDOWN RTEMS_EVENT_4
73
74#define EVENT_CLOSE_PIPE RTEMS_EVENT_5
75
76#define BUF_SIZE 4096
77
78#define PORT 1234
79
80#define TEST_UDATA ((void *) 0xcafe)
81
82typedef struct {
83        char buf[BUF_SIZE];
84        const char *wbuf;
85        char *rbuf;
86        size_t rn;
87        size_t wn;
88        int lfd;
89        int cfd;
90        int afd;
91        int rfd;
92        int wfd;
93        int pfd[2];
94        struct sockaddr_in caddr;
95        rtems_id worker_task;
96} test_context;
97
98static test_context test_instance = {
99        .cfd = -1
100};
101
102static const char msg[] = "This is a message.  One two three.";
103
104static void
105setup_lo0(void)
106{
107        int exit_code;
108        char *lo0[] = {
109                "ifconfig",
110                "lo0",
111                "inet",
112                "127.0.0.1",
113                "netmask",
114                "255.255.255.0",
115                NULL
116        };
117
118        exit_code = rtems_bsd_command_ifconfig(RTEMS_ARRAY_SIZE(lo0) - 1, lo0);
119        assert(exit_code == EX_OK);
120}
121
122static void
123set_self_prio(rtems_task_priority prio)
124{
125        rtems_status_code sc;
126
127        sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
128        assert(sc == RTEMS_SUCCESSFUL);
129}
130
131static void
132create_server_socket(test_context *ctx)
133{
134        struct sockaddr_in saddr;
135        int rv;
136        int lfd;
137
138        lfd = socket(PF_INET, SOCK_STREAM, 0);
139        assert(lfd >= 0);
140
141        memset(&saddr, 0, sizeof(saddr));
142        saddr.sin_family = AF_INET;
143        saddr.sin_port = htons(PORT);
144        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
145
146        rv = bind(lfd, (const struct sockaddr *) &saddr, sizeof(saddr));
147        assert(rv == 0);
148
149        rv = listen(lfd, 1);
150        assert(rv == 0);
151
152        ctx->lfd = lfd;
153}
154
155static void
156create_client_addr(test_context *ctx)
157{
158        struct sockaddr_in *caddr = &ctx->caddr;;
159        int ok;
160
161        memset(caddr, 0, sizeof(*caddr));
162        caddr->sin_family = AF_INET;
163        caddr->sin_port = htons(PORT);
164        ok = inet_aton("127.0.0.1", &caddr->sin_addr);
165        assert(ok != 0);
166}
167
168static void
169worker_task(rtems_task_argument arg)
170{
171        test_context *ctx = (test_context *) arg;
172
173        while (true) {
174                rtems_status_code sc;
175                rtems_event_set events;
176                ssize_t n;
177                int rv;
178                int cfd = ctx->cfd;
179                int rfd = ctx->pfd[0];
180                int wfd = ctx->pfd[1];
181
182                sc = rtems_event_receive(
183                        RTEMS_ALL_EVENTS,
184                        RTEMS_EVENT_ANY | RTEMS_WAIT,
185                        RTEMS_NO_TIMEOUT,
186                        &events
187                );
188                assert(sc == RTEMS_SUCCESSFUL);
189
190                if ((events & EVENT_READ) != 0) {
191                        puts("worker: read");
192
193                        n = read(ctx->rfd, &ctx->rbuf[0], ctx->rn);
194                        assert(n == (ssize_t) ctx->rn);
195                }
196
197                if ((events & EVENT_WRITE) != 0) {
198                        puts("worker: write");
199
200                        n = write(ctx->wfd, &ctx->wbuf[0], ctx->wn);
201                        assert(n == (ssize_t) ctx->wn);
202                }
203
204                if ((events & EVENT_CONNECT) != 0) {
205                        if (cfd >= 0) {
206                                puts("worker: close connect socket");
207
208                                ctx->cfd = -1;
209
210                                rv = close(cfd);
211                                assert(rv == 0);
212
213                                cfd = -1;
214                        }
215
216                        if (cfd < 0) {
217                                puts("worker: create new connect socket");
218
219                                cfd = socket(PF_INET, SOCK_STREAM, 0);
220                                assert(cfd >= 0);
221
222                                ctx->cfd = cfd;
223                        }
224
225                        puts("worker: connect");
226
227                        rv = connect(
228                                cfd,
229                                (const struct sockaddr *) &ctx->caddr,
230                                sizeof(ctx->caddr)
231                        );
232                        assert(rv == 0);
233                }
234
235                if ((events & EVENT_CLOSE) != 0) {
236                        puts("worker: close");
237
238                        ctx->cfd = -1;
239
240                        rv = close(cfd);
241                        assert(rv == 0);
242                }
243
244                if ((events & EVENT_CLOSE_PIPE) != 0) {
245                        puts("worker: close pipe");
246
247                        ctx->pfd[0] = -1;
248                        ctx->pfd[1] = -1;
249
250                        rv = close(wfd);
251                        assert(rv == 0);
252
253                        rv = close(rfd);
254                        assert(rv == 0);
255                }
256
257                if ((events & EVENT_SHUTDOWN) != 0) {
258                        puts("worker: shutdown");
259
260                        rv = shutdown(cfd, SHUT_RDWR);
261                        assert(rv == 0);
262                }
263        }
264}
265
266static void
267send_events(test_context *ctx, rtems_event_set events)
268{
269        rtems_status_code sc;
270
271        sc = rtems_event_send(ctx->worker_task, events);
272        assert(sc == RTEMS_SUCCESSFUL);
273}
274
275static void
276start_worker(test_context *ctx)
277{
278        rtems_status_code sc;
279
280        sc = rtems_task_create(
281                rtems_build_name('W', 'O', 'R', 'K'),
282                PRIO_WORKER,
283                RTEMS_MINIMUM_STACK_SIZE,
284                RTEMS_DEFAULT_MODES,
285                RTEMS_FLOATING_POINT,
286                &ctx->worker_task
287        );
288        assert(sc == RTEMS_SUCCESSFUL);
289
290        sc = rtems_task_start(
291                ctx->worker_task,
292                worker_task,
293                (rtems_task_argument) ctx
294        );
295        assert(sc == RTEMS_SUCCESSFUL);
296}
297
298static void
299set_non_blocking(int fd, int enable)
300{
301        int rv;
302        int flags = fcntl(fd, F_GETFL, 0);
303
304        if (enable) {
305                rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
306        } else {
307                rv = fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
308        }
309        assert(rv == 0);
310}
311
312static void
313test_select_timeout(test_context *ctx)
314{
315        struct timeval timeout = {
316                .tv_sec = 0,
317                .tv_usec = 100000
318        };
319        int fd = ctx->lfd;
320        int nfds = fd + 1;
321        struct fd_set set;
322        int rv;
323        int i;
324
325        puts("test select timeout");
326
327        set_non_blocking(ctx->lfd, 0);
328
329        FD_ZERO(&set);
330        FD_SET(fd, &set);
331
332        rv = select(nfds, &set, NULL, NULL, &timeout);
333        assert(rv == 0);
334
335        for (i = 0; i < nfds; ++i) {
336                assert(!FD_ISSET(i, &set));
337        }
338
339        rv = select(nfds, NULL, &set, NULL, &timeout);
340        assert(rv == 0);
341
342        for (i = 0; i < nfds; ++i) {
343                assert(!FD_ISSET(i, &set));
344        }
345
346        rv = select(nfds, NULL, NULL, &set, &timeout);
347        assert(rv == 0);
348
349        for (i = 0; i < nfds; ++i) {
350                assert(!FD_ISSET(i, &set));
351        }
352}
353
354static void
355test_select_connect(test_context *ctx)
356{
357        int lfd = ctx->lfd;
358        int afd = ctx->afd;
359        int nfds = lfd + 1;
360        struct fd_set set;
361        int rv;
362        int i;
363
364        puts("test select connect");
365
366        if (afd >= 0) {
367                rv = close(afd);
368                assert(rv == 0);
369        }
370
371        send_events(ctx, EVENT_CONNECT);
372
373        set_non_blocking(lfd, 1);
374
375        errno = 0;
376        afd = accept(lfd, NULL, NULL);
377        assert(afd == -1);
378        assert(errno == EAGAIN);
379
380        set_non_blocking(lfd, 0);
381
382        FD_ZERO(&set);
383        FD_SET(lfd, &set);
384
385        rv = select(nfds, &set, NULL, NULL, NULL);
386        assert(rv == 1);
387
388        for (i = 0; i < nfds; ++i) {
389                bool is_set_expected = i == lfd;
390                bool is_set = FD_ISSET(i, &set);
391
392                assert(is_set_expected == is_set);
393        }
394
395        afd = accept(lfd, NULL, NULL);
396        assert(afd >= 0);
397
398        ctx->afd = afd;
399}
400
401static void
402test_select_read(test_context *ctx)
403{
404        int afd = ctx->afd;
405        int cfd = ctx->cfd;
406        int nfds = afd + 1;
407        struct fd_set set;
408        int rv;
409        int i;
410        ssize_t n;
411
412        puts("test select read");
413
414        assert(afd >= 0);
415        assert(cfd >= 0);
416
417        ctx->wfd = cfd;
418        ctx->wbuf = &msg[0];
419        ctx->wn = sizeof(msg);
420        send_events(ctx, EVENT_WRITE);
421
422        set_non_blocking(afd, 1);
423
424        errno = 0;
425        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
426        assert(n == -1);
427        assert(errno == EAGAIN);
428
429        FD_ZERO(&set);
430        FD_SET(afd, &set);
431
432        rv = select(nfds, &set, NULL, NULL, NULL);
433        assert(rv == 1);
434
435        for (i = 0; i < nfds; ++i) {
436                bool is_set_expected = i == afd;
437                bool is_set = FD_ISSET(i, &set);
438
439                assert(is_set_expected == is_set);
440        }
441
442        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
443        assert(n == (ssize_t) sizeof(msg));
444        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
445}
446
447static void
448test_select_write(test_context *ctx)
449{
450        int afd = ctx->afd;
451        int cfd = ctx->cfd;
452        int nfds = afd + 1;
453        struct fd_set set;
454        int rv;
455        int i;
456        ssize_t n;
457
458        puts("test select write");
459
460        assert(afd >= 0);
461        assert(cfd >= 0);
462
463        ctx->rfd = cfd;
464        ctx->rbuf = &ctx->buf[0];
465        ctx->rn = sizeof(ctx->buf);
466        send_events(ctx, EVENT_READ);
467
468        set_non_blocking(afd, 1);
469
470        do {
471                errno = 0;
472                n = write(afd, &ctx->buf[0], sizeof(ctx->buf));
473                if (n == -1) {
474                        assert(errno == EAGAIN);
475                }
476        } while (n > 0);
477
478        FD_ZERO(&set);
479        FD_SET(afd, &set);
480
481        rv = select(nfds, NULL, &set, NULL, NULL);
482        assert(rv == 1);
483
484        for (i = 0; i < nfds; ++i) {
485                bool is_set_expected = i == afd;
486                bool is_set = FD_ISSET(i, &set);
487
488                assert(is_set_expected == is_set);
489        }
490
491        n = write(afd, &ctx->buf[0], 1);
492        assert(n == 1);
493}
494
495static void
496test_select_close(test_context *ctx)
497{
498        int cfd = ctx->cfd;
499        int nfds = cfd + 1;
500        struct fd_set set;
501        int rv;
502
503        puts("test select close");
504
505        assert(ctx->cfd >= 0);
506
507        send_events(ctx, EVENT_CLOSE);
508
509        assert(ctx->cfd >= 0);
510
511        FD_ZERO(&set);
512        FD_SET(cfd, &set);
513
514        errno = 0;
515        rv = select(nfds, NULL, NULL, &set, NULL);
516        assert(rv == -1);
517        assert(errno == EBADF);
518
519        assert(ctx->cfd == -1);
520}
521
522static void
523test_poll_timeout(test_context *ctx)
524{
525        static const short events[] = {
526                POLLIN,
527                POLLPRI,
528                POLLOUT,
529                POLLRDNORM,
530                POLLWRNORM,
531                POLLRDBAND,
532                POLLWRBAND
533        };
534
535        int timeout = 100;
536        struct pollfd pfd = {
537                .fd = ctx->lfd
538        };
539        size_t i;
540
541        puts("test poll timeout");
542
543        for (i = 0; i < nitems(events); ++i) {
544                int rv;
545
546                pfd.events = events[i];
547                pfd.revents = 0;
548
549                rv = poll(&pfd, 1, timeout);
550                assert(rv == 0);
551        }
552}
553
554static void
555test_poll_connect(test_context *ctx)
556{
557        int lfd = ctx->lfd;
558        int afd = ctx->afd;
559        struct pollfd pfd = {
560                .fd = lfd,
561                .events = POLLIN
562        };
563        int timeout = -1;
564        int rv;
565
566        puts("test poll connect");
567
568        if (afd >= 0) {
569                rv = close(afd);
570                assert(rv == 0);
571        }
572
573        send_events(ctx, EVENT_CONNECT);
574
575        set_non_blocking(lfd, 1);
576
577        errno = 0;
578        afd = accept(lfd, NULL, NULL);
579        assert(afd == -1);
580        assert(errno == EAGAIN);
581
582        set_non_blocking(lfd, 0);
583
584        rv = poll(&pfd, 1, timeout);
585        assert(rv == 1);
586        assert(pfd.revents == POLLIN);
587
588        afd = accept(lfd, NULL, NULL);
589        assert(afd >= 0);
590
591        ctx->afd = afd;
592}
593
594static void
595test_poll_read(test_context *ctx)
596{
597        int afd = ctx->afd;
598        int cfd = ctx->cfd;
599        struct pollfd pfd = {
600                .fd = afd,
601                .events = POLLIN
602        };
603        int timeout = -1;
604        int rv;
605        ssize_t n;
606
607        puts("test poll read");
608
609        assert(afd >= 0);
610        assert(cfd >= 0);
611
612        ctx->wfd = cfd;
613        ctx->wbuf = &msg[0];
614        ctx->wn = sizeof(msg);
615        send_events(ctx, EVENT_WRITE);
616
617        set_non_blocking(afd, 1);
618
619        errno = 0;
620        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
621        assert(n == -1);
622        assert(errno == EAGAIN);
623
624        rv = poll(&pfd, 1, timeout);
625        assert(rv == 1);
626        assert(pfd.revents == POLLIN);
627
628        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
629        assert(n == (ssize_t) sizeof(msg));
630        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
631}
632
633static void
634test_poll_write(test_context *ctx)
635{
636        int afd = ctx->afd;
637        int cfd = ctx->cfd;
638        struct pollfd pfd = {
639                .fd = afd,
640                .events = POLLOUT
641        };
642        int timeout = -1;
643        int rv;
644        ssize_t n;
645
646        puts("test poll write");
647
648        assert(afd >= 0);
649        assert(cfd >= 0);
650
651        ctx->rfd = cfd;
652        ctx->rbuf = &ctx->buf[0];
653        ctx->rn = sizeof(ctx->buf);
654        send_events(ctx, EVENT_READ);
655
656        set_non_blocking(afd, 1);
657
658        do {
659                errno = 0;
660                n = write(afd, &ctx->buf[0], sizeof(ctx->buf));
661                if (n == -1) {
662                        assert(errno == EAGAIN);
663                }
664        } while (n > 0);
665
666        rv = poll(&pfd, 1, timeout);
667        assert(rv == 1);
668        assert(pfd.revents == POLLOUT);
669
670        n = write(afd, &ctx->buf[0], 1);
671        assert(n == 1);
672}
673
674static void
675test_poll_close(test_context *ctx)
676{
677        int cfd = ctx->cfd;
678        struct pollfd pfd = {
679                .fd = cfd,
680                .events = POLLRDBAND
681        };
682        int timeout = -1;
683        int rv;
684
685        puts("test poll close");
686
687        assert(ctx->cfd >= 0);
688
689        send_events(ctx, EVENT_CLOSE);
690
691        assert(ctx->cfd >= 0);
692
693        rv = poll(&pfd, 1, timeout);
694        assert(rv == 1);
695        assert(pfd.revents == POLLNVAL);
696
697        assert(ctx->cfd == -1);
698}
699
700static void
701test_kqueue_timer(bool do_resource_check)
702{
703        rtems_resource_snapshot snapshot;
704        int kq;
705        int rv;
706        struct kevent change;
707        int i;
708
709        puts("test kqueue timer");
710
711        if (do_resource_check) {
712                rtems_resource_snapshot_take(&snapshot);
713        }
714
715        kq = kqueue();
716        assert(kq >= 0);
717
718        EV_SET(&change, 0xbeef, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, 100,
719            TEST_UDATA);
720
721        rv = kevent(kq, &change, 1, NULL, 0, NULL);
722        assert(rv == 0);
723
724        for (i = 0; i < 5; ++i) {
725                struct kevent event;
726
727                rv = kevent(kq, NULL, 0, &event, 1, NULL);
728                assert(rv == 1);
729                assert(event.ident == 0xbeef);
730                assert(event.filter == EVFILT_TIMER);
731                assert(event.flags == EV_CLEAR);
732                assert(event.fflags == 0);
733                assert(event.data == 1);
734                assert(event.udata == TEST_UDATA);
735        }
736
737        rv = close(kq);
738        assert(rv == 0);
739
740        if (do_resource_check) {
741                assert(rtems_resource_snapshot_check(&snapshot));
742        }
743}
744
745static void
746test_kqueue_connect(test_context *ctx)
747{
748        int lfd = ctx->lfd;
749        int afd = ctx->afd;
750        int kq;
751        struct kevent change;
752        struct kevent event;
753        const struct timespec *timeout = NULL;
754        int rv;
755
756        puts("test kqueue connect");
757
758        if (afd >= 0) {
759                rv = close(afd);
760                assert(rv == 0);
761        }
762
763        kq = kqueue();
764        assert(kq >= 0);
765
766        EV_SET(&change, lfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
767            TEST_UDATA);
768
769        rv = kevent(kq, &change, 1, NULL, 0, timeout);
770        assert(rv == 0);
771
772        send_events(ctx, EVENT_CONNECT);
773
774        set_non_blocking(lfd, 1);
775
776        errno = 0;
777        afd = accept(lfd, NULL, NULL);
778        assert(afd == -1);
779        assert(errno == EAGAIN);
780
781        set_non_blocking(lfd, 0);
782
783        rv = kevent(kq, NULL, 0, &event, 1, timeout);
784        assert(rv == 1);
785        assert(event.ident == lfd);
786        assert(event.filter == EVFILT_READ);
787        assert(event.flags == 0);
788        assert(event.fflags == 0);
789        assert(event.data == 1);
790        assert(event.udata == TEST_UDATA);
791
792        afd = accept(lfd, NULL, NULL);
793        assert(afd >= 0);
794
795        ctx->afd = afd;
796
797        rv = close(kq);
798        assert(rv == 0);
799}
800
801static void
802test_kqueue_read(test_context *ctx)
803{
804        int afd = ctx->afd;
805        int cfd = ctx->cfd;
806        int kq;
807        struct kevent change;
808        struct kevent event;
809        const struct timespec *timeout = NULL;
810        int rv;
811        ssize_t n;
812
813        puts("test kqueue read");
814
815        assert(afd >= 0);
816        assert(cfd >= 0);
817
818        kq = kqueue();
819        assert(kq >= 0);
820
821        EV_SET(&change, afd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
822            TEST_UDATA);
823
824        rv = kevent(kq, &change, 1, NULL, 0, timeout);
825        assert(rv == 0);
826
827        ctx->wfd = cfd;
828        ctx->wbuf = &msg[0];
829        ctx->wn = sizeof(msg);
830        send_events(ctx, EVENT_WRITE);
831
832        set_non_blocking(afd, 1);
833
834        errno = 0;
835        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
836        assert(n == -1);
837        assert(errno == EAGAIN);
838
839        rv = kevent(kq, NULL, 0, &event, 1, timeout);
840        assert(rv == 1);
841        assert(event.ident == afd);
842        assert(event.filter == EVFILT_READ);
843        assert(event.flags == 0);
844        assert(event.fflags == 0);
845        assert(event.data == sizeof(msg));
846        assert(event.udata == TEST_UDATA);
847
848        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
849        assert(n == (ssize_t) sizeof(msg));
850        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
851
852        rv = close(kq);
853        assert(rv == 0);
854}
855
856static void
857test_kqueue_write(test_context *ctx)
858{
859        int afd = ctx->afd;
860        int cfd = ctx->cfd;
861        int kq;
862        struct kevent change;
863        struct kevent event;
864        const struct timespec *timeout = NULL;
865        int rv;
866        ssize_t n;
867
868        puts("test kqueue write");
869
870        assert(afd >= 0);
871        assert(cfd >= 0);
872
873        kq = kqueue();
874        assert(kq >= 0);
875
876        EV_SET(&change, afd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0,
877            TEST_UDATA);
878
879        rv = kevent(kq, &change, 1, NULL, 0, timeout);
880        assert(rv == 0);
881
882        ctx->rfd = cfd;
883        ctx->rbuf = &ctx->buf[0];
884        ctx->rn = sizeof(ctx->buf);
885        send_events(ctx, EVENT_READ);
886
887        set_non_blocking(afd, 1);
888
889        do {
890                errno = 0;
891                n = write(afd, &ctx->buf[0], sizeof(ctx->buf));
892                if (n == -1) {
893                        assert(errno == EAGAIN);
894                }
895        } while (n > 0);
896
897        rv = kevent(kq, NULL, 0, &event, 1, timeout);
898        assert(rv == 1);
899        assert(event.ident == afd);
900        assert(event.filter == EVFILT_WRITE);
901        assert(event.flags == 0);
902        assert(event.fflags == 0);
903        assert(event.data == 20428);
904        assert(event.udata == TEST_UDATA);
905
906        n = write(afd, &ctx->buf[0], 1);
907        assert(n == 1);
908
909        rv = close(kq);
910        assert(rv == 0);
911}
912
913static void
914test_kqueue_close(test_context *ctx)
915{
916        int cfd = ctx->cfd;
917        int kq;
918        struct kevent change;
919        struct kevent event;
920        const struct timespec *timeout = NULL;
921        int rv;
922        ssize_t n;
923        mode_t canrecv = S_IRUSR | S_IRGRP | S_IROTH;
924        mode_t cansend = S_IWUSR | S_IWGRP | S_IWOTH;
925        struct stat st;
926
927        puts("test kqueue close");
928
929        assert(ctx->cfd >= 0);
930
931        kq = kqueue();
932        assert(kq >= 0);
933
934        EV_SET(&change, cfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
935            TEST_UDATA);
936
937        rv = kevent(kq, &change, 1, NULL, 0, timeout);
938        assert(rv == 0);
939
940        set_non_blocking(cfd, 1);
941
942        do {
943                errno = 0;
944                n = read(cfd, &ctx->buf[0], sizeof(ctx->buf));
945                if (n == -1) {
946                        assert(errno == EAGAIN);
947                }
948        } while (n > 0);
949
950        /*
951         * It is not allowed to close file descriptors still in use by
952         * kevent().  On FreeBSD the file descriptor reference counting would
953         * prevent this also.
954         */
955        send_events(ctx, EVENT_SHUTDOWN);
956
957        rv = fstat(cfd, &st);
958        assert(rv == 0);
959        assert(st.st_mode == (S_IFSOCK | canrecv | cansend));
960
961        rv = kevent(kq, NULL, 0, &event, 1, timeout);
962        assert(rv == 1);
963        assert(event.ident == cfd);
964        assert(event.filter == EVFILT_READ);
965        assert(event.flags == EV_EOF);
966        assert(event.fflags == 0);
967        assert(event.data == 0);
968        assert(event.udata == TEST_UDATA);
969
970        /*
971         * The master task wakes up during the shutdown() operation.  So we do
972         * not see the full shutdown.
973         */
974        rv = fstat(cfd, &st);
975        assert(rv == 0);
976        assert(st.st_mode == (S_IFSOCK | cansend));
977
978        rv = close(kq);
979        assert(rv == 0);
980}
981
982static void
983test_kqueue_user(test_context *ctx)
984{
985        int kq;
986        uintptr_t ident;
987        u_int flag;
988        struct kevent change;
989        struct kevent trigger;
990        struct kevent event;
991        const struct timespec *timeout = NULL;
992        int rv;
993
994        puts("test kqueue user");
995
996        ident = 0xabc;
997        flag = 0x1;
998
999        kq = kqueue();
1000        assert(kq >= 0);
1001
1002        EV_SET(&change, ident, EVFILT_USER, EV_ADD | EV_ENABLE, NOTE_FFNOP, 0,
1003            TEST_UDATA);
1004
1005        rv = kevent(kq, &change, 1, NULL, 0, timeout);
1006        assert(rv == 0);
1007
1008        ident = 0xabc;
1009        EV_SET(&trigger, ident, EVFILT_USER, 0, NOTE_TRIGGER | NOTE_FFCOPY |
1010            flag, 0, TEST_UDATA);
1011
1012        rv = kevent(kq, &trigger, 1, NULL, 0, timeout);
1013        assert(rv == 0);
1014
1015        memset(&event, 0, sizeof(event));
1016        rv = kevent(kq, NULL, 0, &event, 1, timeout);
1017        assert(rv == 1);
1018        assert(event.ident == ident);
1019        assert(event.filter == EVFILT_USER);
1020        assert(event.flags == 0);
1021        assert(event.fflags == flag);
1022        assert(event.data == 0);
1023        assert(event.udata == TEST_UDATA);
1024
1025        rv = close(kq);
1026        assert(rv == 0);
1027}
1028
1029static void
1030test_pipe_timeout(test_context *ctx)
1031{
1032        struct pipe_poll_events
1033        {
1034                short event;
1035                int rv;
1036        };
1037        const struct pipe_poll_events events[] = {
1038                { POLLIN, 0 },
1039                { POLLPRI, 0 },
1040                { POLLOUT, 1 },
1041                { POLLRDNORM, 0 },
1042                { POLLWRNORM, 1 },
1043                { POLLRDBAND, 0 },
1044                { POLLWRBAND, 0 },
1045                { POLLINIGNEOF, 0 }
1046        };
1047
1048        int timeout = 100;
1049        struct pollfd pfd;
1050        size_t i;
1051        int rv;
1052
1053        puts("test pipe timeout");
1054
1055        rv = pipe(ctx->pfd);
1056        assert(rv == 0);
1057
1058        pfd.fd = ctx->pfd[1];
1059
1060        for (i = 0; i < nitems(events); ++i) {
1061                int rv;
1062
1063                pfd.events = events[i].event;
1064                pfd.revents = 0;
1065
1066                rv = poll(&pfd, 1, timeout);
1067                assert(rv == events[i].rv);
1068        }
1069}
1070
1071static void
1072test_pipe_read(test_context *ctx)
1073{
1074        int rfd = ctx->pfd[0];
1075        int wfd = ctx->pfd[1];
1076        struct pollfd pfd = {
1077                .fd = rfd,
1078                .events = POLLIN
1079        };
1080        int timeout = -1;
1081        int rv;
1082        ssize_t n;
1083
1084        puts("test pipe read");
1085
1086        assert(rfd >= 0);
1087        assert(wfd >= 0);
1088
1089        ctx->wfd = wfd;
1090        ctx->wbuf = &msg[0];
1091        ctx->wn = sizeof(msg);
1092        send_events(ctx, EVENT_WRITE);
1093
1094        set_non_blocking(rfd, 1);
1095
1096        errno = 0;
1097        n = read(rfd, &ctx->buf[0], sizeof(ctx->buf));
1098        assert(n == -1);
1099        assert(errno == EAGAIN);
1100
1101        rv = poll(&pfd, 1, timeout);
1102        assert(rv == 1);
1103        assert(pfd.revents == POLLIN);
1104
1105        n = read(rfd, &ctx->buf[0], sizeof(ctx->buf));
1106        assert(n == (ssize_t) sizeof(msg));
1107        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
1108}
1109
1110static void
1111test_pipe_write(test_context *ctx)
1112{
1113        int rfd = ctx->pfd[0];
1114        int wfd = ctx->pfd[1];
1115        struct pollfd pfd = {
1116                .fd = wfd,
1117                .events = POLLOUT
1118        };
1119        int timeout = -1;
1120        int rv;
1121        ssize_t n;
1122
1123        puts("test pipe write");
1124
1125        assert(rfd >= 0);
1126        assert(wfd >= 0);
1127
1128        ctx->rfd = rfd;
1129        ctx->rbuf = &ctx->buf[0];
1130        ctx->rn = sizeof(ctx->buf);
1131        send_events(ctx, EVENT_READ);
1132
1133        set_non_blocking(wfd, 1);
1134
1135        do {
1136                errno = 0;
1137                n = write(wfd, &ctx->buf[0], sizeof(ctx->buf));
1138                if (n == -1) {
1139                        assert(errno == EAGAIN);
1140                }
1141        } while (n > 0);
1142
1143        rv = poll(&pfd, 1, timeout);
1144        assert(rv == 1);
1145        assert(pfd.revents == POLLOUT);
1146}
1147
1148static void
1149test_pipe_close(test_context *ctx)
1150{
1151        int rfd = ctx->pfd[0];
1152        struct pollfd pfd = {
1153                .fd = rfd,
1154                .events = POLLIN
1155        };
1156        int timeout = -1;
1157        int rv;
1158
1159        puts("test pipe close");
1160
1161        assert(ctx->pfd[0] >= 0);
1162        assert(ctx->pfd[1] >= 0);
1163
1164        send_events(ctx, EVENT_CLOSE_PIPE);
1165
1166        set_non_blocking(rfd, 0);
1167
1168        assert(ctx->pfd[0] >= 0);
1169        assert(ctx->pfd[1] >= 0);
1170
1171        rv = poll(&pfd, 1, timeout);
1172        assert(rv == 1);
1173        assert(pfd.revents == (POLLIN | POLLHUP));
1174
1175        assert(ctx->pfd[0] == -1);
1176        assert(ctx->pfd[1] == -1);
1177}
1178
1179static void
1180test_main(void)
1181{
1182        test_context *ctx = &test_instance;
1183
1184        setup_lo0();
1185        set_self_prio(PRIO_MASTER);
1186        start_worker(ctx);
1187        create_server_socket(ctx);
1188        create_client_addr(ctx);
1189
1190        test_select_timeout(ctx);
1191        test_select_connect(ctx);
1192        test_select_read(ctx);
1193        test_select_write(ctx);
1194        test_select_close(ctx);
1195
1196        test_poll_timeout(ctx);
1197        test_poll_connect(ctx);
1198        test_poll_read(ctx);
1199        test_poll_write(ctx);
1200        test_poll_close(ctx);
1201
1202        test_kqueue_timer(false);
1203        test_kqueue_timer(true);
1204        test_kqueue_connect(ctx);
1205        test_kqueue_read(ctx);
1206        test_kqueue_write(ctx);
1207        test_kqueue_close(ctx);
1208        test_kqueue_user(ctx);
1209
1210        test_pipe_timeout(ctx);
1211        test_pipe_read(ctx);
1212        test_pipe_write(ctx);
1213        test_pipe_close(ctx);
1214
1215        exit(0);
1216}
1217
1218#include <rtems/bsd/test/default-init.h>
Note: See TracBrowser for help on using the repository browser.