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