xref: /netbsd-src/tests/kernel/kqueue/t_timer.c (revision ae0245f0df673b85ba0c283bf444f7b2468957ab)
1*ae0245f0Shannken /* $NetBSD: t_timer.c,v 1.4 2021/11/21 09:35:39 hannken Exp $ */
2dbceac44Sthorpej 
3dbceac44Sthorpej /*-
4dbceac44Sthorpej  * Copyright (c) 2021 The NetBSD Foundation, Inc.
5dbceac44Sthorpej  * All rights reserved.
6dbceac44Sthorpej  *
7dbceac44Sthorpej  * Redistribution and use in source and binary forms, with or without
8dbceac44Sthorpej  * modification, are permitted provided that the following conditions
9dbceac44Sthorpej  * are met:
10dbceac44Sthorpej  * 1. Redistributions of source code must retain the above copyright
11dbceac44Sthorpej  *    notice, this list of conditions and the following disclaimer.
12dbceac44Sthorpej  * 2. Redistributions in binary form must reproduce the above copyright
13dbceac44Sthorpej  *    notice, this list of conditions and the following disclaimer in the
14dbceac44Sthorpej  *    documentation and/or other materials provided with the distribution.
15dbceac44Sthorpej  *
16dbceac44Sthorpej  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17dbceac44Sthorpej  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18dbceac44Sthorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19dbceac44Sthorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20dbceac44Sthorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21dbceac44Sthorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22dbceac44Sthorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23dbceac44Sthorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24dbceac44Sthorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25dbceac44Sthorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26dbceac44Sthorpej  * POSSIBILITY OF SUCH DAMAGE.
27dbceac44Sthorpej  */
28dbceac44Sthorpej 
29dbceac44Sthorpej #include <sys/cdefs.h>
30*ae0245f0Shannken __RCSID("$NetBSD: t_timer.c,v 1.4 2021/11/21 09:35:39 hannken Exp $");
31dbceac44Sthorpej 
32dbceac44Sthorpej #include <sys/types.h>
33dbceac44Sthorpej #include <sys/event.h>
34dbceac44Sthorpej #include <errno.h>
35dbceac44Sthorpej #include <stdio.h>
36dbceac44Sthorpej #include <stdlib.h>
37dbceac44Sthorpej #include <time.h>
38dbceac44Sthorpej #include <unistd.h>
39dbceac44Sthorpej 
40dbceac44Sthorpej #include <atf-c.h>
41dbceac44Sthorpej 
42*ae0245f0Shannken #include "isqemu.h"
43*ae0245f0Shannken 
44*ae0245f0Shannken static bool
check_timespec(struct timespec * ts,time_t seconds)45*ae0245f0Shannken check_timespec(struct timespec *ts, time_t seconds)
46*ae0245f0Shannken {
47*ae0245f0Shannken 	time_t upper = seconds;
48*ae0245f0Shannken 	bool result = true;
49*ae0245f0Shannken 
50*ae0245f0Shannken 	/*
51*ae0245f0Shannken 	 * If running under QEMU make sure the upper bound is large
52*ae0245f0Shannken 	 * enough for the effect of kern/43997
53*ae0245f0Shannken 	 */
54*ae0245f0Shannken 	if (isQEMU()) {
55*ae0245f0Shannken 		upper *= 4;
56*ae0245f0Shannken 	}
57*ae0245f0Shannken 
58*ae0245f0Shannken 	if (ts->tv_sec < seconds - 1 ||
59*ae0245f0Shannken 	    (ts->tv_sec == seconds - 1 && ts->tv_nsec < 500000000))
60*ae0245f0Shannken 		result = false;
61*ae0245f0Shannken 	else if (ts->tv_sec > upper ||
62*ae0245f0Shannken 	    (ts->tv_sec == upper && ts->tv_nsec >= 500000000))
63*ae0245f0Shannken 		result = false;
64*ae0245f0Shannken 
65*ae0245f0Shannken 	printf("time %" PRId64 ".%09ld %sin [ %" PRId64 ".5, %" PRId64 ".5 )\n",
66*ae0245f0Shannken 		ts->tv_sec, ts->tv_nsec, (result ? "" : "not "),
67*ae0245f0Shannken 		seconds - 1, upper);
68*ae0245f0Shannken 
69*ae0245f0Shannken 	return result;
70*ae0245f0Shannken }
71*ae0245f0Shannken 
72dbceac44Sthorpej ATF_TC(basic_timer);
ATF_TC_HEAD(basic_timer,tc)73dbceac44Sthorpej ATF_TC_HEAD(basic_timer, tc)
74dbceac44Sthorpej {
75dbceac44Sthorpej 	atf_tc_set_md_var(tc, "descr",
76dbceac44Sthorpej 	    "tests basic EVFILT_TIMER functionality");
77dbceac44Sthorpej }
78dbceac44Sthorpej 
79dbceac44Sthorpej #define	TIME1		1000		/* 1000ms -> 1s */
80dbceac44Sthorpej #define	TIME1_COUNT	5
81dbceac44Sthorpej #define	TIME2		6000		/* 6000ms -> 6s */
82dbceac44Sthorpej 
83dbceac44Sthorpej #define	TIME1_TOTAL_SEC	((TIME1 * TIME1_COUNT) / 1000)
84dbceac44Sthorpej #define	TIME2_TOTAL_SEC	(TIME2 / 1000)
85dbceac44Sthorpej 
ATF_TC_BODY(basic_timer,tc)86dbceac44Sthorpej ATF_TC_BODY(basic_timer, tc)
87dbceac44Sthorpej {
88dbceac44Sthorpej 	struct kevent event[2];
89dbceac44Sthorpej 	int ntimer1 = 0, ntimer2 = 0;
90dbceac44Sthorpej 	struct timespec ots, ts;
91dbceac44Sthorpej 	int kq;
92dbceac44Sthorpej 
93dbceac44Sthorpej 	ATF_REQUIRE((kq = kqueue()) >= 0);
94dbceac44Sthorpej 
95dbceac44Sthorpej 	EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, TIME1, NULL);
96dbceac44Sthorpej 	EV_SET(&event[1], 2, EVFILT_TIMER, EV_ADD | EV_ONESHOT, 0, TIME2, NULL);
97dbceac44Sthorpej 
98dbceac44Sthorpej 	ATF_REQUIRE(kevent(kq, event, 2, NULL, 0, NULL) == 0);
99dbceac44Sthorpej 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ots) == 0);
100dbceac44Sthorpej 
101dbceac44Sthorpej 	for (;;) {
102dbceac44Sthorpej 		ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, NULL) == 1);
103dbceac44Sthorpej 		ATF_REQUIRE(event[0].filter == EVFILT_TIMER);
104dbceac44Sthorpej 		ATF_REQUIRE(event[0].ident == 1 ||
105dbceac44Sthorpej 			    event[0].ident == 2);
106dbceac44Sthorpej 		if (event[0].ident == 1) {
107dbceac44Sthorpej 			ATF_REQUIRE(ntimer1 < TIME1_COUNT);
108dbceac44Sthorpej 			if (++ntimer1 == TIME1_COUNT) {
109dbceac44Sthorpej 				/*
110dbceac44Sthorpej 				 * Make sure TIME1_TOTAL_SEC seconds have
111dbceac44Sthorpej 				 * elapsed, allowing for a little slop.
112dbceac44Sthorpej 				 */
113dbceac44Sthorpej 				ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC,
114dbceac44Sthorpej 				    &ts) == 0);
115dbceac44Sthorpej 				timespecsub(&ts, &ots, &ts);
116*ae0245f0Shannken 				ATF_REQUIRE(check_timespec(&ts,
117*ae0245f0Shannken 				    TIME1_TOTAL_SEC));
118dbceac44Sthorpej 				EV_SET(&event[0], 1, EVFILT_TIMER, EV_DELETE,
119dbceac44Sthorpej 				    0, 0, NULL);
120dbceac44Sthorpej 				ATF_REQUIRE(kevent(kq, event, 1, NULL, 0,
121dbceac44Sthorpej 				    NULL) == 0);
122dbceac44Sthorpej 			}
123dbceac44Sthorpej 		} else {
124dbceac44Sthorpej 			ATF_REQUIRE(ntimer1 == TIME1_COUNT);
125dbceac44Sthorpej 			ATF_REQUIRE(ntimer2 == 0);
126dbceac44Sthorpej 			ntimer2++;
127dbceac44Sthorpej 			/*
128dbceac44Sthorpej 			 * Make sure TIME2_TOTAL_SEC seconds have
129dbceac44Sthorpej 			 * elapsed, allowing for a little slop.
130dbceac44Sthorpej 			 */
131dbceac44Sthorpej 			ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC,
132dbceac44Sthorpej 			    &ts) == 0);
133dbceac44Sthorpej 			timespecsub(&ts, &ots, &ts);
134*ae0245f0Shannken 			ATF_REQUIRE(check_timespec(&ts, TIME2_TOTAL_SEC));
135dbceac44Sthorpej 			EV_SET(&event[0], 2, EVFILT_TIMER, EV_DELETE,
136dbceac44Sthorpej 			    0, 0, NULL);
137dbceac44Sthorpej 			ATF_REQUIRE_ERRNO(ENOENT,
138dbceac44Sthorpej 			    kevent(kq, event, 1, NULL, 0, NULL) == -1);
139dbceac44Sthorpej 			break;
140dbceac44Sthorpej 		}
141dbceac44Sthorpej 	}
142dbceac44Sthorpej 
143dbceac44Sthorpej 	/*
144dbceac44Sthorpej 	 * Now block in kqueue for TIME2_TOTAL_SEC, and ensure we
145dbceac44Sthorpej 	 * don't receive any new events.
146dbceac44Sthorpej 	 */
147dbceac44Sthorpej 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ots) == 0);
148dbceac44Sthorpej 	ts.tv_sec = TIME2_TOTAL_SEC;
149dbceac44Sthorpej 	ts.tv_nsec = 0;
150dbceac44Sthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 0);
151dbceac44Sthorpej 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
152dbceac44Sthorpej 	timespecsub(&ts, &ots, &ts);
153*ae0245f0Shannken 	ATF_REQUIRE(check_timespec(&ts, TIME2_TOTAL_SEC));
154dbceac44Sthorpej }
155dbceac44Sthorpej 
156dbceac44Sthorpej ATF_TC(count_expirations);
ATF_TC_HEAD(count_expirations,tc)157dbceac44Sthorpej ATF_TC_HEAD(count_expirations, tc)
158dbceac44Sthorpej {
159dbceac44Sthorpej 	atf_tc_set_md_var(tc, "descr",
160dbceac44Sthorpej 	    "tests counting timer expirations");
161dbceac44Sthorpej }
162dbceac44Sthorpej 
ATF_TC_BODY(count_expirations,tc)163dbceac44Sthorpej ATF_TC_BODY(count_expirations, tc)
164dbceac44Sthorpej {
165dbceac44Sthorpej 	struct kevent event[1];
166dbceac44Sthorpej 	struct timespec ts = { 0, 0 };
167dbceac44Sthorpej 	struct timespec sleepts;
168dbceac44Sthorpej 	int kq;
169dbceac44Sthorpej 
170dbceac44Sthorpej 	ATF_REQUIRE((kq = kqueue()) >= 0);
171dbceac44Sthorpej 
172dbceac44Sthorpej 	EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, TIME1, NULL);
173dbceac44Sthorpej 	ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0);
174dbceac44Sthorpej 
175dbceac44Sthorpej 	/* Sleep a little longer to mitigate timing jitter. */
176dbceac44Sthorpej 	sleepts.tv_sec = TIME1_TOTAL_SEC;
177dbceac44Sthorpej 	sleepts.tv_nsec = 500000000;
178dbceac44Sthorpej 	ATF_REQUIRE(nanosleep(&sleepts, NULL) == 0);
179dbceac44Sthorpej 
180dbceac44Sthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 1);
181dbceac44Sthorpej 	ATF_REQUIRE(event[0].ident == 1);
182dbceac44Sthorpej 	ATF_REQUIRE(event[0].data == TIME1_COUNT ||
183dbceac44Sthorpej 		    event[0].data == TIME1_COUNT + 1);
184dbceac44Sthorpej }
185dbceac44Sthorpej 
186317dcfdbSthorpej ATF_TC(modify);
ATF_TC_HEAD(modify,tc)187317dcfdbSthorpej ATF_TC_HEAD(modify, tc)
188317dcfdbSthorpej {
189317dcfdbSthorpej 	atf_tc_set_md_var(tc, "descr",
190317dcfdbSthorpej 	    "tests modifying a timer");
191317dcfdbSthorpej }
192317dcfdbSthorpej 
ATF_TC_BODY(modify,tc)193317dcfdbSthorpej ATF_TC_BODY(modify, tc)
194317dcfdbSthorpej {
195317dcfdbSthorpej 	struct kevent event[1];
196317dcfdbSthorpej 	struct timespec ts = { 0, 0 };
197317dcfdbSthorpej 	struct timespec sleepts;
198317dcfdbSthorpej 	int kq;
199317dcfdbSthorpej 
200317dcfdbSthorpej 	ATF_REQUIRE((kq = kqueue()) >= 0);
201317dcfdbSthorpej 
202317dcfdbSthorpej 	/*
203317dcfdbSthorpej 	 * Start a 500ms timer, sleep for 5 seconds, and check
204317dcfdbSthorpej 	 * the total count.
205317dcfdbSthorpej 	 */
206317dcfdbSthorpej 	EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, 500, NULL);
207317dcfdbSthorpej 	ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0);
208317dcfdbSthorpej 
209317dcfdbSthorpej 	sleepts.tv_sec = 5;
210317dcfdbSthorpej 	sleepts.tv_nsec = 0;
211317dcfdbSthorpej 	ATF_REQUIRE(nanosleep(&sleepts, NULL) == 0);
212317dcfdbSthorpej 
213317dcfdbSthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 1);
214317dcfdbSthorpej 	ATF_REQUIRE(event[0].ident == 1);
215317dcfdbSthorpej 	ATF_REQUIRE(event[0].data >= 9 && event[0].data <= 11);
216317dcfdbSthorpej 
217317dcfdbSthorpej 	/*
218317dcfdbSthorpej 	 * Modify to a 4 second timer, sleep for 5 seconds, and check
219317dcfdbSthorpej 	 * the total count.
220317dcfdbSthorpej 	 */
221317dcfdbSthorpej 	EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, 4000, NULL);
222317dcfdbSthorpej 	ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0);
223317dcfdbSthorpej 
2249c9b24b6Sthorpej 	/*
2259c9b24b6Sthorpej 	 * Before we sleep, verify that the knote for this timer is
2269c9b24b6Sthorpej 	 * no longer activated.
2279c9b24b6Sthorpej 	 */
2289c9b24b6Sthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 0);
2299c9b24b6Sthorpej 
230317dcfdbSthorpej 	sleepts.tv_sec = 5;
231317dcfdbSthorpej 	sleepts.tv_nsec = 0;
232317dcfdbSthorpej 	ATF_REQUIRE(nanosleep(&sleepts, NULL) == 0);
233317dcfdbSthorpej 
234317dcfdbSthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 1);
235317dcfdbSthorpej 	ATF_REQUIRE(event[0].ident == 1);
236317dcfdbSthorpej 	ATF_REQUIRE(event[0].data == 1);
237317dcfdbSthorpej 
238317dcfdbSthorpej 	/*
239317dcfdbSthorpej 	 * Start a 500ms timer, sleep for 2 seconds.
240317dcfdbSthorpej 	 */
241317dcfdbSthorpej 	EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, 500, NULL);
242317dcfdbSthorpej 	ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0);
243317dcfdbSthorpej 
244317dcfdbSthorpej 	sleepts.tv_sec = 2;
245317dcfdbSthorpej 	sleepts.tv_nsec = 0;
246317dcfdbSthorpej 	ATF_REQUIRE(nanosleep(&sleepts, NULL) == 0);
247317dcfdbSthorpej 
248317dcfdbSthorpej 	/*
249317dcfdbSthorpej 	 * Set the SAME timer, sleep for 2 seconds.
250317dcfdbSthorpej 	 */
251317dcfdbSthorpej 	EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD, 0, 500, NULL);
252317dcfdbSthorpej 	ATF_REQUIRE(kevent(kq, event, 1, NULL, 0, NULL) == 0);
253317dcfdbSthorpej 
254317dcfdbSthorpej 	sleepts.tv_sec = 2;
255317dcfdbSthorpej 	sleepts.tv_nsec = 0;
256317dcfdbSthorpej 	ATF_REQUIRE(nanosleep(&sleepts, NULL) == 0);
257317dcfdbSthorpej 
258317dcfdbSthorpej 	/*
259317dcfdbSthorpej 	 * The kernel should have reset the count when modifying the
260317dcfdbSthorpej 	 * timer, so we should only expect to see the expiration count
261317dcfdbSthorpej 	 * for the second sleep.
262317dcfdbSthorpej 	 */
263317dcfdbSthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 1);
264317dcfdbSthorpej 	ATF_REQUIRE(event[0].ident == 1);
265317dcfdbSthorpej 	ATF_REQUIRE(event[0].data >= 3 && event[0].data <= 5);
266317dcfdbSthorpej }
267317dcfdbSthorpej 
268dbceac44Sthorpej ATF_TC(abstime);
ATF_TC_HEAD(abstime,tc)269dbceac44Sthorpej ATF_TC_HEAD(abstime, tc)
270dbceac44Sthorpej {
271dbceac44Sthorpej 	atf_tc_set_md_var(tc, "descr",
272dbceac44Sthorpej 	    "tests timers with NOTE_ABSTIME");
273dbceac44Sthorpej }
274dbceac44Sthorpej 
ATF_TC_BODY(abstime,tc)275dbceac44Sthorpej ATF_TC_BODY(abstime, tc)
276dbceac44Sthorpej {
277dbceac44Sthorpej 	struct kevent event[1];
278dbceac44Sthorpej 	struct timespec ts, ots;
279dbceac44Sthorpej 	time_t seconds;
280dbceac44Sthorpej 	int kq;
281dbceac44Sthorpej 
282dbceac44Sthorpej 	ATF_REQUIRE((kq = kqueue()) >= 0);
283dbceac44Sthorpej 
284dbceac44Sthorpej 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ots) == 0);
285dbceac44Sthorpej 	ATF_REQUIRE(ots.tv_sec < INTPTR_MAX - TIME1_TOTAL_SEC);
286dbceac44Sthorpej 
287dbceac44Sthorpej 	seconds = ots.tv_sec + TIME1_TOTAL_SEC;
288dbceac44Sthorpej 
289dbceac44Sthorpej 	EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD,
290dbceac44Sthorpej 	    NOTE_ABSTIME | NOTE_SECONDS, seconds, NULL);
291dbceac44Sthorpej 	ATF_REQUIRE(kevent(kq, event, 1, event, 1, NULL) == 1);
292dbceac44Sthorpej 
293dbceac44Sthorpej 	ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0);
294dbceac44Sthorpej 	timespecsub(&ts, &ots, &ts);
295dbceac44Sthorpej 
296dbceac44Sthorpej 	/*
297dbceac44Sthorpej 	 * We're not going for precision here; just verify that it was
298dbceac44Sthorpej 	 * delivered anywhere between 4.5-6.whatever seconds later.
299dbceac44Sthorpej 	 */
300*ae0245f0Shannken 	ATF_REQUIRE(check_timespec(&ts, 4) || check_timespec(&ts, 5));
301dbceac44Sthorpej 
302dbceac44Sthorpej 	ts.tv_sec = 0;
303dbceac44Sthorpej 	ts.tv_nsec = 0;
304dbceac44Sthorpej 	ATF_REQUIRE(kevent(kq, NULL, 0, event, 1, &ts) == 1);
305dbceac44Sthorpej }
306dbceac44Sthorpej 
307dbceac44Sthorpej #define	PREC_TIMEOUT_SEC	2
308dbceac44Sthorpej 
309dbceac44Sthorpej static void
do_test_timer_units(const char * which,uint32_t fflag,int64_t data)310dbceac44Sthorpej do_test_timer_units(const char *which, uint32_t fflag, int64_t data)
311dbceac44Sthorpej {
312dbceac44Sthorpej 	struct kevent event[1];
313dbceac44Sthorpej 	struct timespec ts, ots;
314dbceac44Sthorpej 	int kq;
315dbceac44Sthorpej 
316dbceac44Sthorpej 	ATF_REQUIRE((kq = kqueue()) >= 0);
317dbceac44Sthorpej 
318dbceac44Sthorpej 	EV_SET(&event[0], 1, EVFILT_TIMER, EV_ADD | EV_ONESHOT,
319dbceac44Sthorpej 	    fflag, data, NULL);
320dbceac44Sthorpej 
321dbceac44Sthorpej 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ots) == 0);
322dbceac44Sthorpej 	ATF_REQUIRE(kevent(kq, event, 1, event, 1, NULL) == 1);
323dbceac44Sthorpej 	ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
324dbceac44Sthorpej 
325dbceac44Sthorpej 	timespecsub(&ts, &ots, &ts);
326*ae0245f0Shannken 	ATF_REQUIRE_MSG(check_timespec(&ts, PREC_TIMEOUT_SEC),
327*ae0245f0Shannken 	    "units '%s' failed", which);
328dbceac44Sthorpej 
329dbceac44Sthorpej 	(void)close(kq);
330dbceac44Sthorpej }
331dbceac44Sthorpej 
332dbceac44Sthorpej #define	test_timer_units(fflag, data)				\
333dbceac44Sthorpej 	do_test_timer_units(#fflag, fflag, data)
334dbceac44Sthorpej 
335dbceac44Sthorpej ATF_TC(timer_units);
ATF_TC_HEAD(timer_units,tc)336dbceac44Sthorpej ATF_TC_HEAD(timer_units, tc)
337dbceac44Sthorpej {
338dbceac44Sthorpej 	atf_tc_set_md_var(tc, "descr",
339dbceac44Sthorpej 	    "tests timers with NOTE_* units modifiers");
340dbceac44Sthorpej }
341dbceac44Sthorpej 
ATF_TC_BODY(timer_units,tc)342dbceac44Sthorpej ATF_TC_BODY(timer_units, tc)
343dbceac44Sthorpej {
344dbceac44Sthorpej 	test_timer_units(NOTE_SECONDS,  PREC_TIMEOUT_SEC);
345dbceac44Sthorpej 	test_timer_units(NOTE_MSECONDS, PREC_TIMEOUT_SEC * 1000);
346dbceac44Sthorpej 	test_timer_units(NOTE_USECONDS, PREC_TIMEOUT_SEC * 1000000);
347dbceac44Sthorpej 	test_timer_units(NOTE_NSECONDS, PREC_TIMEOUT_SEC * 1000000000);
348dbceac44Sthorpej }
349dbceac44Sthorpej 
ATF_TP_ADD_TCS(tp)350dbceac44Sthorpej ATF_TP_ADD_TCS(tp)
351dbceac44Sthorpej {
352dbceac44Sthorpej 	ATF_TP_ADD_TC(tp, basic_timer);
353dbceac44Sthorpej 	ATF_TP_ADD_TC(tp, count_expirations);
354dbceac44Sthorpej 	ATF_TP_ADD_TC(tp, abstime);
355dbceac44Sthorpej 	ATF_TP_ADD_TC(tp, timer_units);
356317dcfdbSthorpej 	ATF_TP_ADD_TC(tp, modify);
357dbceac44Sthorpej 
358dbceac44Sthorpej 	return atf_no_error();
359dbceac44Sthorpej }
360