source: rtems-libbsd/testsuite/selectpollkqueue01/test_main.c @ 510946e

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 510946e was 510946e, checked in by Sebastian Huber <sebastian.huber@…>, on 10/23/13 at 14:07:49

selectpollkqueue01: New test

  • Property mode set to 100644
File size: 18.2 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 <rtems/bsd/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/stackchk.h>
57#include <rtems.h>
58
59#define TEST_NAME "LIBBSD SELECT AND POLL AND KQUEUE 1"
60
61#define PRIO_MASTER 1
62
63#define PRIO_WORKER 2
64
65#define EVENT_READ RTEMS_EVENT_0
66
67#define EVENT_WRITE RTEMS_EVENT_1
68
69#define EVENT_CONNECT RTEMS_EVENT_2
70
71#define EVENT_CLOSE RTEMS_EVENT_3
72
73#define EVENT_SHUTDOWN RTEMS_EVENT_4
74
75#define BUF_SIZE 4096
76
77#define PORT 1234
78
79#define TEST_UDATA ((void *) 0xcafe)
80
81typedef struct {
82        char buf[BUF_SIZE];
83        const char *wbuf;
84        char *rbuf;
85        size_t rn;
86        size_t wn;
87        int lfd;
88        int cfd;
89        int afd;
90        int rfd;
91        int wfd;
92        struct sockaddr_in caddr;
93        rtems_id worker_task;
94} test_context;
95
96static test_context test_instance = {
97        .cfd = -1
98};
99
100static const char msg[] = "This is a message.  One two three.";
101
102static void
103setup_lo0(void)
104{
105        int exit_code;
106        char *lo0[] = {
107                "ifconfig",
108                "lo0",
109                "inet",
110                "127.0.0.1",
111                "netmask",
112                "255.255.255.0",
113                NULL
114        };
115
116        exit_code = rtems_bsd_command_ifconfig(RTEMS_ARRAY_SIZE(lo0) - 1, lo0);
117        assert(exit_code == EX_OK);
118}
119
120static void
121set_self_prio(rtems_task_priority prio)
122{
123        rtems_status_code sc;
124
125        sc = rtems_task_set_priority(RTEMS_SELF, prio, &prio);
126        assert(sc == RTEMS_SUCCESSFUL);
127}
128
129static void
130create_server_socket(test_context *ctx)
131{
132        struct sockaddr_in saddr;
133        int rv;
134        int lfd;
135
136        lfd = socket(PF_INET, SOCK_STREAM, 0);
137        assert(lfd >= 0);
138
139        memset(&saddr, 0, sizeof(saddr));
140        saddr.sin_family = AF_INET;
141        saddr.sin_port = htons(PORT);
142        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
143
144        rv = bind(lfd, (const struct sockaddr *) &saddr, sizeof(saddr));
145        assert(rv == 0);
146
147        rv = listen(lfd, 1);
148        assert(rv == 0);
149
150        ctx->lfd = lfd;
151}
152
153static void
154create_client_addr(test_context *ctx)
155{
156        struct sockaddr_in *caddr = &ctx->caddr;;
157        int ok;
158
159        memset(caddr, 0, sizeof(*caddr));
160        caddr->sin_family = AF_INET;
161        caddr->sin_port = htons(PORT);
162        ok = inet_aton("127.0.0.1", &caddr->sin_addr);
163        assert(ok != 0);
164}
165
166static void
167worker_task(rtems_task_argument arg)
168{
169        test_context *ctx = (test_context *) arg;
170
171        while (true) {
172                rtems_status_code sc;
173                rtems_event_set events;
174                ssize_t n;
175                int rv;
176                int cfd = ctx->cfd;
177
178                sc = rtems_event_receive(
179                        RTEMS_ALL_EVENTS,
180                        RTEMS_EVENT_ANY | RTEMS_WAIT,
181                        RTEMS_NO_TIMEOUT,
182                        &events
183                );
184                assert(sc == RTEMS_SUCCESSFUL);
185
186                if ((events & EVENT_READ) != 0) {
187                        puts("worker: read");
188
189                        n = read(ctx->rfd, &ctx->rbuf[0], ctx->rn);
190                        assert(n == (ssize_t) ctx->rn);
191                }
192
193                if ((events & EVENT_WRITE) != 0) {
194                        puts("worker: write");
195
196                        n = write(ctx->wfd, &ctx->wbuf[0], ctx->wn);
197                        assert(n == (ssize_t) ctx->wn);
198                }
199
200                if ((events & EVENT_CONNECT) != 0) {
201                        if (cfd >= 0) {
202                                puts("worker: close connect socket");
203
204                                ctx->cfd = -1;
205
206                                rv = close(cfd);
207                                assert(rv == 0);
208
209                                cfd = -1;
210                        }
211
212                        if (cfd < 0) {
213                                puts("worker: create new connect socket");
214
215                                cfd = socket(PF_INET, SOCK_STREAM, 0);
216                                assert(cfd >= 0);
217
218                                ctx->cfd = cfd;
219                        }
220
221                        puts("worker: connect");
222
223                        rv = connect(
224                                cfd,
225                                (const struct sockaddr *) &ctx->caddr,
226                                sizeof(ctx->caddr)
227                        );
228                        assert(rv == 0);
229                }
230
231                if ((events & EVENT_CLOSE) != 0) {
232                        puts("worker: close");
233
234                        ctx->cfd = -1;
235
236                        rv = close(cfd);
237                        assert(rv == 0);
238                }
239
240                if ((events & EVENT_SHUTDOWN) != 0) {
241                        puts("worker: shutdown");
242
243                        rv = shutdown(cfd, SHUT_RDWR);
244                        assert(rv == 0);
245                }
246        }
247}
248
249static void
250send_events(test_context *ctx, rtems_event_set events)
251{
252        rtems_status_code sc;
253
254        sc = rtems_event_send(ctx->worker_task, events);
255        assert(sc == RTEMS_SUCCESSFUL);
256}
257
258static void
259start_worker(test_context *ctx)
260{
261        rtems_status_code sc;
262
263        sc = rtems_task_create(
264                rtems_build_name('W', 'O', 'R', 'K'),
265                PRIO_WORKER,
266                RTEMS_MINIMUM_STACK_SIZE,
267                RTEMS_DEFAULT_MODES,
268                RTEMS_DEFAULT_ATTRIBUTES,
269                &ctx->worker_task
270        );
271        assert(sc == RTEMS_SUCCESSFUL);
272
273        sc = rtems_task_start(
274                ctx->worker_task,
275                worker_task,
276                (rtems_task_argument) ctx
277        );
278        assert(sc == RTEMS_SUCCESSFUL);
279}
280
281static void
282set_non_blocking(int fd, int enable)
283{
284        int rv;
285
286        rv = ioctl(fd, FIONBIO, &enable);
287        assert(rv == 0);
288}
289
290static void
291test_select_timeout(test_context *ctx)
292{
293        struct timeval timeout = {
294                .tv_sec = 0,
295                .tv_usec = 100000
296        };
297        int fd = ctx->lfd;
298        int nfds = fd + 1;
299        struct fd_set set;
300        int rv;
301        int i;
302
303        puts("test select timeout");
304
305        set_non_blocking(ctx->lfd, 0);
306
307        FD_ZERO(&set);
308        FD_SET(fd, &set);
309
310        rv = select(nfds, &set, NULL, NULL, &timeout);
311        assert(rv == 0);
312
313        for (i = 0; i < nfds; ++i) {
314                assert(!FD_ISSET(i, &set));
315        }
316
317        rv = select(nfds, NULL, &set, NULL, &timeout);
318        assert(rv == 0);
319
320        for (i = 0; i < nfds; ++i) {
321                assert(!FD_ISSET(i, &set));
322        }
323
324        rv = select(nfds, NULL, NULL, &set, &timeout);
325        assert(rv == 0);
326
327        for (i = 0; i < nfds; ++i) {
328                assert(!FD_ISSET(i, &set));
329        }
330}
331
332static void
333test_select_connect(test_context *ctx)
334{
335        int lfd = ctx->lfd;
336        int afd = ctx->afd;
337        int nfds = lfd + 1;
338        struct fd_set set;
339        int rv;
340        int i;
341
342        puts("test select connect");
343
344        if (afd >= 0) {
345                rv = close(afd);
346                assert(rv == 0);
347        }
348
349        send_events(ctx, EVENT_CONNECT);
350
351        set_non_blocking(lfd, 1);
352
353        errno = 0;
354        afd = accept(lfd, NULL, NULL);
355        assert(afd == -1);
356        assert(errno == EAGAIN);
357
358        set_non_blocking(lfd, 0);
359
360        FD_ZERO(&set);
361        FD_SET(lfd, &set);
362
363        rv = select(nfds, &set, NULL, NULL, NULL);
364        assert(rv == 1);
365
366        for (i = 0; i < nfds; ++i) {
367                bool is_set_expected = i == lfd;
368                bool is_set = FD_ISSET(i, &set);
369
370                assert(is_set_expected == is_set);
371        }
372
373        afd = accept(lfd, NULL, NULL);
374        assert(afd >= 0);
375
376        ctx->afd = afd;
377}
378
379static void
380test_select_read(test_context *ctx)
381{
382        int afd = ctx->afd;
383        int cfd = ctx->cfd;
384        int nfds = afd + 1;
385        struct fd_set set;
386        int rv;
387        int i;
388        ssize_t n;
389
390        puts("test select read");
391
392        assert(afd >= 0);
393        assert(cfd >= 0);
394
395        ctx->wfd = cfd;
396        ctx->wbuf = &msg[0];
397        ctx->wn = sizeof(msg);
398        send_events(ctx, EVENT_WRITE);
399
400        set_non_blocking(afd, 1);
401
402        errno = 0;
403        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
404        assert(n == -1);
405        assert(errno == EAGAIN);
406
407        FD_ZERO(&set);
408        FD_SET(afd, &set);
409
410        rv = select(nfds, &set, NULL, NULL, NULL);
411        assert(rv == 1);
412
413        for (i = 0; i < nfds; ++i) {
414                bool is_set_expected = i == afd;
415                bool is_set = FD_ISSET(i, &set);
416
417                assert(is_set_expected == is_set);
418        }
419
420        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
421        assert(n == (ssize_t) sizeof(msg));
422        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
423}
424
425static void
426test_select_write(test_context *ctx)
427{
428        int afd = ctx->afd;
429        int cfd = ctx->cfd;
430        int nfds = afd + 1;
431        struct fd_set set;
432        int rv;
433        int i;
434        ssize_t n;
435
436        puts("test select write");
437
438        assert(afd >= 0);
439        assert(cfd >= 0);
440
441        ctx->rfd = cfd;
442        ctx->rbuf = &ctx->buf[0];
443        ctx->rn = sizeof(ctx->buf);
444        send_events(ctx, EVENT_READ);
445
446        set_non_blocking(afd, 1);
447
448        do {
449                errno = 0;
450                n = write(afd, &ctx->buf[0], sizeof(ctx->buf));
451                if (n == -1) {
452                        assert(errno == EAGAIN);
453                }
454        } while (n > 0);
455
456        FD_ZERO(&set);
457        FD_SET(afd, &set);
458
459        rv = select(nfds, NULL, &set, NULL, NULL);
460        assert(rv == 1);
461
462        for (i = 0; i < nfds; ++i) {
463                bool is_set_expected = i == afd;
464                bool is_set = FD_ISSET(i, &set);
465
466                assert(is_set_expected == is_set);
467        }
468
469        n = write(afd, &ctx->buf[0], 1);
470        assert(n == 1);
471}
472
473static void
474test_select_close(test_context *ctx)
475{
476        int cfd = ctx->cfd;
477        int nfds = cfd + 1;
478        struct fd_set set;
479        int rv;
480
481        puts("test select close");
482
483        assert(ctx->cfd >= 0);
484
485        send_events(ctx, EVENT_CLOSE);
486
487        assert(ctx->cfd >= 0);
488
489        FD_ZERO(&set);
490        FD_SET(cfd, &set);
491
492        errno = 0;
493        rv = select(nfds, NULL, NULL, &set, NULL);
494        assert(rv == -1);
495        assert(errno == EBADF);
496
497        assert(ctx->cfd == -1);
498}
499
500static void
501test_poll_timeout(test_context *ctx)
502{
503        static const short events[] = {
504                POLLIN,
505                POLLPRI,
506                POLLOUT,
507                POLLRDNORM,
508                POLLWRNORM,
509                POLLRDBAND,
510                POLLWRBAND
511        };
512
513        int timeout = 100;
514        struct pollfd pfd = {
515                .fd = ctx->lfd
516        };
517        size_t i;
518
519        puts("test poll timeout");
520
521        for (i = 0; i < nitems(events); ++i) {
522                int rv;
523
524                pfd.events = events[i];
525                pfd.revents = 0;
526
527                rv = poll(&pfd, 1, timeout);
528                assert(rv == 0);
529        }
530}
531
532static void
533test_poll_connect(test_context *ctx)
534{
535        int lfd = ctx->lfd;
536        int afd = ctx->afd;
537        struct pollfd pfd = {
538                .fd = lfd,
539                .events = POLLIN
540        };
541        int timeout = -1;
542        int rv;
543
544        puts("test poll connect");
545
546        if (afd >= 0) {
547                rv = close(afd);
548                assert(rv == 0);
549        }
550
551        send_events(ctx, EVENT_CONNECT);
552
553        set_non_blocking(lfd, 1);
554
555        errno = 0;
556        afd = accept(lfd, NULL, NULL);
557        assert(afd == -1);
558        assert(errno == EAGAIN);
559
560        set_non_blocking(lfd, 0);
561
562        rv = poll(&pfd, 1, timeout);
563        assert(rv == 1);
564        assert(pfd.revents == POLLIN);
565
566        afd = accept(lfd, NULL, NULL);
567        assert(afd >= 0);
568
569        ctx->afd = afd;
570}
571
572static void
573test_poll_read(test_context *ctx)
574{
575        int afd = ctx->afd;
576        int cfd = ctx->cfd;
577        struct pollfd pfd = {
578                .fd = afd,
579                .events = POLLIN
580        };
581        int timeout = -1;
582        int rv;
583        ssize_t n;
584
585        puts("test poll read");
586
587        assert(afd >= 0);
588        assert(cfd >= 0);
589
590        ctx->wfd = cfd;
591        ctx->wbuf = &msg[0];
592        ctx->wn = sizeof(msg);
593        send_events(ctx, EVENT_WRITE);
594
595        set_non_blocking(afd, 1);
596
597        errno = 0;
598        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
599        assert(n == -1);
600        assert(errno == EAGAIN);
601
602        rv = poll(&pfd, 1, timeout);
603        assert(rv == 1);
604        assert(pfd.revents == POLLIN);
605
606        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
607        assert(n == (ssize_t) sizeof(msg));
608        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
609}
610
611static void
612test_poll_write(test_context *ctx)
613{
614        int afd = ctx->afd;
615        int cfd = ctx->cfd;
616        struct pollfd pfd = {
617                .fd = afd,
618                .events = POLLOUT
619        };
620        int timeout = -1;
621        int rv;
622        ssize_t n;
623
624        puts("test poll write");
625
626        assert(afd >= 0);
627        assert(cfd >= 0);
628
629        ctx->rfd = cfd;
630        ctx->rbuf = &ctx->buf[0];
631        ctx->rn = sizeof(ctx->buf);
632        send_events(ctx, EVENT_READ);
633
634        set_non_blocking(afd, 1);
635
636        do {
637                errno = 0;
638                n = write(afd, &ctx->buf[0], sizeof(ctx->buf));
639                if (n == -1) {
640                        assert(errno == EAGAIN);
641                }
642        } while (n > 0);
643
644        rv = poll(&pfd, 1, timeout);
645        assert(rv == 1);
646        assert(pfd.revents == POLLOUT);
647
648        n = write(afd, &ctx->buf[0], 1);
649        assert(n == 1);
650}
651
652static void
653test_poll_close(test_context *ctx)
654{
655        int cfd = ctx->cfd;
656        struct pollfd pfd = {
657                .fd = cfd,
658                .events = POLLRDBAND
659        };
660        int timeout = -1;
661        int rv;
662
663        puts("test poll close");
664
665        assert(ctx->cfd >= 0);
666
667        send_events(ctx, EVENT_CLOSE);
668
669        assert(ctx->cfd >= 0);
670
671        rv = poll(&pfd, 1, timeout);
672        assert(rv == 1);
673        assert(pfd.revents == POLLNVAL);
674
675        assert(ctx->cfd == -1);
676}
677
678static void
679test_kqueue_timer(bool do_resource_check)
680{
681        rtems_resource_snapshot snapshot;
682        int kq;
683        int rv;
684        struct kevent change;
685        int i;
686
687        puts("test kqueue timer");
688
689        if (do_resource_check) {
690                rtems_resource_snapshot_take(&snapshot);
691        }
692
693        kq = kqueue();
694        assert(kq >= 0);
695
696        EV_SET(&change, 0xbeef, EVFILT_TIMER, EV_ADD | EV_ENABLE, 0, 100,
697            TEST_UDATA);
698
699        rv = kevent(kq, &change, 1, NULL, 0, NULL);
700        assert(rv == 0);
701
702        for (i = 0; i < 5; ++i) {
703                struct kevent event;
704
705                rv = kevent(kq, NULL, 0, &event, 1, NULL);
706                assert(rv == 1);
707                assert(event.ident == 0xbeef);
708                assert(event.filter == EVFILT_TIMER);
709                assert(event.flags == EV_CLEAR);
710                assert(event.fflags == 0);
711                assert(event.data == 1);
712                assert(event.udata == TEST_UDATA);
713        }
714
715        rv = close(kq);
716        assert(rv == 0);
717
718        if (do_resource_check) {
719                assert(rtems_resource_snapshot_check(&snapshot));
720        }
721}
722
723static void
724test_kqueue_connect(test_context *ctx)
725{
726        int lfd = ctx->lfd;
727        int afd = ctx->afd;
728        int kq;
729        struct kevent change;
730        struct kevent event;
731        const struct timespec *timeout = NULL;
732        int rv;
733
734        puts("test kqueue connect");
735
736        if (afd >= 0) {
737                rv = close(afd);
738                assert(rv == 0);
739        }
740
741        kq = kqueue();
742        assert(kq >= 0);
743
744        EV_SET(&change, lfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
745            TEST_UDATA);
746
747        rv = kevent(kq, &change, 1, NULL, 0, timeout);
748        assert(rv == 0);
749
750        send_events(ctx, EVENT_CONNECT);
751
752        set_non_blocking(lfd, 1);
753
754        errno = 0;
755        afd = accept(lfd, NULL, NULL);
756        assert(afd == -1);
757        assert(errno == EAGAIN);
758
759        set_non_blocking(lfd, 0);
760
761        rv = kevent(kq, NULL, 0, &event, 1, timeout);
762        assert(rv == 1);
763        assert(event.ident == lfd);
764        assert(event.filter == EVFILT_READ);
765        assert(event.flags == 0);
766        assert(event.fflags == 0);
767        assert(event.data == 1);
768        assert(event.udata == TEST_UDATA);
769
770        afd = accept(lfd, NULL, NULL);
771        assert(afd >= 0);
772
773        ctx->afd = afd;
774
775        rv = close(kq);
776        assert(rv == 0);
777}
778
779static void
780test_kqueue_read(test_context *ctx)
781{
782        int afd = ctx->afd;
783        int cfd = ctx->cfd;
784        int kq;
785        struct kevent change;
786        struct kevent event;
787        const struct timespec *timeout = NULL;
788        int rv;
789        ssize_t n;
790
791        puts("test kqueue read");
792
793        assert(afd >= 0);
794        assert(cfd >= 0);
795
796        kq = kqueue();
797        assert(kq >= 0);
798
799        EV_SET(&change, afd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
800            TEST_UDATA);
801
802        rv = kevent(kq, &change, 1, NULL, 0, timeout);
803        assert(rv == 0);
804
805        ctx->wfd = cfd;
806        ctx->wbuf = &msg[0];
807        ctx->wn = sizeof(msg);
808        send_events(ctx, EVENT_WRITE);
809
810        set_non_blocking(afd, 1);
811
812        errno = 0;
813        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
814        assert(n == -1);
815        assert(errno == EAGAIN);
816
817        rv = kevent(kq, NULL, 0, &event, 1, timeout);
818        assert(rv == 1);
819        assert(event.ident == afd);
820        assert(event.filter == EVFILT_READ);
821        assert(event.flags == 0);
822        assert(event.fflags == 0);
823        assert(event.data == sizeof(msg));
824        assert(event.udata == TEST_UDATA);
825
826        n = read(afd, &ctx->buf[0], sizeof(ctx->buf));
827        assert(n == (ssize_t) sizeof(msg));
828        assert(memcmp(&msg[0], &ctx->buf[0], sizeof(msg)) == 0);
829
830        rv = close(kq);
831        assert(rv == 0);
832}
833
834static void
835test_kqueue_write(test_context *ctx)
836{
837        int afd = ctx->afd;
838        int cfd = ctx->cfd;
839        int kq;
840        struct kevent change;
841        struct kevent event;
842        const struct timespec *timeout = NULL;
843        int rv;
844        ssize_t n;
845
846        puts("test kqueue write");
847
848        assert(afd >= 0);
849        assert(cfd >= 0);
850
851        kq = kqueue();
852        assert(kq >= 0);
853
854        EV_SET(&change, afd, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0,
855            TEST_UDATA);
856
857        rv = kevent(kq, &change, 1, NULL, 0, timeout);
858        assert(rv == 0);
859
860        ctx->rfd = cfd;
861        ctx->rbuf = &ctx->buf[0];
862        ctx->rn = sizeof(ctx->buf);
863        send_events(ctx, EVENT_READ);
864
865        set_non_blocking(afd, 1);
866
867        do {
868                errno = 0;
869                n = write(afd, &ctx->buf[0], sizeof(ctx->buf));
870                if (n == -1) {
871                        assert(errno == EAGAIN);
872                }
873        } while (n > 0);
874
875        rv = kevent(kq, NULL, 0, &event, 1, timeout);
876        assert(rv == 1);
877        assert(event.ident == afd);
878        assert(event.filter == EVFILT_WRITE);
879        assert(event.flags == 0);
880        assert(event.fflags == 0);
881        assert(event.data == 18432);
882        assert(event.udata == TEST_UDATA);
883
884        n = write(afd, &ctx->buf[0], 1);
885        assert(n == 1);
886
887        rv = close(kq);
888        assert(rv == 0);
889}
890
891static void
892test_kqueue_close(test_context *ctx)
893{
894        int cfd = ctx->cfd;
895        int kq;
896        struct kevent change;
897        struct kevent event;
898        const struct timespec *timeout = NULL;
899        int rv;
900        ssize_t n;
901        mode_t canrecv = S_IRUSR | S_IRGRP | S_IROTH;
902        mode_t cansend = S_IWUSR | S_IWGRP | S_IWOTH;
903        struct stat st;
904
905        puts("test kqueue close");
906
907        assert(ctx->cfd >= 0);
908
909        kq = kqueue();
910        assert(kq >= 0);
911
912        EV_SET(&change, cfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
913            TEST_UDATA);
914
915        rv = kevent(kq, &change, 1, NULL, 0, timeout);
916        assert(rv == 0);
917
918        set_non_blocking(cfd, 1);
919
920        do {
921                errno = 0;
922                n = read(cfd, &ctx->buf[0], sizeof(ctx->buf));
923                if (n == -1) {
924                        assert(errno == EAGAIN);
925                }
926        } while (n > 0);
927
928        /*
929         * It is not allowed to close file descriptors still in use by
930         * kevent().  On FreeBSD the file descriptor reference counting would
931         * prevent this also.
932         */
933        send_events(ctx, EVENT_SHUTDOWN);
934
935        rv = fstat(cfd, &st);
936        assert(rv == 0);
937        assert(st.st_mode == (S_IFSOCK | canrecv | cansend));
938
939        rv = kevent(kq, NULL, 0, &event, 1, timeout);
940        assert(rv == 1);
941        assert(event.ident == cfd);
942        assert(event.filter == EVFILT_READ);
943        assert(event.flags == EV_EOF);
944        assert(event.fflags == 0);
945        assert(event.data == 0);
946        assert(event.udata == TEST_UDATA);
947
948        /*
949         * The master task wakes up during the shutdown() operation.  So we do
950         * not see the full shutdown.
951         */
952        rv = fstat(cfd, &st);
953        assert(rv == 0);
954        assert(st.st_mode == (S_IFSOCK | cansend));
955
956        rv = close(kq);
957        assert(rv == 0);
958}
959
960static void
961test_main(void)
962{
963        test_context *ctx = &test_instance;
964
965        setup_lo0();
966        set_self_prio(PRIO_MASTER);
967        start_worker(ctx);
968        create_server_socket(ctx);
969        create_client_addr(ctx);
970
971        test_select_timeout(ctx);
972        test_select_connect(ctx);
973        test_select_read(ctx);
974        test_select_write(ctx);
975        test_select_close(ctx);
976
977        test_poll_timeout(ctx);
978        test_poll_connect(ctx);
979        test_poll_read(ctx);
980        test_poll_write(ctx);
981        test_poll_close(ctx);
982
983        test_kqueue_timer(false);
984        test_kqueue_timer(true);
985        test_kqueue_connect(ctx);
986        test_kqueue_read(ctx);
987        test_kqueue_write(ctx);
988        test_kqueue_close(ctx);
989
990        rtems_stack_checker_report_usage_with_plugin(NULL,
991            rtems_printf_plugin);
992
993        puts("*** END OF " TEST_NAME " TEST ***");
994        exit(0);
995}
996
997#include <rtems/bsd/test/default-init.h>
Note: See TracBrowser for help on using the repository browser.