1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 #include <testUtil.h> 19 20 #include <assert.h> 21 #include <errno.h> 22 #include <math.h> 23 #include <stdarg.h> 24 #include <stdint.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <time.h> 28 29 #include <sys/time.h> 30 #include <sys/wait.h> 31 32 #include <cutils/log.h> 33 34 #define ALEN(a) (sizeof(a) / sizeof(a [0])) // Array length 35 typedef unsigned int bool_t; 36 #define true (0 == 0) 37 #define false (!true) 38 39 #define MAXSTR 200 40 41 static const char *logCatTag; 42 static const unsigned int uSecsPerSec = 1000000; 43 static const unsigned int nSecsPerSec = 1000000000; 44 45 // struct timespec to double 46 double ts2double(const struct timespec *val) 47 { 48 double rv; 49 50 rv = val->tv_sec; 51 rv += (double) val->tv_nsec / nSecsPerSec; 52 53 return rv; 54 } 55 56 // struct timeval to double 57 double tv2double(const struct timeval *val) 58 { 59 double rv; 60 61 rv = val->tv_sec; 62 rv += (double) val->tv_usec / uSecsPerSec; 63 64 return rv; 65 } 66 67 // double to struct timespec 68 struct timespec double2ts(double amt) 69 { 70 struct timespec rv; 71 72 rv.tv_sec = floor(amt); 73 rv.tv_nsec = (amt - rv.tv_sec) * nSecsPerSec; 74 // TODO: Handle cases where amt is negative 75 while ((unsigned) rv.tv_nsec >= nSecsPerSec) { 76 rv.tv_nsec -= nSecsPerSec; 77 rv.tv_sec++; 78 } 79 80 return rv; 81 } 82 83 // double to struct timeval 84 struct timeval double2tv(double amt) 85 { 86 struct timeval rv; 87 88 rv.tv_sec = floor(amt); 89 rv.tv_usec = (amt - rv.tv_sec) * uSecsPerSec; 90 // TODO: Handle cases where amt is negative 91 while ((unsigned) rv.tv_usec >= uSecsPerSec) { 92 rv.tv_usec -= uSecsPerSec; 93 rv.tv_sec++; 94 } 95 96 return rv; 97 } 98 99 // Delta (difference) between two struct timespec. 100 // It is expected that the time given by the structure pointed to by 101 // second, is later than the time pointed to by first. 102 struct timespec tsDelta(const struct timespec *first, 103 const struct timespec *second) 104 { 105 struct timespec rv; 106 107 assert(first != NULL); 108 assert(second != NULL); 109 assert(first->tv_nsec >= 0 && first->tv_nsec < nSecsPerSec); 110 assert(second->tv_nsec >= 0 && second->tv_nsec < nSecsPerSec); 111 rv.tv_sec = second->tv_sec - first->tv_sec; 112 if (second->tv_nsec >= first->tv_nsec) { 113 rv.tv_nsec = second->tv_nsec - first->tv_nsec; 114 } else { 115 rv.tv_nsec = (second->tv_nsec + nSecsPerSec) - first->tv_nsec; 116 rv.tv_sec--; 117 } 118 119 return rv; 120 } 121 122 // Delta (difference) between two struct timeval. 123 // It is expected that the time given by the structure pointed to by 124 // second, is later than the time pointed to by first. 125 struct timeval tvDelta(const struct timeval *first, 126 const struct timeval *second) 127 { 128 struct timeval rv; 129 130 assert(first != NULL); 131 assert(second != NULL); 132 assert(first->tv_usec >= 0 && first->tv_usec < uSecsPerSec); 133 assert(second->tv_usec >= 0 && second->tv_usec < uSecsPerSec); 134 rv.tv_sec = second->tv_sec - first->tv_sec; 135 if (second->tv_usec >= first->tv_usec) { 136 rv.tv_usec = second->tv_usec - first->tv_usec; 137 } else { 138 rv.tv_usec = (second->tv_usec + uSecsPerSec) - first->tv_usec; 139 rv.tv_sec--; 140 } 141 142 return rv; 143 } 144 145 void testPrint(FILE *stream, const char *fmt, ...) 146 { 147 char line[MAXSTR]; 148 va_list args; 149 150 va_start(args, fmt); 151 vsnprintf(line, sizeof(line), fmt, args); 152 if (stream == stderr) { 153 ALOG(LOG_ERROR, logCatTag, "%s", line); 154 } else { 155 ALOG(LOG_INFO, logCatTag, "%s", line); 156 } 157 vfprintf(stream, fmt, args); 158 fputc('\n', stream); 159 } 160 161 // Set tag used while logging to the logcat error interface 162 void testSetLogCatTag(const char *tag) 163 { 164 logCatTag = tag; 165 } 166 167 // Obtain pointer to current log to logcat error interface tag 168 const char * testGetLogCatTag(void) 169 { 170 return logCatTag; 171 } 172 173 /* 174 * Random 175 * 176 * Returns a pseudo random number in the range [0:2^32-1]. 177 * 178 * Precondition: srand48() called to set the seed of 179 * the pseudo random number generator. 180 */ 181 uint32_t testRand(void) 182 { 183 uint32_t val; 184 185 // Use lrand48() to obtain 31 bits worth 186 // of randomness. 187 val = lrand48(); 188 189 // Make an additional lrand48() call and merge 190 // the randomness into the most significant bits. 191 val ^= lrand48() << 1; 192 193 return val; 194 } 195 196 /* 197 * Random Modulus 198 * 199 * Pseudo randomly returns unsigned integer in the range [0, mod). 200 * 201 * Precondition: srand48() called to set the seed of 202 * the pseudo random number generator. 203 */ 204 uint32_t testRandMod(uint32_t mod) 205 { 206 // Obtain the random value 207 // Use lrand48() when it would produce a sufficient 208 // number of random bits, otherwise use testRand(). 209 const uint32_t lrand48maxVal = ((uint32_t) 1 << 31) - 1; 210 uint32_t val = (mod <= lrand48maxVal) ? (uint32_t) lrand48() : testRand(); 211 212 /* 213 * The contents of individual bytes tend to be less than random 214 * across different seeds. For example, srand48(x) and 215 * srand48(x + n * 4) cause lrand48() to return the same sequence of 216 * least significant bits. For small mod values this can produce 217 * noticably non-random sequnces. For mod values of less than 2 218 * bytes, will use the randomness from all the bytes. 219 */ 220 if (mod <= 0x10000) { 221 val = (val & 0xffff) ^ (val >> 16); 222 223 // If mod less than a byte, can further combine down to 224 // a single byte. 225 if (mod <= 0x100) { 226 val = (val & 0xff) ^ (val >> 8); 227 } 228 } 229 230 return val % mod; 231 } 232 233 /* 234 * Random Boolean 235 * 236 * Pseudo randomly returns 0 (false) or 1 (true). 237 * 238 * Precondition: srand48() called to set the seed of 239 * the pseudo random number generator. 240 */ 241 int testRandBool(void) 242 { 243 return (testRandMod(2)); 244 } 245 246 /* 247 * Random Fraction 248 * 249 * Pseudo randomly return a value in the range [0.0, 1.0). 250 * 251 * Precondition: srand48() called to set the seed of 252 * the pseudo random number generator. 253 */ 254 double testRandFract(void) 255 { 256 return drand48(); 257 } 258 259 // Delays for the number of seconds specified by amt or a greater amount. 260 // The amt variable is of type float and thus non-integer amounts 261 // of time can be specified. This function automatically handles cases 262 // where nanosleep(2) returns early due to reception of a signal. 263 void testDelay(float amt) 264 { 265 struct timespec start, current, delta; 266 struct timespec remaining; 267 268 // Get the time at which we started 269 clock_gettime(CLOCK_MONOTONIC, &start); 270 271 do { 272 // Get current time 273 clock_gettime(CLOCK_MONOTONIC, ¤t); 274 275 // How much time is left 276 delta = tsDelta(&start, ¤t); 277 if (ts2double(&delta) > amt) { break; } 278 279 // Request to sleep for the remaining time 280 remaining = double2ts(amt - ts2double(&delta)); 281 (void) nanosleep(&remaining, NULL); 282 } while (true); 283 } 284 285 // Delay spins for the number of seconds specified by amt or a greater 286 // amount. The amt variable is of type float and thus non-integer amounts 287 // of time can be specified. Differs from testDelay() in that 288 // testDelaySpin() performs a spin loop, instead of using nanosleep(). 289 void testDelaySpin(float amt) 290 { 291 struct timespec start, current, delta; 292 293 // Get the time at which we started 294 clock_gettime(CLOCK_MONOTONIC, &start); 295 296 do { 297 // Get current time 298 clock_gettime(CLOCK_MONOTONIC, ¤t); 299 300 // How much time is left 301 delta = tsDelta(&start, ¤t); 302 if (ts2double(&delta) > amt) { break; } 303 } while (true); 304 } 305 306 /* 307 * Hex Dump 308 * 309 * Displays in hex the contents of the memory starting at the location 310 * pointed to by buf, for the number of bytes given by size. 311 * Each line of output is indented by a number of spaces that 312 * can be set by calling xDumpSetIndent(). It is also possible 313 * to offset the displayed address by an amount set by calling 314 * xDumpSetOffset. 315 */ 316 static uint8_t xDumpIndent; 317 static uint64_t xDumpOffset; 318 void 319 testXDump(const void *buf, size_t size) 320 { 321 const unsigned int bytesPerLine = 16; 322 int rv; 323 char line[MAXSTR]; 324 const unsigned char *ptr = buf, *start = buf; 325 size_t num = size; 326 char *linep = line; 327 328 while (num) { 329 if (((ptr - start) % bytesPerLine) == 0) { 330 if (linep != line) { 331 testPrintE("%s", line); 332 } 333 linep = line; 334 rv = snprintf(linep, ALEN(line) - (linep - line), 335 "%*s%06llx:", xDumpIndent, "", 336 (long long) (ptr - start) + xDumpOffset); 337 linep += rv; 338 } 339 340 // Check that there is at least room for 4 341 // more characters. The 4 characters being 342 // a space, 2 hex digits and the terminating 343 // '\0'. 344 assert((ALEN(line) - 4) >= (linep - line)); 345 rv = snprintf(linep, ALEN(line) - (linep - line), 346 " %02x", *ptr++); 347 linep += rv; 348 num--; 349 } 350 if (linep != line) { 351 testPrintE("%s", line); 352 } 353 } 354 355 // Set an indent of spaces for each line of hex dump output 356 void 357 testXDumpSetIndent(uint8_t indent) 358 { 359 xDumpIndent = indent; 360 } 361 362 // Obtain the current hex dump indent amount 363 uint8_t 364 testXDumpGetIndent(void) 365 { 366 return xDumpIndent; 367 } 368 369 // Set the hex dump address offset amount 370 void 371 testXDumpSetOffset(uint64_t offset) 372 { 373 xDumpOffset = offset; 374 } 375 376 // Get the current hex dump address offset amount 377 uint64_t 378 testXDumpGetOffset(void) 379 { 380 return xDumpOffset; 381 } 382 383 /* 384 * Execute Command 385 * 386 * Executes the command pointed to by cmd. Output from the 387 * executed command is captured and sent to LogCat Info. Once 388 * the command has finished execution, it's exit status is captured 389 * and checked for an exit status of zero. Any other exit status 390 * causes diagnostic information to be printed and an immediate 391 * testcase failure. 392 */ 393 void testExecCmd(const char *cmd) 394 { 395 FILE *fp; 396 int rv; 397 int status; 398 char str[MAXSTR]; 399 400 // Display command to be executed 401 testPrintI("cmd: %s", cmd); 402 403 // Execute the command 404 fflush(stdout); 405 if ((fp = popen(cmd, "r")) == NULL) { 406 testPrintE("execCmd popen failed, errno: %i", errno); 407 exit(100); 408 } 409 410 // Obtain and display each line of output from the executed command 411 while (fgets(str, sizeof(str), fp) != NULL) { 412 if ((strlen(str) > 1) && (str[strlen(str) - 1] == '\n')) { 413 str[strlen(str) - 1] = '\0'; 414 } 415 testPrintI(" out: %s", str); 416 } 417 418 // Obtain and check return status of executed command. 419 // Fail on non-zero exit status 420 status = pclose(fp); 421 if (!(WIFEXITED(status) && (WEXITSTATUS(status) == 0))) { 422 testPrintE("Unexpected command failure"); 423 testPrintE(" status: %#x", status); 424 if (WIFEXITED(status)) { 425 testPrintE("WEXITSTATUS: %i", WEXITSTATUS(status)); 426 } 427 if (WIFSIGNALED(status)) { 428 testPrintE("WTERMSIG: %i", WTERMSIG(status)); 429 } 430 exit(101); 431 } 432 } 433