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
19static int __thread kqfd;
20
21void
22test_kevent_timer_add(void)
23{
24    struct kevent kev;
25
26    kevent_add(kqfd, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL);
27}
28
29void
30test_kevent_timer_del(void)
31{
32    struct kevent kev;
33
34    kevent_add(kqfd, &kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
35
36    test_no_kevents(kqfd);
37}
38
39void
40test_kevent_timer_get(void)
41{
42    struct kevent kev;
43
44    kevent_add(kqfd, &kev, 1, EVFILT_TIMER, EV_ADD, 0, 1000, NULL);
45
46    kev.flags |= EV_CLEAR;
47    kev.data = 1;
48    kevent_cmp(&kev, kevent_get(kqfd));
49
50    kevent_add(kqfd, &kev, 1, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
51}
52
53static void
54test_kevent_timer_oneshot(void)
55{
56    struct kevent kev;
57
58    test_no_kevents(kqfd);
59
60    kevent_add(kqfd, &kev, 2, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 500,NULL);
61
62    /* Retrieve the event */
63    kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT;
64    kev.data = 1;
65    kevent_cmp(&kev, kevent_get(kqfd));
66
67    /* Check if the event occurs again */
68    sleep(3);
69    test_no_kevents(kqfd);
70}
71
72static void
73test_kevent_timer_periodic(void)
74{
75    struct kevent kev;
76
77    test_no_kevents(kqfd);
78
79    kevent_add(kqfd, &kev, 3, EVFILT_TIMER, EV_ADD, 0, 1000,NULL);
80
81    /* Retrieve the event */
82    kev.flags = EV_ADD | EV_CLEAR;
83    kev.data = 1;
84    kevent_cmp(&kev, kevent_get(kqfd));
85
86    /* Check if the event occurs again */
87    sleep(1);
88    kevent_cmp(&kev, kevent_get(kqfd));
89
90    /* Delete the event */
91    kev.flags = EV_DELETE;
92    kevent_update(kqfd, &kev);
93}
94
95static void
96test_kevent_timer_disable_and_enable(void)
97{
98    struct kevent kev;
99
100    test_no_kevents(kqfd);
101
102    /* Add the watch and immediately disable it */
103    kevent_add(kqfd, &kev, 4, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, 2000,NULL);
104    kev.flags = EV_DISABLE;
105    kevent_update(kqfd, &kev);
106    test_no_kevents(kqfd);
107
108    /* Re-enable and check again */
109    kev.flags = EV_ENABLE;
110    kevent_update(kqfd, &kev);
111
112    kev.flags = EV_ADD | EV_CLEAR | EV_ONESHOT;
113    kev.data = 1;
114    kevent_cmp(&kev, kevent_get(kqfd));
115}
116
117#if HAVE_EV_DISPATCH
118void
119test_kevent_timer_dispatch(void)
120{
121    struct kevent kev;
122
123    test_no_kevents(kqfd);
124
125    kevent_add(kqfd, &kev, 4, EVFILT_TIMER, EV_ADD | EV_DISPATCH, 0, 800, NULL);
126
127    /* Get one event */
128    kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH;
129    kev.data = 1;
130    kevent_cmp(&kev, kevent_get(kqfd));
131
132    /* Confirm that the knote is disabled */
133    sleep(1);
134    test_no_kevents(kqfd);
135
136    /* Enable the knote and make sure no events are pending */
137    kevent_add(kqfd, &kev, 4, EVFILT_TIMER, EV_ENABLE | EV_DISPATCH, 0, 800, NULL);
138    test_no_kevents(kqfd);
139
140    /* Get the next event */
141    sleep(1);
142    kev.flags = EV_ADD | EV_CLEAR | EV_DISPATCH;
143    kev.data = 1;
144    kevent_cmp(&kev, kevent_get(kqfd));
145
146    /* Remove the knote and ensure the event no longer fires */
147    kevent_add(kqfd, &kev, 4, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
148    sleep(1);
149    test_no_kevents(kqfd);
150}
151#endif  /* HAVE_EV_DISPATCH */
152
153void
154test_evfilt_timer(int _kqfd)
155{
156	kqfd = _kqfd;
157    test(kevent_timer_add);
158    test(kevent_timer_del);
159    test(kevent_timer_get);
160    test(kevent_timer_oneshot);
161    test(kevent_timer_periodic);
162    test(kevent_timer_disable_and_enable);
163#if HAVE_EV_DISPATCH
164    test(kevent_timer_dispatch);
165#endif
166}
167