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