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