1 /* $OpenBSD: t_getrusage.c,v 1.1.1.1 2019/11/19 19:57:03 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 212 for (i = 0; i < maxiter; i++) { 213 214 (void)memset(&ru1, 0, sizeof(struct rusage)); 215 (void)memset(&ru2, 0, sizeof(struct rusage)); 216 217 work(); 218 219 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru1) == 0); 220 221 work(); 222 223 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru2) == 0); 224 225 if (timercmp(&ru2.ru_utime, &ru1.ru_utime, <) != 0) 226 atf_tc_fail("user time went backwards"); 227 } 228 } 229 230 ATF_TC(getrusage_utime_zero); 231 ATF_TC_HEAD(getrusage_utime_zero, tc) 232 { 233 atf_tc_set_md_var(tc, "descr", "Test zero utime from getrusage(2)"); 234 } 235 236 ATF_TC_BODY(getrusage_utime_zero, tc) 237 { 238 struct rusage ru; 239 size_t i; 240 241 /* 242 * Test that getrusage(2) does not return 243 * zero user time for the calling process. 244 */ 245 246 for (i = 0; i < maxiter; i++) { 247 work(); 248 } 249 250 (void)memset(&ru, 0, sizeof(struct rusage)); 251 252 ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0); 253 254 if (ru.ru_utime.tv_sec == 0 && ru.ru_utime.tv_usec == 0) 255 atf_tc_fail("zero user time from getrusage(2)"); 256 } 257 258 ATF_TP_ADD_TCS(tp) 259 { 260 261 ATF_TP_ADD_TC(tp, getrusage_err); 262 ATF_TP_ADD_TC(tp, getrusage_sig); 263 ATF_TP_ADD_TC(tp, getrusage_maxrss); 264 ATF_TP_ADD_TC(tp, getrusage_msgsnd); 265 ATF_TP_ADD_TC(tp, getrusage_utime_back); 266 ATF_TP_ADD_TC(tp, getrusage_utime_zero); 267 268 return atf_no_error(); 269 } 270