]> git.saurik.com Git - apple/xnu.git/blame - tests/kqueue_fifo_18776047.c
xnu-4903.241.1.tar.gz
[apple/xnu.git] / tests / kqueue_fifo_18776047.c
CommitLineData
39037602
A
1/*
2 * testname: kqueue_fifo
3 */
4
5#include <darwintest.h>
6#include <fcntl.h>
7#include <sys/event.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <unistd.h>
11#include <stdlib.h>
12#include <errno.h>
13
5ba3f43e
A
14#include <TargetConditionals.h>
15
39037602
A
16#define TMP_FILE_PATH "/tmp/test_kqueue_fifo_18776047"
17
18#define READ_BUFFER_LEN 256
19
5ba3f43e 20#if TARGET_OS_WATCH
39037602
A
21#define TOTAL_ITERATIONS 5000
22#else
23#define TOTAL_ITERATIONS 10000
24#endif
25
26/* prototypes */
27int write_some_data(int fd);
28int read_data(int fd);
29void create_fifo(const char * filepath);
30void kevent_one_shot(int kq, int fd, int filter);
31
32int
33write_some_data(int fd)
34{
35 int retval = 0;
36 int count = 0;
37 int len = 5;
38 char * data = "ABCDE";
39 while (true) {
40 errno = 0;
41 retval = (int)write(fd, data, (size_t)len);
42 if (retval < 0) {
43 if (errno == EAGAIN) {
44 if (len == 1)
45 return count;
46 else
47 len--;
48 } else {
49 T_ASSERT_FAIL("write to fd %d of %s of len %d failed.", fd, data, len);
50 abort();
51 }
52 } else {
53 count += retval;
54 }
55 }
56}
57
58int
59read_data(int fd)
60{
61 int retval, count = 0;
62 char databuffer[READ_BUFFER_LEN];
63 while (true) {
64 errno = 0;
65 retval = (int)read(fd, databuffer, READ_BUFFER_LEN);
66 if (retval < 0) {
67 if (errno == EAGAIN) {
68 return count;
69 } else {
70 T_ASSERT_FAIL("read from fd %d failed.", fd);
71 abort();
72 }
73 }
74 count += retval;
75 }
76}
77
78void
79create_fifo(const char * filepath)
80{
81 struct stat f_stat;
82 int ret = 0;
83 errno = 0;
84 ret = stat(filepath, &f_stat);
85 if (ret == 0) {
86 /* if file exists, make sure its a fifo */
87 T_ASSERT_TRUE(S_ISFIFO(f_stat.st_mode), "ensure %s is a fifo", filepath);
88 } else if (errno == ENOENT) {
89 ret = mkfifo(filepath, 0777);
90 T_ASSERT_POSIX_ZERO(ret, "creating a fifo at path %s", filepath);
91 } else {
92 T_ASSERT_FAIL("stat operation on %s", filepath);
93 }
94}
95
96void
97kevent_one_shot(int kq, int fd, int filter)
98{
99 int retval = 0;
100 struct timespec t_zero = {0, 0};
101 struct kevent kev[1];
102
103 T_QUIET;
104 T_ASSERT_GE(kq, 0, "ensure kq is valid");
105 T_LOG("kevent doing ONESHOT %s", filter == EVFILT_READ ? "read" : "write");
106
107 EV_SET(kev, fd, filter, EV_ADD | EV_ONESHOT, 0, 0, NULL);
108 retval = kevent(kq, kev, 1, NULL, 0, &t_zero);
109 T_QUIET;
110 T_ASSERT_POSIX_ZERO(retval, "ONESHOT kevent for fd %d, filter %d", fd, filter);
111}
112
813fb2f6 113T_DECL(kqueue_fifo_18776047, "Tests kqueue, kevent for watching a fifo.", T_META_LTEPHASE(LTE_POSTINIT))
39037602
A
114{
115 struct kevent kev[1];
116 int read_fd, write_fd, kq;
117 int retval = 0;
118 int iter = 0;
119 const char * fpath = TMP_FILE_PATH;
120 T_SETUPBEGIN;
121 create_fifo(fpath);
122
123 kq = kqueue();
124 T_ASSERT_GE(kq, 0, "create a kqueue");
125
126 read_fd = open(fpath, O_RDONLY | O_APPEND | O_NONBLOCK);
127 T_ASSERT_POSIX_SUCCESS(read_fd, "opening read fd on fifo.");
128
129 write_fd = open(fpath, O_WRONLY | O_APPEND | O_NONBLOCK);
130 T_ASSERT_POSIX_SUCCESS(write_fd, "opening write fd on fifo.");
131
132 T_SETUPEND;
133
134 kevent_one_shot(kq, write_fd, EVFILT_WRITE);
135 kevent_one_shot(kq, read_fd, EVFILT_READ);
136
137 while (iter++ < TOTAL_ITERATIONS) {
138 retval = kevent(kq, NULL, 0, kev, 1, NULL);
139 T_QUIET;
140 T_ASSERT_GE(retval, 0, "kevent on kq %d", kq);
141
142 if (kev[0].ident == (uintptr_t)write_fd) {
143 retval = write_some_data(write_fd);
144 T_LOG("writer ready iter: %d wrote %d bytes", iter, retval);
145 kevent_one_shot(kq, write_fd, EVFILT_WRITE);
146 } else if (kev[0].ident == (uintptr_t)read_fd) {
147 retval = read_data(read_fd);
148 T_LOG("reader ready iter: %d read %d bytes", iter, retval);
149 kevent_one_shot(kq, read_fd, EVFILT_READ);
150 }
151 }
152 T_PASS("kqueue_fifo_18776047 PASSED");
153}