Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / native_client / tests / syscalls / timefuncs_test.cc
1 // Copyright (c) 2012 The Native Client Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /*
6  * These are the syscalls being tested:
7  *   #define NACL_sys_gettimeofday           40
8  *   #define NACL_sys_clock                  41
9  *   #define NACL_sys_nanosleep              42
10 */
11
12
13 #include <errno.h>
14 #include <inttypes.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <sys/time.h>   // For gettimeofday.
18 #include <sys/times.h>  // For clock which uses times
19 #include <time.h>       // For nanosleep.
20 #include <unistd.h>
21
22 #include "native_client/src/trusted/service_runtime/include/machine/_types.h"
23 #include "native_client/src/trusted/service_runtime/include/sys/nacl_syscalls.h"
24
25 // #include "native_client/tests/syscalls/test.h"
26 #ifdef USE_RAW_SYSCALLS
27 #include "native_client/src/untrusted/nacl/syscall_bindings_trampoline.h"
28 #endif
29 #include "native_client/tests/syscalls/test.h"
30
31 /*
32  * These four definitions are copied from nanosleep_test.c
33  */
34 #define NANOS_PER_MICRO   (1000)
35 #define MICROS_PER_MILLI  (1000)
36 #define NANOS_PER_MILLI   (NANOS_PER_MICRO * MICROS_PER_MILLI)
37 #define MICROS_PER_UNIT   (1000 * 1000)
38
39
40 #ifdef USE_RAW_SYSCALLS
41 #define CLOCK NACL_SYSCALL(clock)
42 #define NANOSLEEP(REQ, REM)  NACL_SYSCALL(nanosleep)(REQ, REM)
43 #define GETTIMEOFDAY(TV, TZ) ((void) (TZ), NACL_SYSCALL(gettimeofday)(TV))
44 #else
45 #define CLOCK clock
46 #define NANOSLEEP(REQ, REM)  nanosleep(REQ, REM)
47 #define GETTIMEOFDAY(TV, TZ) gettimeofday(TV, TZ)
48 #endif
49
50 #define MAX_COUNTER 100000
51
52 int TestClockFunction() {
53   START_TEST("test clock function");
54
55   clock_t clock_time = 0;
56   int counter = 0;
57
58   // clock returns how much cpu time has been used so far. If the test is fast
59   // and/or granularity not very fine, then clock() can return 0 sometimes.
60   // It should (eventually) return a non-zero value.
61   // This loop will keep calling clock() until it returns non-zero or until the
62   // counter is larger than |MAX_COUNTER| (so that we don't hang if clock()
63   //  is broken).
64   while (counter < MAX_COUNTER && clock_time == 0) {
65     clock_time = CLOCK();
66     ++counter;
67   }
68   printf("Called clock.  clock_time=%ld, CLOCKS_PER_SEC=%d\n", clock_time,
69          (int) CLOCKS_PER_SEC);
70   EXPECT(clock_time > 0);
71
72   END_TEST();
73 }
74
75 int TestTimeFuncs() {
76   START_TEST("test gettimeofday,nanosleep function");
77   struct timeval tv1;   // Used by gettimeofday
78
79   /* Passing NULL as the first argument causes a warning with glibc. */
80 #ifndef __GLIBC__
81   EXPECT(0 != GETTIMEOFDAY(NULL, NULL));
82 #endif
83
84   /*
85    * gettimeofday takes two args: timeval and timezone pointers.
86    * The use of the timezone structure is obsolete; the tz argument should
87    * normally be specified as  NULL.
88    */
89   EXPECT(0 == GETTIMEOFDAY(&tv1, NULL));
90
91   struct timespec ts;  // Used by nanosleep.
92
93   ts.tv_sec = 1;
94   ts.tv_nsec = 5000000;
95   EXPECT(0 == NANOSLEEP(&ts, NULL));   // Sleep 1 second
96
97   struct timeval tv2;
98   EXPECT(0 == GETTIMEOFDAY(&tv2, NULL));   // Get time of day again
99
100   /*
101    * Because of our nanosleep call, tv2 should have a later time than tv1
102    */
103   EXPECT(tv2.tv_sec > tv1.tv_sec);
104
105   struct timeval tv3;
106   struct timezone tz;
107   tz.tz_minuteswest = 0;
108   tz.tz_dsttime = 0;
109
110   /*
111    * Test gettimeofday using obselete timezone struct pointer
112    */
113   EXPECT(0 == GETTIMEOFDAY(&tv3, &tz));  // Get time of day again
114
115   /*
116    * The time of day (tv3) should not be earlier than time of day (tv2)
117    */
118   EXPECT(tv3.tv_sec >= tv2.tv_sec);
119
120   /*
121    * Test nanosleep error conditions
122    */
123   EXPECT(0 != NANOSLEEP(NULL, NULL));
124   END_TEST();
125 }
126
127 /*
128  * Returns failure count.  t_suspend should not be shorter than 1us,
129  * since elapsed time measurement cannot possibly be any finer in
130  * granularity.  In practice, 1ms is probably the best we can hope for
131  * in timer resolution, so even if nanosleep suspends for 1us, the
132  * gettimeofday resolution may cause a false failure report.
133  */
134 int TestNanoSleep(struct timespec *t_suspend) {
135   START_TEST("Test nanosleep");
136   struct timespec t_remain;
137   struct timeval  t_start;
138   int             rv;
139   struct timeval  t_end;
140   struct timeval  t_elapsed;
141
142   printf("%40s: %"PRId64".%09ld seconds\n",
143          "Requesting nanosleep duration",
144          (int64_t) t_suspend->tv_sec,
145          t_suspend->tv_nsec);
146   t_remain = *t_suspend;
147   /*
148    * BUG: ntp or other time adjustments can mess up timing.
149    * BUG: time-of-day clock resolution may be not be fine enough to
150    * measure nanosleep duration.
151    */
152   EXPECT(-1 != GETTIMEOFDAY(&t_start, NULL));
153
154   while (-1 == (rv = NANOSLEEP(&t_remain, &t_remain)) &&
155          EINTR == errno) {
156   }
157   EXPECT(-1 != rv);
158
159   EXPECT(-1 != GETTIMEOFDAY(&t_end, NULL));
160
161   t_elapsed.tv_sec = t_end.tv_sec - t_start.tv_sec;
162   t_elapsed.tv_usec = t_end.tv_usec - t_start.tv_usec;
163   if (t_elapsed.tv_usec < 0) {
164     t_elapsed.tv_usec += MICROS_PER_UNIT;
165     t_elapsed.tv_sec -= 1;
166   }
167   if (t_elapsed.tv_usec >= MICROS_PER_UNIT) {
168     printf("Microsecond field too large: %ld\n", t_elapsed.tv_usec);
169   }
170
171   printf("%40s: %"PRId64".%06ld seconds\n",
172          "Actual nanosleep duration",
173          (int64_t) t_elapsed.tv_sec,
174          t_elapsed.tv_usec);
175
176   /*
177    * This is the original check and error message (from nanosleep_test.c),
178    * which provides feedback and is more readable.
179    */
180   if (t_elapsed.tv_sec < t_suspend->tv_sec ||
181       (t_elapsed.tv_sec == t_suspend->tv_sec &&
182        (NANOS_PER_MICRO * t_elapsed.tv_usec < t_suspend->tv_nsec))) {
183     printf("Error: Elapsed time too short!"
184            " t_elapsed.tv_sec=%"PRId64" "
185            " t_suspend->tv_sec=%"PRId64" "
186            " t_elapsed.tv_usec=%"PRId64" "
187            " t_suspend->tv_nsec=%"PRId64" \n",
188            (int64_t) t_elapsed.tv_sec, (int64_t) t_suspend->tv_sec,
189            (int64_t) t_elapsed.tv_usec, (int64_t) t_suspend->tv_nsec);
190   }
191
192   /*
193    * This check works with BEGIN_TEST/END_TEST and restates the check above
194    */
195   EXPECT(!(t_elapsed.tv_sec < t_suspend->tv_sec ||
196           (t_elapsed.tv_sec == t_suspend->tv_sec &&
197           (NANOS_PER_MICRO * t_elapsed.tv_usec < t_suspend->tv_nsec))));
198   END_TEST();
199 }
200
201 /*
202  * function TestSuite()
203  *
204  *   Run through a complete sequence of file tests.
205  *
206  * Returns the number of failed tests.
207  */
208 int TestSuite() {
209   int fail_count = 0;
210
211   fail_count += TestTimeFuncs();
212
213   /*
214    * Copied from tests/nanosleep.c
215    */
216   static struct timespec  t_suspend[] = {
217     { 0,   1 * NANOS_PER_MILLI, },
218     { 0,   2 * NANOS_PER_MILLI, },
219     { 0,   5 * NANOS_PER_MILLI, },
220     { 0,  10 * NANOS_PER_MILLI, },
221     { 0,  25 * NANOS_PER_MILLI, },
222     { 0,  50 * NANOS_PER_MILLI, },
223     { 0, 100 * NANOS_PER_MILLI, },
224     { 0, 250 * NANOS_PER_MILLI, },
225     { 0, 500 * NANOS_PER_MILLI, },
226     { 1,   0 * NANOS_PER_MILLI, },
227     { 1, 500 * NANOS_PER_MILLI, },
228   };
229
230   for (unsigned int ix = 0; ix < sizeof t_suspend/sizeof t_suspend[0]; ++ix) {
231     fail_count += TestNanoSleep(&t_suspend[ix]);
232   }
233
234   // run clock() tests last, so that the test has been running as long as
235   // possible -- to get a non-zero return for clock()
236   fail_count += TestClockFunction();
237   return fail_count;
238 }
239
240 /*
241  * main entry point.
242  *
243  * run all tests and call system exit with appropriate value
244  *   0 - success, all tests passed.
245  *  -1 - one or more tests failed.
246  */
247
248 int main(const int argc, const char *argv[]) {
249   int fail_count = TestSuite();
250
251   if (fail_count == 0)
252     printf("All tests PASSED\n");
253   else
254     printf("There were %d failures\n", fail_count);
255
256   exit(fail_count);
257 }