testUtil.c revision 87dd9e92610d5e7552f5cdb6ab2578035e2210f5
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 <math.h>
22#include <stdarg.h>
23#include <stdint.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <time.h>
27#include <sys/time.h>
28#include <cutils/log.h>
29
30#define ALEN(a) (sizeof(a) / sizeof(a [0]))  // Array length
31typedef unsigned int bool_t;
32#define true (0 == 0)
33#define false (!true)
34
35#define MAXSTR 200
36static const char *logCatTag;
37
38// struct timeval to double
39double
40tv2double(const struct timeval *val)
41{
42    const unsigned int uSecsPerSec = 1000000;
43    double rv;
44
45    rv = val->tv_sec;
46    rv += (double) val->tv_usec / uSecsPerSec;
47
48    return rv;
49}
50
51// double to struct timespec
52struct timespec
53double2ts(double amt)
54{
55    const unsigned int nSecsPerSec = 1000000000;
56    struct timespec rv;
57
58    rv.tv_sec = floor(amt);
59    rv.tv_nsec = (amt - rv.tv_sec) * nSecsPerSec;
60    // TODO: Handle cases where amt is negative
61    while ((unsigned) rv.tv_nsec >= nSecsPerSec) {
62        rv.tv_nsec -= nSecsPerSec;
63        rv.tv_sec++;
64    }
65
66    return rv;
67}
68
69// Delta (difference) between two struct timeval.
70// It is expected that the time given by the structure pointed to by
71// second, is later than the time pointed to by first.
72struct timeval
73tvDelta(const struct timeval *first,
74    const struct timeval *second)
75{
76    const unsigned int uSecsPerSec = 1000000;
77    struct timeval rv;
78
79    assert(first != NULL);
80    assert(second != NULL);
81    assert(first->tv_usec >= 0 && first->tv_usec < uSecsPerSec);
82    assert(second->tv_usec >= 0 && second->tv_usec < uSecsPerSec);
83    rv.tv_sec = second->tv_sec - first->tv_sec;
84    if (second->tv_usec >= first->tv_usec) {
85        rv.tv_usec = second->tv_usec - first->tv_usec;
86    } else {
87        rv.tv_usec = (second->tv_usec + uSecsPerSec) - first->tv_usec;
88        rv.tv_sec--;
89    }
90
91    return rv;
92}
93
94void
95testPrint(FILE *stream, const char *fmt, ...)
96{
97    char line[MAXSTR];
98    va_list args;
99
100    va_start(args, fmt);
101    vsnprintf(line, sizeof(line), fmt, args);
102    if (stream == stderr) {
103        LOG(LOG_ERROR, logCatTag, "%s", line);
104    } else {
105        LOG(LOG_INFO, logCatTag, "%s", line);
106    }
107    vfprintf(stream, fmt, args);
108    fputc('\n', stream);
109}
110
111// Set tag used while logging to the logcat error interface
112void
113testSetLogCatTag(const char *tag)
114{
115    logCatTag = tag;
116}
117
118// Obtain pointer to current log to logcat error interface tag
119const char *
120testGetLogCatTag(void)
121{
122    return logCatTag;
123}
124
125/*
126 * Random Boolean
127 *
128 * Pseudo randomly returns 0 (false) or 1 (true).
129 *
130 * Precondition: srand48() called to set the seed of
131 *   the pseudo random number generator.
132 */
133int
134testRandBool(void)
135{
136    /* Use the most significant bit from lrand48(), because the
137     * less significant bits are less random across different seeds
138     * (e.g. srand48(x) and srand48(x + n * 4) cause lrand48() to
139     * return the same sequence of least significant bits.)
140     */
141    return (lrand48() & (1U << 30)) ? 0 : 1;
142}
143
144// Delays for the number of seconds specified by amt or a greater amount.
145// The amt variable is of type float and thus non-integer amounts
146// of time can be specified.  This function automatically handles cases
147// where nanosleep(2) returns early due to reception of a signal.
148void
149delay(float amt)
150{
151    struct timeval    start, current, delta;
152    struct timespec   remaining;
153
154    // Get the time at which we started
155    gettimeofday(&start, NULL);
156
157    do {
158        // Get current time
159        gettimeofday(&current, NULL);
160
161        // How much time is left
162        delta = tvDelta(&start, &current);
163        if (tv2double(&delta) > amt) { break; }
164
165        // Request to sleep for the remaining time
166        remaining = double2ts(amt - tv2double(&delta));
167        (void) nanosleep(&remaining, NULL);
168    } while (true);
169}
170