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.
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
17 #include <sys/time.h> // For gettimeofday.
18 #include <sys/times.h> // For clock which uses times
19 #include <time.h> // For nanosleep.
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"
25 // #include "native_client/tests/syscalls/test.h"
26 #ifdef USE_RAW_SYSCALLS
27 #include "native_client/src/untrusted/nacl/syscall_bindings_trampoline.h"
29 #include "native_client/tests/syscalls/test.h"
32 * These four definitions are copied from nanosleep_test.c
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)
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))
46 #define NANOSLEEP(REQ, REM) nanosleep(REQ, REM)
47 #define GETTIMEOFDAY(TV, TZ) gettimeofday(TV, TZ)
50 #define MAX_COUNTER 100000
52 int TestClockFunction() {
53 START_TEST("test clock function");
55 clock_t clock_time = 0;
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()
64 while (counter < MAX_COUNTER && clock_time == 0) {
68 printf("Called clock. clock_time=%ld, CLOCKS_PER_SEC=%d\n", clock_time,
69 (int) CLOCKS_PER_SEC);
70 EXPECT(clock_time > 0);
76 START_TEST("test gettimeofday,nanosleep function");
77 struct timeval tv1; // Used by gettimeofday
79 /* Passing NULL as the first argument causes a warning with glibc. */
81 EXPECT(0 != GETTIMEOFDAY(NULL, NULL));
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.
89 EXPECT(0 == GETTIMEOFDAY(&tv1, NULL));
91 struct timespec ts; // Used by nanosleep.
95 EXPECT(0 == NANOSLEEP(&ts, NULL)); // Sleep 1 second
98 EXPECT(0 == GETTIMEOFDAY(&tv2, NULL)); // Get time of day again
101 * Because of our nanosleep call, tv2 should have a later time than tv1
103 EXPECT(tv2.tv_sec > tv1.tv_sec);
107 tz.tz_minuteswest = 0;
111 * Test gettimeofday using obselete timezone struct pointer
113 EXPECT(0 == GETTIMEOFDAY(&tv3, &tz)); // Get time of day again
116 * The time of day (tv3) should not be earlier than time of day (tv2)
118 EXPECT(tv3.tv_sec >= tv2.tv_sec);
121 * Test nanosleep error conditions
123 EXPECT(0 != NANOSLEEP(NULL, NULL));
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.
134 int TestNanoSleep(struct timespec *t_suspend) {
135 START_TEST("Test nanosleep");
136 struct timespec t_remain;
137 struct timeval t_start;
139 struct timeval t_end;
140 struct timeval t_elapsed;
142 printf("%40s: %"PRId64".%09ld seconds\n",
143 "Requesting nanosleep duration",
144 (int64_t) t_suspend->tv_sec,
146 t_remain = *t_suspend;
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.
152 EXPECT(-1 != GETTIMEOFDAY(&t_start, NULL));
154 while (-1 == (rv = NANOSLEEP(&t_remain, &t_remain)) &&
159 EXPECT(-1 != GETTIMEOFDAY(&t_end, NULL));
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;
167 if (t_elapsed.tv_usec >= MICROS_PER_UNIT) {
168 printf("Microsecond field too large: %ld\n", t_elapsed.tv_usec);
171 printf("%40s: %"PRId64".%06ld seconds\n",
172 "Actual nanosleep duration",
173 (int64_t) t_elapsed.tv_sec,
177 * This is the original check and error message (from nanosleep_test.c),
178 * which provides feedback and is more readable.
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);
193 * This check works with BEGIN_TEST/END_TEST and restates the check above
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))));
202 * function TestSuite()
204 * Run through a complete sequence of file tests.
206 * Returns the number of failed tests.
211 fail_count += TestTimeFuncs();
214 * Copied from tests/nanosleep.c
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, },
230 for (unsigned int ix = 0; ix < sizeof t_suspend/sizeof t_suspend[0]; ++ix) {
231 fail_count += TestNanoSleep(&t_suspend[ix]);
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();
243 * run all tests and call system exit with appropriate value
244 * 0 - success, all tests passed.
245 * -1 - one or more tests failed.
248 int main(const int argc, const char *argv[]) {
249 int fail_count = TestSuite();
252 printf("All tests PASSED\n");
254 printf("There were %d failures\n", fail_count);