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