xref: /freebsd/tests/sys/kqueue/libkqueue/timer.c (revision 2b34e843)
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 "common.h"
20 #include <sys/time.h>
21 
22 int kqfd;
23 
24 void
25 test_kevent_timer_add(void)
26 {
27     const char *test_id = "kevent(EVFILT_TIMER, EV_ADD)";
28     struct kevent kev;
29 
30     test_begin(test_id);
31 
32     EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL);
33     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
34         err(1, "%s", test_id);
35 
36     success();
37 }
38 
39 void
40 test_kevent_timer_del(void)
41 {
42     const char *test_id = "kevent(EVFILT_TIMER, EV_DELETE)";
43     struct kevent kev;
44 
45     test_begin(test_id);
46 
47     EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
48     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
49         err(1, "%s", test_id);
50 
51     test_no_kevents();
52 
53     success();
54 }
55 
56 void
57 test_kevent_timer_get(void)
58 {
59     const char *test_id = "kevent(EVFILT_TIMER, wait)";
60     struct kevent kev;
61 
62     test_begin(test_id);
63 
64     EV_SET(&kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL);
65     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
66         err(1, "%s", test_id);
67 
68     kev.flags |= EV_CLEAR;
69     kev.data = 1;
70     kevent_cmp(&kev, kevent_get(kqfd));
71 
72     EV_SET(&kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
73     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
74         err(1, "%s", test_id);
75 
76     success();
77 }
78 
79 static void
80 test_oneshot(void)
81 {
82     const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT)";
83     struct kevent kev;
84 
85     test_begin(test_id);
86 
87     test_no_kevents();
88 
89     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL);
90     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
91         err(1, "%s", test_id);
92 
93     /* Retrieve the event */
94     kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT;
95     kev.data = 1;
96     kevent_cmp(&kev, kevent_get(kqfd));
97 
98     /* Check if the event occurs again */
99     sleep(3);
100     test_no_kevents();
101 
102 
103     success();
104 }
105 
106 static void
107 test_periodic(void)
108 {
109     const char *test_id = "kevent(EVFILT_TIMER, periodic)";
110     struct kevent kev;
111 
112     test_begin(test_id);
113 
114     test_no_kevents();
115 
116     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD, 0, 1000,NULL);
117     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
118         err(1, "%s", test_id);
119 
120     /* Retrieve the event */
121     kev.flags = EV_ADD | EV_CLEAR;
122     kev.data = 1;
123     kevent_cmp(&kev, kevent_get(kqfd));
124 
125     /* Check if the event occurs again */
126     sleep(1);
127     kevent_cmp(&kev, kevent_get(kqfd));
128 
129     /* Delete the event */
130     kev.flags = EV_DELETE;
131     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
132         err(1, "%s", test_id);
133 
134     success();
135 }
136 
137 static void
138 disable_and_enable(void)
139 {
140     const char *test_id = "kevent(EVFILT_TIMER, EV_DISABLE and EV_ENABLE)";
141     struct kevent kev;
142 
143     test_begin(test_id);
144 
145     test_no_kevents();
146 
147     /* Add the watch and immediately disable it */
148     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL);
149     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
150         err(1, "%s", test_id);
151     kev.flags = EV_DISABLE;
152     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
153         err(1, "%s", test_id);
154     test_no_kevents();
155 
156     /* Re-enable and check again */
157     kev.flags = EV_ENABLE;
158     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
159         err(1, "%s", test_id);
160 
161     kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT;
162     kev.data = 1;
163     kevent_cmp(&kev, kevent_get(kqfd));
164 
165     success();
166 }
167 
168 static void
169 test_abstime(void)
170 {
171     const char *test_id = "kevent(EVFILT_TIMER, EV_ONESHOT, NOTE_ABSTIME)";
172     struct kevent kev;
173     time_t when;
174     const int timeout = 3;
175 
176     test_begin(test_id);
177 
178     test_no_kevents();
179 
180     when = time(NULL);
181     EV_SET(&kev, vnode_fd, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
182       NOTE_ABSTIME | NOTE_SECONDS, when + timeout, NULL);
183     if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
184         err(1, "%s", test_id);
185 
186     /* Retrieve the event */
187     kev.flags = EV_ADD | EV_ONESHOT;
188     kev.data = 1;
189     kev.fflags = 0;
190     kevent_cmp(&kev, kevent_get(kqfd));
191     if (time(NULL) < when + timeout)
192 	err(1, "too early %jd %jd", time(), when + timeout);
193 
194     /* Check if the event occurs again */
195     sleep(3);
196     test_no_kevents();
197 
198     success();
199 }
200 
201 void
202 test_evfilt_timer()
203 {
204 	kqfd = kqueue();
205     test_kevent_timer_add();
206     test_kevent_timer_del();
207     test_kevent_timer_get();
208     test_oneshot();
209     test_periodic();
210     test_abstime();
211     disable_and_enable();
212 	close(kqfd);
213 }
214