1 /* $OpenBSD: t_getrusage.c,v 1.2 2020/11/09 23:18:51 bluhm Exp $ */ 2 /* $NetBSD: t_getrusage.c,v 1.8 2018/05/09 08:45:03 mrg Exp $ */ 3 4 /*- 5 * Copyright (c) 2011 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Jukka Ruohonen. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include "macros.h" 34 35 #include <sys/cdefs.h> 36 __RCSID("$NetBSD: t_getrusage.c,v 1.8 2018/05/09 08:45:03 mrg Exp $"); 37 38 #include <sys/resource.h> 39 #include <sys/time.h> 40 41 #include "atf-c.h" 42 #include <stdio.h> 43 #include <errno.h> 44 #include <limits.h> 45 #include <signal.h> 46 #include <stdint.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <fcntl.h> 50 #include <sys/socket.h> 51 #include <netinet/in.h> 52 53 static void work(void); 54 static void sighandler(int); 55 56 static const size_t maxiter = 2000; 57 58 static void 59 sighandler(int signo __unused) 60 { 61 /* Nothing. */ 62 } 63 64 static void 65 work(void) 66 { 67 size_t n = UINT16_MAX * 10; 68 69 while (n > 0) { 70 #ifdef __or1k__ 71 asm volatile("l.nop"); /* Do something. */ 72 #elif defined(__ia64__) 73 asm volatile("nop 0"); /* Do something. */ 74 #else 75 asm volatile("nop"); /* Do something. */ 76 #endif 77 n--; 78 } 79 } 80 81 ATF_TC(getrusage_err); 82 ATF_TC_HEAD(getrusage_err, tc) 83 { 84 atf_tc_set_md_var(tc, "descr", "Test error conditions"); 85 } 86 87 ATF_TC_BODY(getrusage_err, tc) 88 { 89 struct rusage ru; 90 91 errno = 0; 92 93 ATF_REQUIRE(getrusage(INT_MAX, &ru) != 0); 94 ATF_REQUIRE(errno == EINVAL); 95 96 errno = 0; 97 98 ATF_REQUIRE(getrusage(RUSAGE_SELF, (void *)0) != 0); 99 ATF_REQUIRE(errno == EFAULT); 100 } 101 102 ATF_TC(getrusage_sig); 103 ATF_TC_HEAD(getrusage_sig, tc) 104 { 105 atf_tc_set_md_var(tc, "descr", "Test signal count with getrusage(2)"); 106 } 107 108 ATF_TC_BODY(getrusage_sig, tc) 109 { 110 struct rusage ru; 111 const long n = 5; 112 int i; 113 114 /* 115 * Test that signals are recorded. 116 */ 117 ATF_REQUIRE(signal(SIGUSR1, sighandler) != SIG_ERR); 118 119 for (i = 0; i < n; i++) 120 ATF_REQUIRE(raise(SIGUSR1) == 0); 121 122 (void)memset(&ru, 0, sizeof(struct rusage)); 123 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0); 124 125 if (n != ru.ru_nsignals) 126 atf_tc_fail("getrusage(2) did not record signals"); 127 } 128 129 ATF_TC(getrusage_maxrss); 130 ATF_TC_HEAD(getrusage_maxrss, tc) 131 { 132 atf_tc_set_md_var(tc, "descr", "Test maxrss growing with getrusage(2)"); 133 } 134 135 ATF_TC_BODY(getrusage_maxrss, tc) 136 { 137 struct rusage ru; 138 long maxrss; 139 int i, fd; 140 141 #define DUMP_FILE "dump" 142 143 fd = open(DUMP_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0222); 144 ATF_REQUIRE(fd != -1); 145 146 (void)memset(&ru, 0, sizeof(struct rusage)); 147 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0); 148 maxrss = ru.ru_maxrss; 149 150 #define CHUNK (1024 * 1024) 151 for (i = 0; i < 40; i++) { 152 void *p = malloc(CHUNK); 153 memset(p, 0, CHUNK); 154 write(fd, p, CHUNK); 155 } 156 close(fd); 157 unlink(DUMP_FILE); 158 159 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0); 160 ATF_REQUIRE_MSG(maxrss < ru.ru_maxrss, 161 "maxrss: %ld, ru.ru_maxrss: %ld", maxrss, ru.ru_maxrss); 162 } 163 164 ATF_TC(getrusage_msgsnd); 165 ATF_TC_HEAD(getrusage_msgsnd, tc) 166 { 167 atf_tc_set_md_var(tc, "descr", "Test send growing with getrusage(2)"); 168 } 169 170 ATF_TC_BODY(getrusage_msgsnd, tc) 171 { 172 struct rusage ru; 173 long msgsnd; 174 int s, i; 175 struct sockaddr_in sin; 176 177 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0); 178 msgsnd = ru.ru_msgsnd; 179 180 s = socket(AF_INET, SOCK_DGRAM, 0); 181 ATF_REQUIRE(s >= 0); 182 memset(&sin, 0, sizeof(sin)); 183 sin.sin_family = AF_INET; 184 sin.sin_len = sizeof(sin); 185 sin.sin_addr.s_addr = ntohl(INADDR_LOOPBACK); 186 sin.sin_port = htons(3333); 187 188 for (i = 0; i < 10; i++) 189 ATF_REQUIRE(sendto(s, &sin, sizeof(sin), 0, (void *)&sin, 190 (socklen_t)sizeof(sin)) != -1); 191 192 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0); 193 ATF_REQUIRE(msgsnd + 10 == ru.ru_msgsnd); 194 close(s); 195 } 196 197 ATF_TC(getrusage_utime_back); 198 ATF_TC_HEAD(getrusage_utime_back, tc) 199 { 200 atf_tc_set_md_var(tc, "descr", "Test bogus values from getrusage(2)"); 201 } 202 203 ATF_TC_BODY(getrusage_utime_back, tc) 204 { 205 struct rusage ru1, ru2; 206 size_t i; 207 208 /* 209 * Test that two consecutive calls are sane. 210 */ 211 #ifndef __OpenBSD__ 212 atf_tc_expect_fail("PR kern/30115"); 213 #endif 214 215 for (i = 0; i < maxiter; i++) { 216 217 (void)memset(&ru1, 0, sizeof(struct rusage)); 218 (void)memset(&ru2, 0, sizeof(struct rusage)); 219 220 work(); 221 222 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru1) == 0); 223 224 work(); 225 226 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru2) == 0); 227 228 if (timercmp(&ru2.ru_utime, &ru1.ru_utime, <) != 0) 229 atf_tc_fail("user time went backwards"); 230 } 231 232 #ifndef __OpenBSD__ 233 atf_tc_fail("anticipated error did not occur"); 234 #endif 235 } 236 237 ATF_TC(getrusage_utime_zero); 238 ATF_TC_HEAD(getrusage_utime_zero, tc) 239 { 240 atf_tc_set_md_var(tc, "descr", "Test zero utime from getrusage(2)"); 241 } 242 243 ATF_TC_BODY(getrusage_utime_zero, tc) 244 { 245 struct rusage ru; 246 size_t i; 247 248 /* 249 * Test that getrusage(2) does not return 250 * zero user time for the calling process. 251 * 252 * See also (duplicate) PR port-amd64/41734. 253 */ 254 #ifndef __OpenBSD__ 255 atf_tc_expect_fail("PR kern/30115"); 256 #endif 257 258 for (i = 0; i < maxiter; i++) { 259 260 work(); 261 #ifdef __OpenBSD__ 262 } 263 #endif 264 265 (void)memset(&ru, 0, sizeof(struct rusage)); 266 267 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0); 268 269 if (ru.ru_utime.tv_sec == 0 && ru.ru_utime.tv_usec == 0) 270 atf_tc_fail("zero user time from getrusage(2)"); 271 #ifndef __OpenBSD__ 272 } 273 274 atf_tc_fail("anticipated error did not occur"); 275 #endif 276 } 277 278 ATF_TP_ADD_TCS(tp) 279 { 280 281 ATF_TP_ADD_TC(tp, getrusage_err); 282 ATF_TP_ADD_TC(tp, getrusage_sig); 283 ATF_TP_ADD_TC(tp, getrusage_maxrss); 284 ATF_TP_ADD_TC(tp, getrusage_msgsnd); 285 ATF_TP_ADD_TC(tp, getrusage_utime_back); 286 ATF_TP_ADD_TC(tp, getrusage_utime_zero); 287 288 return atf_no_error(); 289 } 290