t_getitimer.c revision 273938
1/* $NetBSD: t_getitimer.c,v 1.2 2012/03/22 18:20:46 christos Exp $ */
2
3/*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jukka Ruohonen.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31#include <sys/cdefs.h>
32__RCSID("$NetBSD: t_getitimer.c,v 1.2 2012/03/22 18:20:46 christos Exp $");
33
34#include <sys/time.h>
35
36#include <atf-c.h>
37#include <errno.h>
38#include <limits.h>
39#include <signal.h>
40#include <string.h>
41#include <unistd.h>
42
43static bool	fail;
44static void	sighandler(int);
45
46static void
47sighandler(int signo)
48{
49
50	if (signo == SIGALRM || signo == SIGVTALRM)
51		fail = false;
52}
53
54ATF_TC(getitimer_empty);
55ATF_TC_HEAD(getitimer_empty, tc)
56{
57	atf_tc_set_md_var(tc, "descr", "getitimer(2) before setitimer(2)");
58}
59
60ATF_TC_BODY(getitimer_empty, tc)
61{
62	struct itimerval it;
63
64	/*
65	 * Verify that the passed structure remains
66	 * empty after calling getitimer(2) but before
67	 * actually arming the timer with setitimer(2).
68	 */
69	(void)memset(&it, 0, sizeof(struct itimerval));
70
71	ATF_REQUIRE(getitimer(ITIMER_REAL, &it) == 0);
72
73	if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0)
74		goto fail;
75
76	ATF_REQUIRE(getitimer(ITIMER_VIRTUAL, &it) == 0);
77
78	if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0)
79		goto fail;
80
81	ATF_REQUIRE(getitimer(ITIMER_PROF, &it) == 0);
82
83	if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0)
84		goto fail;
85
86	return;
87
88fail:
89	atf_tc_fail("getitimer(2) modfied the timer before it was armed");
90}
91
92ATF_TC(getitimer_err);
93ATF_TC_HEAD(getitimer_err, tc)
94{
95	atf_tc_set_md_var(tc, "descr", "Test errors from getitimer(2)");
96}
97
98ATF_TC_BODY(getitimer_err, tc)
99{
100	struct itimerval it;
101
102	errno = 0;
103	ATF_REQUIRE_ERRNO(EINVAL, getitimer(-1, &it) == -1);
104
105	errno = 0;
106	ATF_REQUIRE_ERRNO(EINVAL, getitimer(INT_MAX, &it) == -1);
107
108	errno = 0;
109	ATF_REQUIRE_ERRNO(EFAULT, getitimer(ITIMER_REAL, (void *)-1) == -1);
110}
111
112ATF_TC(setitimer_basic);
113ATF_TC_HEAD(setitimer_basic, tc)
114{
115	atf_tc_set_md_var(tc, "descr", "A basic test of setitimer(2)");
116}
117
118ATF_TC_BODY(setitimer_basic, tc)
119{
120	struct itimerval it;
121
122	it.it_value.tv_sec = 0;
123	it.it_value.tv_usec = 100;
124
125	it.it_interval.tv_sec = 0;
126	it.it_interval.tv_usec = 0;
127
128	fail = true;
129
130	ATF_REQUIRE(signal(SIGALRM, sighandler) != SIG_ERR);
131	ATF_REQUIRE(setitimer(ITIMER_REAL, &it, NULL) == 0);
132
133	/*
134	 * Although the interaction between
135	 * setitimer(2) and sleep(3) can be
136	 * unspecified, it is assumed that one
137	 * second suspension will be enough for
138	 * the timer to fire.
139	 */
140	(void)sleep(1);
141
142	if (fail != false)
143		atf_tc_fail("timer did not fire");
144}
145
146ATF_TC(setitimer_err);
147ATF_TC_HEAD(setitimer_err, tc)
148{
149	atf_tc_set_md_var(tc, "descr", "Test errors from setitimer(2)"
150	    " (PR standards/44927)");
151}
152
153ATF_TC_BODY(setitimer_err, tc)
154{
155	struct itimerval it, ot;
156
157	errno = 0;
158	ATF_REQUIRE_ERRNO(EINVAL, setitimer(-1, &it, &ot) == -1);
159
160	errno = 0;
161	ATF_REQUIRE_ERRNO(EINVAL, setitimer(INT_MAX, &it, &ot) == -1);
162
163	errno = 0;
164	ATF_REQUIRE_ERRNO(EFAULT, setitimer(ITIMER_REAL,(void*)-1, &ot) == -1);
165}
166
167ATF_TC(setitimer_old);
168ATF_TC_HEAD(setitimer_old, tc)
169{
170	atf_tc_set_md_var(tc, "descr", "Test old values from setitimer(2)");
171}
172
173ATF_TC_BODY(setitimer_old, tc)
174{
175	struct itimerval it, ot;
176
177	/*
178	 * Make two calls; the second one
179	 * should store the old values.
180	 */
181	it.it_value.tv_sec = 4;
182	it.it_value.tv_usec = 3;
183
184	it.it_interval.tv_sec = 0;
185	it.it_interval.tv_usec = 0;
186
187	ATF_REQUIRE(setitimer(ITIMER_REAL, &it, &ot) == 0);
188
189	it.it_value.tv_sec = 2;
190	it.it_value.tv_usec = 1;
191
192	it.it_interval.tv_sec = 0;
193	it.it_interval.tv_usec = 0;
194
195	ATF_REQUIRE(setitimer(ITIMER_REAL, &it, &ot) == 0);
196
197#ifdef __FreeBSD__
198	if (ot.it_value.tv_sec == 4 && ot.it_value.tv_usec == 3)
199		atf_tc_fail("setitimer(2) did not return remaining time");
200#else
201	if (ot.it_value.tv_sec != 4 || ot.it_value.tv_usec != 3)
202		atf_tc_fail("setitimer(2) did not store old values");
203#endif
204}
205
206ATF_TP_ADD_TCS(tp)
207{
208
209	ATF_TP_ADD_TC(tp, getitimer_empty);
210	ATF_TP_ADD_TC(tp, getitimer_err);
211	ATF_TP_ADD_TC(tp, setitimer_basic);
212	ATF_TP_ADD_TC(tp, setitimer_err);
213	ATF_TP_ADD_TC(tp, setitimer_old);
214
215	return atf_no_error();
216}
217