source: rtems-libbsd/testsuite/selectpollkqueue01/test_main.c @ 3df89c0

5-freebsd-12
Last change on this file since 3df89c0 was 3df89c0, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 26, 2018 at 11:52:43 AM

selectpollkqueue01: Invalidate file descriptor

This is not a functional change or a fix.

  • Property mode set to 100755
File size: 22.0 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                ctx->afd = -1;
368
369                rv = close(afd);
370                assert(rv == 0);
371        }
372
373        send_events(ctx, EVENT_CONNECT);
374
375        set_non_blocking(lfd, 1);
376
377        errno = 0;
378        afd = accept(lfd, NULL, NULL);
379        assert(afd == -1);
380        assert(errno == EAGAIN);
381
382        set_non_blocking(lfd, 0);
383
384        FD_ZERO(&set);
385        FD_SET(lfd, &set);
386
387        rv = select(nfds, &set, NULL, NULL, NULL);
388        assert(rv == 1);
389
390        for (i = 0; i < nfds; ++i) {
391                bool is_set_expected = i == lfd;
392                bool is_set = FD_ISSET(i, &set);
393
394                assert(is_set_expected == is_set);
395        }
396
397        afd = accept(lfd, NULL, NULL);
398        assert(afd >= 0);
399
400        ctx->afd = afd;
401}
402
403static void
404test_select_read(test_context *ctx)
405{
406        int afd = ctx->afd;
407        int cfd = ctx->cfd;
408        int nfds = afd + 1;
409        struct fd_set set;
410        int rv;
411        int i;
412        ssize_t n;
413
414        puts("test select read");
415
416        assert(afd >= 0);
417        assert(cfd >= 0);
418
419        ctx->wfd = cfd;
420        ctx->wbuf = &msg[0];
421        ctx->wn = sizeof(msg);
422        send_events(ctx, EVENT_WRITE);
423
424        set_non_blocking(afd, 1);
425
426        errno = 0;
427        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
428        assert(n == -1);
429        assert(errno == EAGAIN);
430
431        FD_ZERO(&set);
432        FD_SET(afd, &set);
433
434        rv = select(nfds, &set, NULL, NULL, NULL);
435        assert(rv == 1);
436
437        for (i = 0; i < nfds; ++i) {
438                bool is_set_expected = i == afd;
439                bool is_set = FD_ISSET(i, &set);
440
441                assert(is_set_expected == is_set);
442        }
443
444        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
445        assert(n == (ssize_t) sizeof(msg));
446        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
447}
448
449static void
450test_select_write(test_context *ctx)
451{
452        int afd = ctx->afd;
453        int cfd = ctx->cfd;
454        int nfds = afd + 1;
455        struct fd_set set;
456        int rv;
457        int i;
458        ssize_t n;
459
460        puts("test select write");
461
462        assert(afd >= 0);
463        assert(cfd >= 0);
464
465        ctx->rfd = cfd;
466        ctx->rbuf = &ctx->buf[0];
467        ctx->rn = sizeof(ctx->buf);
468        send_events(ctx, EVENT_READ);
469
470        set_non_blocking(afd, 1);
471
472        do {
473                errno = 0;
474                n = write(afd, &ctx->buf[0], sizeof(ctx->buf));
475                if (n == -1) {
476                        assert(errno == EAGAIN);
477                }
478        } while (n > 0);
479
480        FD_ZERO(&set);
481        FD_SET(afd, &set);
482
483        rv = select(nfds, NULL, &set, NULL, NULL);
484        assert(rv == 1);
485
486        for (i = 0; i < nfds; ++i) {
487                bool is_set_expected = i == afd;
488                bool is_set = FD_ISSET(i, &set);
489
490                assert(is_set_expected == is_set);
491        }
492
493        n = write(afd, &ctx->buf[0], 1);
494        assert(n == 1);
495}
496
497static void
498test_select_close(test_context *ctx)
499{
500        int cfd = ctx->cfd;
501        int nfds = cfd + 1;
502        struct fd_set set;
503        int rv;
504
505        puts("test select close");
506
507        assert(ctx->cfd >= 0);
508
509        send_events(ctx, EVENT_CLOSE);
510
511        assert(ctx->cfd >= 0);
512
513        FD_ZERO(&set);
514        FD_SET(cfd, &set);
515
516        errno = 0;
517        rv = select(nfds, NULL, NULL, &set, NULL);
518        assert(rv == -1);
519        assert(errno == EBADF);
520
521        assert(ctx->cfd == -1);
522}
523
524static void
525test_poll_timeout(test_context *ctx)
526{
527        static const short events[] = {
528                POLLIN,
529                POLLPRI,
530                POLLOUT,
531                POLLRDNORM,
532                POLLWRNORM,
533                POLLRDBAND,
534                POLLWRBAND
535        };
536
537        int timeout = 100;
538        struct pollfd pfd = {
539                .fd = ctx->lfd
540        };
541        size_t i;
542
543        puts("test poll timeout");
544
545        for (i = 0; i < nitems(events); ++i) {
546                int rv;
547
548                pfd.events = events[i];
549                pfd.revents = 0;
550
551                rv = poll(&pfd, 1, timeout);
552                assert(rv == 0);
553        }
554}
555
556static void
557test_poll_connect(test_context *ctx)
558{
559        int lfd = ctx->lfd;
560        int afd = ctx->afd;
561        struct pollfd pfd = {
562                .fd = lfd,
563                .events = POLLIN
564        };
565        int timeout = -1;
566        int rv;
567
568        puts("test poll connect");
569
570        if (afd >= 0) {
571                ctx->afd = -1;
572
573                rv = close(afd);
574                assert(rv == 0);
575        }
576
577        send_events(ctx, EVENT_CONNECT);
578
579        set_non_blocking(lfd, 1);
580
581        errno = 0;
582        afd = accept(lfd, NULL, NULL);
583        assert(afd == -1);
584        assert(errno == EAGAIN);
585
586        set_non_blocking(lfd, 0);
587
588        rv = poll(&pfd, 1, timeout);
589        assert(rv == 1);
590        assert(pfd.revents == POLLIN);
591
592        afd = accept(lfd, NULL, NULL);
593        assert(afd >= 0);
594
595        ctx->afd = afd;
596}
597
598static void
599test_poll_read(test_context *ctx)
600{
601        int afd = ctx->afd;
602        int cfd = ctx->cfd;
603        struct pollfd pfd = {
604                .fd = afd,
605                .events = POLLIN
606        };
607        int timeout = -1;
608        int rv;
609        ssize_t n;
610
611        puts("test poll read");
612
613        assert(afd >= 0);
614        assert(cfd >= 0);
615
616        ctx->wfd = cfd;
617        ctx->wbuf = &msg[0];
618        ctx->wn = sizeof(msg);
619        send_events(ctx, EVENT_WRITE);
620
621        set_non_blocking(afd, 1);
622
623        errno = 0;
624        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
625        assert(n == -1);
626        assert(errno == EAGAIN);
627
628        rv = poll(&pfd, 1, timeout);
629        assert(rv == 1);
630        assert(pfd.revents == POLLIN);
631
632        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
633        assert(n == (ssize_t) sizeof(msg));
634        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
635}
636
637static void
638test_poll_write(test_context *ctx)
639{
640        int afd = ctx->afd;
641        int cfd = ctx->cfd;
642        struct pollfd pfd = {
643                .fd = afd,
644                .events = POLLOUT
645        };
646        int timeout = -1;
647        int rv;
648        ssize_t n;
649
650        puts("test poll write");
651
652        assert(afd >= 0);
653        assert(cfd >= 0);
654
655        ctx->rfd = cfd;
656        ctx->rbuf = &ctx->buf[0];
657        ctx->rn = sizeof(ctx->buf);
658        send_events(ctx, EVENT_READ);
659
660        set_non_blocking(afd, 1);
661
662        do {
663                errno = 0;
664                n = write(afd, &ctx->buf[0], sizeof(ctx->buf));
665                if (n == -1) {
666                        assert(errno == EAGAIN);
667                }
668        } while (n > 0);
669
670        rv = poll(&pfd, 1, timeout);
671        assert(rv == 1);
672        assert(pfd.revents == POLLOUT);
673
674        n = write(afd, &ctx->buf[0], 1);
675        assert(n == 1);
676}
677
678static void
679test_poll_close(test_context *ctx)
680{
681        int cfd = ctx->cfd;
682        struct pollfd pfd = {
683                .fd = cfd,
684                .events = POLLRDBAND
685        };
686        int timeout = -1;
687        int rv;
688
689        puts("test poll close");
690
691        assert(ctx->cfd >= 0);
692
693        send_events(ctx, EVENT_CLOSE);
694
695        assert(ctx->cfd >= 0);
696
697        rv = poll(&pfd, 1, timeout);
698        assert(rv == 1);
699        assert(pfd.revents == POLLNVAL);
700
701        assert(ctx->cfd == -1);
702}
703
704static void
705test_kqueue_timer(bool do_resource_check)
706{
707        rtems_resource_snapshot snapshot;
708        int kq;
709        int rv;
710        struct kevent change;
711        int i;
712
713        puts("test kqueue timer");
714
715        if (do_resource_check) {
716                rtems_resource_snapshot_take(&snapshot);
717        }
718
719        kq = kqueue();
720        assert(kq >= 0);
721
722        EV_SET(&change, 0xbeef, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, 100,
723            TEST_UDATA);
724
725        rv = kevent(kq, &change, 1, NULL, 0, NULL);
726        assert(rv == 0);
727
728        for (i = 0; i < 5; ++i) {
729                struct kevent event;
730
731                rv = kevent(kq, NULL, 0, &event, 1, NULL);
732                assert(rv == 1);
733                assert(event.ident == 0xbeef);
734                assert(event.filter == EVFILT_TIMER);
735                assert(event.flags == EV_CLEAR);
736                assert(event.fflags == 0);
737                assert(event.data == 1);
738                assert(event.udata == TEST_UDATA);
739        }
740
741        rv = close(kq);
742        assert(rv == 0);
743
744        if (do_resource_check) {
745                assert(rtems_resource_snapshot_check(&snapshot));
746        }
747}
748
749static void
750test_kqueue_connect(test_context *ctx)
751{
752        int lfd = ctx->lfd;
753        int afd = ctx->afd;
754        int kq;
755        struct kevent change;
756        struct kevent event;
757        const struct timespec *timeout = NULL;
758        int rv;
759
760        puts("test kqueue connect");
761
762        if (afd >= 0) {
763                ctx->afd = -1;
764
765                rv = close(afd);
766                assert(rv == 0);
767        }
768
769        kq = kqueue();
770        assert(kq >= 0);
771
772        EV_SET(&change, lfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
773            TEST_UDATA);
774
775        rv = kevent(kq, &change, 1, NULL, 0, timeout);
776        assert(rv == 0);
777
778        send_events(ctx, EVENT_CONNECT);
779
780        set_non_blocking(lfd, 1);
781
782        errno = 0;
783        afd = accept(lfd, NULL, NULL);
784        assert(afd == -1);
785        assert(errno == EAGAIN);
786
787        set_non_blocking(lfd, 0);
788
789        rv = kevent(kq, NULL, 0, &event, 1, timeout);
790        assert(rv == 1);
791        assert(event.ident == lfd);
792        assert(event.filter == EVFILT_READ);
793        assert(event.flags == 0);
794        assert(event.fflags == 0);
795        assert(event.data == 1);
796        assert(event.udata == TEST_UDATA);
797
798        afd = accept(lfd, NULL, NULL);
799        assert(afd >= 0);
800
801        ctx->afd = afd;
802
803        rv = close(kq);
804        assert(rv == 0);
805}
806
807static void
808test_kqueue_read(test_context *ctx)
809{
810        int afd = ctx->afd;
811        int cfd = ctx->cfd;
812        int kq;
813        struct kevent change;
814        struct kevent event;
815        const struct timespec *timeout = NULL;
816        int rv;
817        ssize_t n;
818
819        puts("test kqueue read");
820
821        assert(afd >= 0);
822        assert(cfd >= 0);
823
824        kq = kqueue();
825        assert(kq >= 0);
826
827        EV_SET(&change, afd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
828            TEST_UDATA);
829
830        rv = kevent(kq, &change, 1, NULL, 0, timeout);
831        assert(rv == 0);
832
833        ctx->wfd = cfd;
834        ctx->wbuf = &msg[0];
835        ctx->wn = sizeof(msg);
836        send_events(ctx, EVENT_WRITE);
837
838        set_non_blocking(afd, 1);
839
840        errno = 0;
841        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
842        assert(n == -1);
843        assert(errno == EAGAIN);
844
845        rv = kevent(kq, NULL, 0, &event, 1, timeout);
846        assert(rv == 1);
847        assert(event.ident == afd);
848        assert(event.filter == EVFILT_READ);
849        assert(event.flags == 0);
850        assert(event.fflags == 0);
851        assert(event.data == sizeof(msg));
852        assert(event.udata == TEST_UDATA);
853
854        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
855        assert(n == (ssize_t) sizeof(msg));
856        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
857
858        rv = close(kq);
859        assert(rv == 0);
860}
861
862static void
863test_kqueue_write(test_context *ctx)
864{
865        int afd = ctx->afd;
866        int cfd = ctx->cfd;
867        int kq;
868        struct kevent change;
869        struct kevent event;
870        const struct timespec *timeout = NULL;
871        int rv;
872        ssize_t n;
873
874        puts("test kqueue write");
875
876        assert(afd >= 0);
877        assert(cfd >= 0);
878
879        kq = kqueue();
880        assert(kq >= 0);
881
882        EV_SET(&change, afd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0,
883            TEST_UDATA);
884
885        rv = kevent(kq, &change, 1, NULL, 0, timeout);
886        assert(rv == 0);
887
888        ctx->rfd = cfd;
889        ctx->rbuf = &ctx->buf[0];
890        ctx->rn = sizeof(ctx->buf);
891        send_events(ctx, EVENT_READ);
892
893        set_non_blocking(afd, 1);
894
895        do {
896                errno = 0;
897                n = write(afd, &ctx->buf[0], sizeof(ctx->buf));
898                if (n == -1) {
899                        assert(errno == EAGAIN);
900                }
901        } while (n > 0);
902
903        rv = kevent(kq, NULL, 0, &event, 1, timeout);
904        assert(rv == 1);
905        assert(event.ident == afd);
906        assert(event.filter == EVFILT_WRITE);
907        assert(event.flags == 0);
908        assert(event.fflags == 0);
909        assert(event.data == 20428);
910        assert(event.udata == TEST_UDATA);
911
912        n = write(afd, &ctx->buf[0], 1);
913        assert(n == 1);
914
915        rv = close(kq);
916        assert(rv == 0);
917}
918
919static void
920test_kqueue_close(test_context *ctx)
921{
922        int cfd = ctx->cfd;
923        int kq;
924        struct kevent change;
925        struct kevent event;
926        const struct timespec *timeout = NULL;
927        int rv;
928        ssize_t n;
929        mode_t canrecv = S_IRUSR | S_IRGRP | S_IROTH;
930        mode_t cansend = S_IWUSR | S_IWGRP | S_IWOTH;
931        struct stat st;
932
933        puts("test kqueue close");
934
935        assert(ctx->cfd >= 0);
936
937        kq = kqueue();
938        assert(kq >= 0);
939
940        EV_SET(&change, cfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
941            TEST_UDATA);
942
943        rv = kevent(kq, &change, 1, NULL, 0, timeout);
944        assert(rv == 0);
945
946        set_non_blocking(cfd, 1);
947
948        do {
949                errno = 0;
950                n = read(cfd, &ctx->buf[0], sizeof(ctx->buf));
951                if (n == -1) {
952                        assert(errno == EAGAIN);
953                }
954        } while (n > 0);
955
956        /*
957         * It is not allowed to close file descriptors still in use by
958         * kevent().  On FreeBSD the file descriptor reference counting would
959         * prevent this also.
960         */
961        send_events(ctx, EVENT_SHUTDOWN);
962
963        rv = fstat(cfd, &st);
964        assert(rv == 0);
965        assert(st.st_mode == (S_IFSOCK | canrecv | cansend));
966
967        rv = kevent(kq, NULL, 0, &event, 1, timeout);
968        assert(rv == 1);
969        assert(event.ident == cfd);
970        assert(event.filter == EVFILT_READ);
971        assert(event.flags == EV_EOF);
972        assert(event.fflags == 0);
973        assert(event.data == 0);
974        assert(event.udata == TEST_UDATA);
975
976        /*
977         * The master task wakes up during the shutdown() operation.  So we do
978         * not see the full shutdown.
979         */
980        rv = fstat(cfd, &st);
981        assert(rv == 0);
982        assert(st.st_mode == (S_IFSOCK | cansend));
983
984        rv = close(kq);
985        assert(rv == 0);
986}
987
988static void
989test_kqueue_user(test_context *ctx)
990{
991        int kq;
992        uintptr_t ident;
993        u_int flag;
994        struct kevent change;
995        struct kevent trigger;
996        struct kevent event;
997        const struct timespec *timeout = NULL;
998        int rv;
999
1000        puts("test kqueue user");
1001
1002        ident = 0xabc;
1003        flag = 0x1;
1004
1005        kq = kqueue();
1006        assert(kq >= 0);
1007
1008        EV_SET(&change, ident, EVFILT_USER, EV_ADD | EV_ENABLE, NOTE_FFNOP, 0,
1009            TEST_UDATA);
1010
1011        rv = kevent(kq, &change, 1, NULL, 0, timeout);
1012        assert(rv == 0);
1013
1014        ident = 0xabc;
1015        EV_SET(&trigger, ident, EVFILT_USER, 0, NOTE_TRIGGER | NOTE_FFCOPY |
1016            flag, 0, TEST_UDATA);
1017
1018        rv = kevent(kq, &trigger, 1, NULL, 0, timeout);
1019        assert(rv == 0);
1020
1021        memset(&event, 0, sizeof(event));
1022        rv = kevent(kq, NULL, 0, &event, 1, timeout);
1023        assert(rv == 1);
1024        assert(event.ident == ident);
1025        assert(event.filter == EVFILT_USER);
1026        assert(event.flags == 0);
1027        assert(event.fflags == flag);
1028        assert(event.data == 0);
1029        assert(event.udata == TEST_UDATA);
1030
1031        rv = close(kq);
1032        assert(rv == 0);
1033}
1034
1035static void
1036test_pipe_timeout(test_context *ctx)
1037{
1038        struct pipe_poll_events
1039        {
1040                short event;
1041                int rv;
1042        };
1043        const struct pipe_poll_events events[] = {
1044                { POLLIN, 0 },
1045                { POLLPRI, 0 },
1046                { POLLOUT, 1 },
1047                { POLLRDNORM, 0 },
1048                { POLLWRNORM, 1 },
1049                { POLLRDBAND, 0 },
1050                { POLLWRBAND, 0 },
1051                { POLLINIGNEOF, 0 }
1052        };
1053
1054        int timeout = 100;
1055        struct pollfd pfd;
1056        size_t i;
1057        int rv;
1058
1059        puts("test pipe timeout");
1060
1061        rv = pipe(ctx->pfd);
1062        assert(rv == 0);
1063
1064        pfd.fd = ctx->pfd[1];
1065
1066        for (i = 0; i < nitems(events); ++i) {
1067                int rv;
1068
1069                pfd.events = events[i].event;
1070                pfd.revents = 0;
1071
1072                rv = poll(&pfd, 1, timeout);
1073                assert(rv == events[i].rv);
1074        }
1075}
1076
1077static void
1078test_pipe_read(test_context *ctx)
1079{
1080        int rfd = ctx->pfd[0];
1081        int wfd = ctx->pfd[1];
1082        struct pollfd pfd = {
1083                .fd = rfd,
1084                .events = POLLIN
1085        };
1086        int timeout = -1;
1087        int rv;
1088        ssize_t n;
1089
1090        puts("test pipe read");
1091
1092        assert(rfd >= 0);
1093        assert(wfd >= 0);
1094
1095        ctx->wfd = wfd;
1096        ctx->wbuf = &msg[0];
1097        ctx->wn = sizeof(msg);
1098        send_events(ctx, EVENT_WRITE);
1099
1100        set_non_blocking(rfd, 1);
1101
1102        errno = 0;
1103        n = read(rfd, &ctx->buf[0], sizeof(ctx->buf));
1104        assert(n == -1);
1105        assert(errno == EAGAIN);
1106
1107        rv = poll(&pfd, 1, timeout);
1108        assert(rv == 1);
1109        assert(pfd.revents == POLLIN);
1110
1111        n = read(rfd, &ctx->buf[0], sizeof(ctx->buf));
1112        assert(n == (ssize_t) sizeof(msg));
1113        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
1114}
1115
1116static void
1117test_pipe_write(test_context *ctx)
1118{
1119        int rfd = ctx->pfd[0];
1120        int wfd = ctx->pfd[1];
1121        struct pollfd pfd = {
1122                .fd = wfd,
1123                .events = POLLOUT
1124        };
1125        int timeout = -1;
1126        int rv;
1127        ssize_t n;
1128
1129        puts("test pipe write");
1130
1131        assert(rfd >= 0);
1132        assert(wfd >= 0);
1133
1134        ctx->rfd = rfd;
1135        ctx->rbuf = &ctx->buf[0];
1136        ctx->rn = sizeof(ctx->buf);
1137        send_events(ctx, EVENT_READ);
1138
1139        set_non_blocking(wfd, 1);
1140
1141        do {
1142                errno = 0;
1143                n = write(wfd, &ctx->buf[0], sizeof(ctx->buf));
1144                if (n == -1) {
1145                        assert(errno == EAGAIN);
1146                }
1147        } while (n > 0);
1148
1149        rv = poll(&pfd, 1, timeout);
1150        assert(rv == 1);
1151        assert(pfd.revents == POLLOUT);
1152}
1153
1154static void
1155test_pipe_close(test_context *ctx)
1156{
1157        int rfd = ctx->pfd[0];
1158        struct pollfd pfd = {
1159                .fd = rfd,
1160                .events = POLLIN
1161        };
1162        int timeout = -1;
1163        int rv;
1164
1165        puts("test pipe close");
1166
1167        assert(ctx->pfd[0] >= 0);
1168        assert(ctx->pfd[1] >= 0);
1169
1170        send_events(ctx, EVENT_CLOSE_PIPE);
1171
1172        set_non_blocking(rfd, 0);
1173
1174        assert(ctx->pfd[0] >= 0);
1175        assert(ctx->pfd[1] >= 0);
1176
1177        rv = poll(&pfd, 1, timeout);
1178        assert(rv == 1);
1179        assert(pfd.revents == (POLLIN | POLLHUP));
1180
1181        assert(ctx->pfd[0] == -1);
1182        assert(ctx->pfd[1] == -1);
1183}
1184
1185static void
1186test_main(void)
1187{
1188        test_context *ctx = &test_instance;
1189
1190        setup_lo0();
1191        set_self_prio(PRIO_MASTER);
1192        start_worker(ctx);
1193        create_server_socket(ctx);
1194        create_client_addr(ctx);
1195
1196        test_select_timeout(ctx);
1197        test_select_connect(ctx);
1198        test_select_read(ctx);
1199        test_select_write(ctx);
1200        test_select_close(ctx);
1201
1202        test_poll_timeout(ctx);
1203        test_poll_connect(ctx);
1204        test_poll_read(ctx);
1205        test_poll_write(ctx);
1206        test_poll_close(ctx);
1207
1208        test_kqueue_timer(false);
1209        test_kqueue_timer(true);
1210        test_kqueue_connect(ctx);
1211        test_kqueue_read(ctx);
1212        test_kqueue_write(ctx);
1213        test_kqueue_close(ctx);
1214        test_kqueue_user(ctx);
1215
1216        test_pipe_timeout(ctx);
1217        test_pipe_read(ctx);
1218        test_pipe_write(ctx);
1219        test_pipe_close(ctx);
1220
1221        exit(0);
1222}
1223
1224#include <rtems/bsd/test/default-init.h>
Note: See TracBrowser for help on using the repository browser.