source: rtems-libbsd/testsuite/selectpollkqueue01/test_main.c @ 2e5f808

6-freebsd-12
Last change on this file since 2e5f808 was 2e5f808, checked in by Chris Johns <chrisj@…>, on 09/23/21 at 05:42:12

rtemsbsd/syscalls: Remove pipe()

  • This call is provided by RTEMS and that is preferred

Closes #4518

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