OSDN Git Service

system/extras: Replace cutils/log.h with android/log.h or log/log.h
[android-x86/system-extras.git] / tests / lib / testUtil / testUtil.c
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 <sys/time.h>
29 #include <sys/wait.h>
30 #include <time.h>
31
32 #include <android/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, &current);
274
275         // How much time is left
276         delta = tsDelta(&start, &current);
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, &current);
299
300         // How much time is left
301         delta = tsDelta(&start, &current);
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 }