Tizen 2.1 base
[platform/upstream/gcd.git] / kqueue-1.0.4 / test / vnode.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
17 #include "common.h"
18
19 static int __thread kqfd;
20 static int __thread vnode_fd;
21 static char __thread testfile[1024];
22
23
24 /* Create an empty file */
25 static void
26 testfile_create(void)
27 {
28     int fd;
29
30     if ((fd = open(testfile, O_CREAT | O_WRONLY, 0600)) < 0)
31         die("open");
32     close(fd);
33 }
34
35 static void
36 testfile_touch(void)
37 {
38     char buf[1024];
39
40     snprintf(&buf[0], sizeof(buf), "touch %s", testfile);
41     if (system(buf) != 0)
42         die("system"); 
43 }
44
45 static void
46 testfile_write(void)
47 {
48     char buf[1024];
49
50     snprintf(&buf[0], sizeof(buf), "echo hi >> %s", testfile);
51     if (system(buf) != 0)
52         die("system"); 
53 }
54
55 static void
56 testfile_rename(int step)
57 {
58     char buf[1024];
59
60     snprintf(&buf[0], sizeof(buf), "%s.tmp", testfile);
61     /* XXX-FIXME use of 'step' conceals a major memory corruption
62             when the file is renamed twice.
63             To replicate, remove "if step" conditional so
64             two renames occur in this function.
65             */
66     if (step == 0) {
67         if (rename(testfile,buf) != 0)
68             err(1,"rename"); 
69     } else {
70         if (rename(buf, testfile) != 0)
71             err(1,"rename"); 
72     }
73 }
74
75 void
76 test_kevent_vnode_add(void)
77 {
78     struct kevent kev;
79
80     testfile_create();
81
82     vnode_fd = open(testfile, O_RDWR);
83     if (vnode_fd < 0)
84         err(1, "open of %s", testfile);
85
86     kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD, 
87             NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME | NOTE_DELETE, 0, NULL);
88 }
89
90 void
91 test_kevent_vnode_note_delete(void)
92 {
93     struct kevent kev;
94
95     kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_DELETE, 0, NULL);
96
97     if (unlink(testfile) < 0)
98         die("unlink");
99
100     kevent_cmp(&kev, kevent_get(kqfd));
101 }
102
103 void
104 test_kevent_vnode_note_write(void)
105 {
106     struct kevent kev;
107
108     kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_WRITE, 0, NULL);
109
110     testfile_write();
111
112     /* BSD kqueue adds NOTE_EXTEND even though it was not requested */
113     /* BSD kqueue removes EV_ENABLE */
114     kev.flags &= ~EV_ENABLE; // XXX-FIXME compatibility issue
115     kev.fflags |= NOTE_EXTEND; // XXX-FIXME compatibility issue
116     kevent_cmp(&kev, kevent_get(kqfd));
117 }
118
119 void
120 test_kevent_vnode_note_attrib(void)
121 {
122     struct kevent kev;
123     int nfds;
124
125     kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
126
127     testfile_touch();
128
129     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
130     if (nfds < 1)
131         die("kevent");
132     if (kev.ident != vnode_fd ||
133             kev.filter != EVFILT_VNODE || 
134             kev.fflags != NOTE_ATTRIB)
135         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", 
136                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
137 }
138
139 void
140 test_kevent_vnode_note_rename(void)
141 {
142     struct kevent kev;
143     int nfds;
144
145     kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_RENAME, 0, NULL);
146
147     testfile_rename(0);
148
149     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
150     if (nfds < 1)
151         die("kevent");
152     if (kev.ident != vnode_fd ||
153             kev.filter != EVFILT_VNODE || 
154             kev.fflags != NOTE_RENAME)
155         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", 
156                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
157
158     testfile_rename(1);
159
160     test_no_kevents(kqfd);
161 }
162
163 void
164 test_kevent_vnode_del(void)
165 {
166     struct kevent kev;
167
168     kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_DELETE, 0, 0, NULL);
169 }
170
171 void
172 test_kevent_vnode_disable_and_enable(void)
173 {
174     struct kevent kev;
175     int nfds;
176
177     test_no_kevents(kqfd);
178
179     /* Add the watch and immediately disable it */
180     kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_ONESHOT, NOTE_ATTRIB, 0, NULL);
181     kev.flags = EV_DISABLE;
182     kevent_update(kqfd, &kev);
183
184     /* Confirm that the watch is disabled */
185     testfile_touch();
186     test_no_kevents(kqfd);
187
188     /* Re-enable and check again */
189     kev.flags = EV_ENABLE;
190     kevent_update(kqfd, &kev);
191     testfile_touch();
192     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
193     if (nfds < 1)
194         die("kevent");
195     if (kev.ident != vnode_fd ||
196             kev.filter != EVFILT_VNODE || 
197             kev.fflags != NOTE_ATTRIB)
198         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", 
199                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
200 }
201
202 #if HAVE_EV_DISPATCH
203 void
204 test_kevent_vnode_dispatch(void)
205 {
206     struct kevent kev;
207     int nfds;
208
209     test_no_kevents(kqfd);
210
211     kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ADD | EV_DISPATCH, NOTE_ATTRIB, 0, NULL);
212
213     testfile_touch();
214
215     nfds = kevent(kqfd, NULL, 0, &kev, 1, NULL);
216     if (nfds < 1)
217         die("kevent");
218     if (kev.ident != vnode_fd ||
219             kev.filter != EVFILT_VNODE || 
220             kev.fflags != NOTE_ATTRIB)
221         err(1, "%s - incorrect event (sig=%u; filt=%d; flags=%d)", 
222                 test_id, (unsigned int)kev.ident, kev.filter, kev.flags);
223
224     /* Confirm that the watch is disabled automatically */
225     testfile_touch();
226     test_no_kevents(kqfd);
227
228     /* Re-enable the kevent */
229     /* FIXME- is EV_DISPATCH needed when rearming ? */
230     kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_ENABLE | EV_DISPATCH, 0, 0, NULL);
231     kev.flags = EV_ADD | EV_DISPATCH;   /* FIXME: may not be portable */
232     kev.fflags = NOTE_ATTRIB;
233     testfile_touch();
234     kevent_cmp(&kev, kevent_get(kqfd));
235     test_no_kevents(kqfd);
236
237     /* Delete the watch */
238     kevent_add(kqfd, &kev, vnode_fd, EVFILT_VNODE, EV_DELETE, NOTE_ATTRIB, 0, NULL);
239 }
240 #endif  /* HAVE_EV_DISPATCH */
241
242 void
243 test_evfilt_vnode(int _kqfd)
244 {
245     snprintf(testfile, sizeof(testfile), "/tmp/kqueue-test%d.tmp",
246             testing_make_uid());
247
248         kqfd = _kqfd;
249     test(kevent_vnode_add);
250     test(kevent_vnode_del);
251     test(kevent_vnode_disable_and_enable);
252 #if HAVE_EV_DISPATCH
253     test(kevent_vnode_dispatch);
254 #endif
255     test(kevent_vnode_note_write);
256     test(kevent_vnode_note_attrib);
257     test(kevent_vnode_note_rename);
258     test(kevent_vnode_note_delete);
259     unlink(testfile);
260 }