]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/regression/kqueue/main.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / regression / kqueue / main.c
1 /*
2  * Copyright (c) 2009 Mark Heily <mark@heily.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * $FreeBSD$
17  */
18
19 #include <sys/types.h>
20
21 #include "config.h"
22 #include "common.h"
23
24 int testnum = 1;
25 char *cur_test_id = NULL;
26 int kqfd;
27
28 extern void test_evfilt_read();
29 extern void test_evfilt_signal();
30 extern void test_evfilt_vnode();
31 extern void test_evfilt_timer();
32 extern void test_evfilt_proc();
33 #if HAVE_EVFILT_USER
34 extern void test_evfilt_user();
35 #endif
36
37 /* Checks if any events are pending, which is an error. */
38 void 
39 test_no_kevents(void)
40 {
41     int nfds;
42     struct timespec timeo;
43     struct kevent kev;
44
45     puts("confirming that there are no events pending");
46     memset(&timeo, 0, sizeof(timeo));
47     nfds = kevent(kqfd, NULL, 0, &kev, 1, &timeo);
48     if (nfds != 0) {
49         puts("\nUnexpected event:");
50         puts(kevent_to_str(&kev));
51         errx(1, "%d event(s) pending, but none expected:", nfds);
52     }
53 }
54
55 /* Retrieve a single kevent */
56 struct kevent *
57 kevent_get(int kqfd)
58 {
59     int nfds;
60     struct kevent *kev;
61
62     if ((kev = calloc(1, sizeof(*kev))) == NULL)
63         err(1, "out of memory");
64     
65     nfds = kevent(kqfd, NULL, 0, kev, 1, NULL);
66     if (nfds < 1)
67         err(1, "kevent(2)");
68
69     return (kev);
70 }
71
72 char *
73 kevent_fflags_dump(struct kevent *kev)
74 {
75     char *buf;
76
77 #define KEVFFL_DUMP(attrib) \
78     if (kev->fflags & attrib) \
79         strncat(buf, #attrib" ", 64);
80
81     if ((buf = calloc(1, 1024)) == NULL)
82         abort();
83
84     /* Not every filter has meaningful fflags */
85     if (kev->filter != EVFILT_VNODE) {
86         snprintf(buf, 1024, "fflags = %d", kev->fflags);
87         return (buf);
88     }
89
90     snprintf(buf, 1024, "fflags = %d (", kev->fflags);
91     KEVFFL_DUMP(NOTE_DELETE);
92     KEVFFL_DUMP(NOTE_WRITE);
93     KEVFFL_DUMP(NOTE_EXTEND);
94 #if HAVE_NOTE_TRUNCATE
95     KEVFFL_DUMP(NOTE_TRUNCATE);
96 #endif
97     KEVFFL_DUMP(NOTE_ATTRIB);
98     KEVFFL_DUMP(NOTE_LINK);
99     KEVFFL_DUMP(NOTE_RENAME);
100 #if HAVE_NOTE_REVOKE
101     KEVFFL_DUMP(NOTE_REVOKE);
102 #endif
103     buf[strlen(buf) - 1] = ')';
104
105     return (buf);
106 }
107
108 char *
109 kevent_flags_dump(struct kevent *kev)
110 {
111     char *buf;
112
113 #define KEVFL_DUMP(attrib) \
114     if (kev->flags & attrib) \
115         strncat(buf, #attrib" ", 64);
116
117     if ((buf = calloc(1, 1024)) == NULL)
118         abort();
119
120     snprintf(buf, 1024, "flags = %d (", kev->flags);
121     KEVFL_DUMP(EV_ADD);
122     KEVFL_DUMP(EV_ENABLE);
123     KEVFL_DUMP(EV_DISABLE);
124     KEVFL_DUMP(EV_DELETE);
125     KEVFL_DUMP(EV_ONESHOT);
126     KEVFL_DUMP(EV_CLEAR);
127     KEVFL_DUMP(EV_EOF);
128     KEVFL_DUMP(EV_ERROR);
129 #if HAVE_EV_DISPATCH
130     KEVFL_DUMP(EV_DISPATCH);
131 #endif
132 #if HAVE_EV_RECEIPT
133     KEVFL_DUMP(EV_RECEIPT);
134 #endif
135     buf[strlen(buf) - 1] = ')';
136
137     return (buf);
138 }
139
140 /* Copied from ../kevent.c kevent_dump() and improved */
141 const char *
142 kevent_to_str(struct kevent *kev)
143 {
144     char buf[512];
145
146     snprintf(&buf[0], sizeof(buf), 
147             "[ident=%d, filter=%d, %s, %s, data=%d, udata=%p]",
148             (u_int) kev->ident,
149             kev->filter,
150             kevent_flags_dump(kev),
151             kevent_fflags_dump(kev),
152             (int) kev->data,
153             kev->udata);
154
155     return (strdup(buf));
156 }
157
158 void
159 kevent_add(int kqfd, struct kevent *kev, 
160         uintptr_t ident,
161         short     filter,
162         u_short   flags,
163         u_int     fflags,
164         intptr_t  data,
165         void      *udata)
166 {
167     EV_SET(kev, ident, filter, flags, fflags, data, NULL);    
168     if (kevent(kqfd, kev, 1, NULL, 0, NULL) < 0) {
169         printf("Unable to add the following kevent:\n%s\n",
170                 kevent_to_str(kev));
171         err(1, "kevent(): %s", strerror(errno));
172     }
173 }
174
175 void
176 kevent_cmp(struct kevent *k1, struct kevent *k2)
177 {
178 /* XXX-
179    Workaround for inconsistent implementation of kevent(2) 
180  */
181 #ifdef __FreeBSD__
182     if (k1->flags & EV_ADD)
183         k2->flags |= EV_ADD;
184 #endif
185     if (memcmp(k1, k2, sizeof(*k1)) != 0) {
186         printf("kevent_cmp: mismatch:\n  %s !=\n  %s\n", 
187               kevent_to_str(k1), kevent_to_str(k2));
188         abort();
189     }
190 }
191
192 void
193 test_begin(const char *func)
194 {
195     if (cur_test_id)
196         free(cur_test_id);
197     cur_test_id = strdup(func);
198     if (!cur_test_id)
199         err(1, "strdup failed");
200
201     printf("\n\nTest %d: %s\n", testnum++, func);
202 }
203
204 void
205 success(void)
206 {
207     printf("%-70s %s\n", cur_test_id, "passed");
208     free(cur_test_id);
209     cur_test_id = NULL;
210 }
211
212 void
213 test_kqueue(void)
214 {
215     test_begin("kqueue()");
216     if ((kqfd = kqueue()) < 0)
217         err(1, "kqueue()");
218     test_no_kevents();
219     success();
220 }
221
222 void
223 test_kqueue_close(void)
224 {
225     test_begin("close(kq)");
226     if (close(kqfd) < 0)
227         err(1, "close()");
228     success();
229 }
230
231 int 
232 main(int argc, char **argv)
233 {
234     int test_proc = 1;
235     int test_socket = 1;
236     int test_signal = 1;
237     int test_vnode = 1;
238     int test_timer = 1;
239 #ifdef __FreeBSD__
240     int test_user = 1;
241 #else
242     /* XXX-FIXME temporary */
243     int test_user = 0;
244 #endif
245
246     while (argc) {
247         if (strcmp(argv[0], "--no-proc") == 0)
248             test_proc = 0;
249         if (strcmp(argv[0], "--no-socket") == 0)
250             test_socket = 0;
251         if (strcmp(argv[0], "--no-timer") == 0)
252             test_timer = 0;
253         if (strcmp(argv[0], "--no-signal") == 0)
254             test_signal = 0;
255         if (strcmp(argv[0], "--no-vnode") == 0)
256             test_vnode = 0;
257         if (strcmp(argv[0], "--no-user") == 0)
258             test_user = 0;
259         argv++;
260         argc--;
261     }
262
263     test_kqueue();
264     test_kqueue_close();
265
266     if (test_socket) 
267         test_evfilt_read();
268     if (test_signal) 
269         test_evfilt_signal();
270     if (test_vnode) 
271         test_evfilt_vnode();
272 #if HAVE_EVFILT_USER
273     if (test_user) 
274         test_evfilt_user();
275 #endif
276     if (test_timer) 
277         test_evfilt_timer();
278     if (test_proc) 
279         test_evfilt_proc();
280
281     printf("\n---\n"
282             "+OK All %d tests completed.\n", testnum - 1);
283     return (0);
284 }