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
ts2double(const struct timespec * val)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
tv2double(const struct timeval * val)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
double2ts(double amt)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
double2tv(double amt)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.
tsDelta(const struct timespec * first,const struct timespec * second)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.
tvDelta(const struct timeval * first,const struct timeval * second)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 
testPrint(FILE * stream,const char * fmt,...)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
testSetLogCatTag(const char * tag)160 void testSetLogCatTag(const char *tag)
161 {
162     logCatTag = tag;
163 }
164 
165 // Obtain pointer to current log to logcat error interface tag
testGetLogCatTag(void)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  */
testRand(void)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  */
testRandMod(uint32_t mod)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  */
testRandBool(void)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  */
testRandFract(void)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.
testDelay(float amt)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, &current);
272 
273         // How much time is left
274         delta = tsDelta(&start, &current);
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().
testDelaySpin(float amt)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, &current);
297 
298         // How much time is left
299         delta = tsDelta(&start, &current);
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
testXDump(const void * buf,size_t size)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
testXDumpSetIndent(uint8_t indent)355 testXDumpSetIndent(uint8_t indent)
356 {
357     xDumpIndent = indent;
358 }
359 
360 // Obtain the current hex dump indent amount
361 uint8_t
testXDumpGetIndent(void)362 testXDumpGetIndent(void)
363 {
364     return xDumpIndent;
365 }
366 
367 // Set the hex dump address offset amount
368 void
testXDumpSetOffset(uint64_t offset)369 testXDumpSetOffset(uint64_t offset)
370 {
371     xDumpOffset = offset;
372 }
373 
374 // Get the current hex dump address offset amount
375 uint64_t
testXDumpGetOffset(void)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  */
testExecCmd(const char * cmd)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