t_getrusage.c revision 276478
1/* $NetBSD: t_getrusage.c,v 1.3 2014/09/03 19:24:12 matt 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_getrusage.c,v 1.3 2014/09/03 19:24:12 matt Exp $");
33
34#include <sys/resource.h>
35#include <sys/time.h>
36
37#include <atf-c.h>
38#include <errno.h>
39#include <limits.h>
40#include <signal.h>
41#include <stdint.h>
42#include <string.h>
43
44static void		work(void);
45static void		sighandler(int);
46
47static const size_t	maxiter = 2000;
48
49static void
50#ifdef __FreeBSD__
51sighandler(int signo __unused)
52#else
53sighandler(int signo)
54#endif
55{
56	/* Nothing. */
57}
58
59static void
60work(void)
61{
62	size_t n = UINT16_MAX * 10;
63
64	while (n > 0) {
65#ifdef __or1k__
66		 asm volatile("l.nop");	/* Do something. */
67#else
68		 asm volatile("nop");	/* Do something. */
69#endif
70		 n--;
71	}
72}
73
74ATF_TC(getrusage_err);
75ATF_TC_HEAD(getrusage_err, tc)
76{
77	atf_tc_set_md_var(tc, "descr", "Test error conditions");
78}
79
80ATF_TC_BODY(getrusage_err, tc)
81{
82	struct rusage ru;
83
84	errno = 0;
85
86	ATF_REQUIRE(getrusage(INT_MAX, &ru) != 0);
87	ATF_REQUIRE(errno == EINVAL);
88
89	errno = 0;
90
91	ATF_REQUIRE(getrusage(RUSAGE_SELF, (void *)0) != 0);
92	ATF_REQUIRE(errno == EFAULT);
93}
94
95ATF_TC(getrusage_sig);
96ATF_TC_HEAD(getrusage_sig, tc)
97{
98	atf_tc_set_md_var(tc, "descr", "Test signal count with getrusage(2)");
99}
100
101ATF_TC_BODY(getrusage_sig, tc)
102{
103	struct rusage ru;
104	const long n = 5;
105	int i;
106
107	/*
108	 * Test that signals are recorded.
109	 */
110	ATF_REQUIRE(signal(SIGUSR1, sighandler) != SIG_ERR);
111
112	for (i = 0; i < n; i++)
113		ATF_REQUIRE(raise(SIGUSR1) == 0);
114
115	(void)memset(&ru, 0, sizeof(struct rusage));
116	ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0);
117
118	if (n != ru.ru_nsignals)
119		atf_tc_fail("getrusage(2) did not record signals");
120}
121
122ATF_TC(getrusage_utime_back);
123ATF_TC_HEAD(getrusage_utime_back, tc)
124{
125	atf_tc_set_md_var(tc, "descr", "Test bogus values from getrusage(2)");
126}
127
128ATF_TC_BODY(getrusage_utime_back, tc)
129{
130	struct rusage ru1, ru2;
131	size_t i;
132
133	/*
134	 * Test that two consecutive calls are sane.
135	 */
136#ifdef __NetBSD__
137	atf_tc_expect_fail("PR kern/30115");
138#endif
139
140	for (i = 0; i < maxiter; i++) {
141
142		(void)memset(&ru1, 0, sizeof(struct rusage));
143		(void)memset(&ru2, 0, sizeof(struct rusage));
144
145		work();
146
147		ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru1) == 0);
148
149		work();
150
151		ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru2) == 0);
152
153		if (timercmp(&ru2.ru_utime, &ru1.ru_utime, <) != 0)
154			atf_tc_fail("user time went backwards");
155	}
156
157#ifdef __NetBSD__
158	atf_tc_fail("anticipated error did not occur");
159#endif
160}
161
162ATF_TC(getrusage_utime_zero);
163ATF_TC_HEAD(getrusage_utime_zero, tc)
164{
165	atf_tc_set_md_var(tc, "descr", "Test zero utime from getrusage(2)");
166}
167
168ATF_TC_BODY(getrusage_utime_zero, tc)
169{
170	struct rusage ru;
171	size_t i;
172
173#ifdef __FreeBSD__
174	atf_tc_skip("this testcase passes/fails sporadically on FreeBSD/i386 "
175	    "@ r273153 (at least)");
176#endif
177
178	/*
179	 * Test that getrusage(2) does not return
180	 * zero user time for the calling process.
181	 *
182	 * See also (duplicate) PR port-amd64/41734.
183	 */
184	atf_tc_expect_fail("PR kern/30115");
185
186	for (i = 0; i < maxiter; i++) {
187
188		work();
189
190		(void)memset(&ru, 0, sizeof(struct rusage));
191
192		ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0);
193
194		if (ru.ru_utime.tv_sec == 0 && ru.ru_utime.tv_usec == 0)
195			atf_tc_fail("zero user time from getrusage(2)");
196	}
197
198	atf_tc_fail("anticipated error did not occur");
199}
200
201ATF_TP_ADD_TCS(tp)
202{
203
204	ATF_TP_ADD_TC(tp, getrusage_err);
205	ATF_TP_ADD_TC(tp, getrusage_sig);
206	ATF_TP_ADD_TC(tp, getrusage_utime_back);
207	ATF_TP_ADD_TC(tp, getrusage_utime_zero);
208
209	return atf_no_error();
210}
211