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