1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include <ztest.h>
7 #include <posix/time.h>
8 #include <posix/sys/time.h>
9 #include <posix/unistd.h>
10
11 #define SLEEP_SECONDS 1
12 #define CLOCK_INVALID -1
13
test_posix_clock(void)14 void test_posix_clock(void)
15 {
16 int64_t nsecs_elapsed, secs_elapsed;
17 struct timespec ts, te;
18
19 printk("POSIX clock APIs\n");
20
21 /* TESTPOINT: Pass invalid clock type */
22 zassert_equal(clock_gettime(CLOCK_INVALID, &ts), -1,
23 NULL);
24 zassert_equal(errno, EINVAL, NULL);
25
26 zassert_ok(clock_gettime(CLOCK_MONOTONIC, &ts), NULL);
27 zassert_ok(k_sleep(K_SECONDS(SLEEP_SECONDS)), NULL);
28 zassert_ok(clock_gettime(CLOCK_MONOTONIC, &te), NULL);
29
30 if (te.tv_nsec >= ts.tv_nsec) {
31 secs_elapsed = te.tv_sec - ts.tv_sec;
32 nsecs_elapsed = te.tv_nsec - ts.tv_nsec;
33 } else {
34 nsecs_elapsed = NSEC_PER_SEC + te.tv_nsec - ts.tv_nsec;
35 secs_elapsed = (te.tv_sec - ts.tv_sec - 1);
36 }
37
38 /*TESTPOINT: Check if POSIX clock API test passes*/
39 zassert_equal(secs_elapsed, SLEEP_SECONDS,
40 "POSIX clock API test failed");
41
42 printk("POSIX clock APIs test done\n");
43 }
44
test_posix_realtime(void)45 void test_posix_realtime(void)
46 {
47 int ret;
48 struct timespec rts, mts;
49 struct timeval tv;
50
51 ret = clock_gettime(CLOCK_MONOTONIC, &mts);
52 zassert_equal(ret, 0, "Fail to get monotonic clock");
53
54 ret = clock_gettime(CLOCK_REALTIME, &rts);
55 zassert_equal(ret, 0, "Fail to get realtime clock");
56
57 /* Set a particular time. In this case, the output of:
58 * `date +%s -d 2018-01-01T15:45:01Z`
59 */
60 struct timespec nts;
61 nts.tv_sec = 1514821501;
62 nts.tv_nsec = NSEC_PER_SEC / 2U;
63
64 /* TESTPOINT: Pass invalid clock type */
65 zassert_equal(clock_settime(CLOCK_INVALID, &nts), -1,
66 NULL);
67 zassert_equal(errno, EINVAL, NULL);
68
69 ret = clock_settime(CLOCK_MONOTONIC, &nts);
70 zassert_not_equal(ret, 0, "Should not be able to set monotonic time");
71
72 ret = clock_settime(CLOCK_REALTIME, &nts);
73 zassert_equal(ret, 0, "Fail to set realtime clock");
74
75 /*
76 * Loop 20 times, sleeping a little bit for each, making sure
77 * that the arithmetic roughly makes sense. This tries to
78 * catch all of the boundary conditions of the clock to make
79 * sure there are no errors in the arithmetic.
80 */
81 int64_t last_delta = 0;
82 for (int i = 1; i <= 20; i++) {
83 usleep(USEC_PER_MSEC * 90U);
84 ret = clock_gettime(CLOCK_REALTIME, &rts);
85 zassert_equal(ret, 0, "Fail to read realitime clock");
86
87 int64_t delta =
88 ((int64_t)rts.tv_sec * NSEC_PER_SEC -
89 (int64_t)nts.tv_sec * NSEC_PER_SEC) +
90 ((int64_t)rts.tv_nsec - (int64_t)nts.tv_nsec);
91
92 /* Make the delta milliseconds. */
93 delta /= (NSEC_PER_SEC / 1000U);
94
95 zassert_true(delta > last_delta, "Clock moved backward");
96 int64_t error = delta - last_delta;
97
98 /* printk("Delta %d: %lld\n", i, delta); */
99
100 /* Allow for a little drift upward, but not
101 * downward
102 */
103 zassert_true(error >= 90, "Clock inaccurate %d", error);
104 zassert_true(error <= 110, "Clock inaccurate %d", error);
105
106 last_delta = delta;
107 }
108
109 /* Validate gettimeofday API */
110 ret = gettimeofday(&tv, NULL);
111 zassert_equal(ret, 0, NULL);
112
113 ret = clock_gettime(CLOCK_REALTIME, &rts);
114 zassert_equal(ret, 0, NULL);
115
116 /* TESTPOINT: Check if time obtained from
117 * gettimeofday is same or more than obtained
118 * from clock_gettime
119 */
120 zassert_true(rts.tv_sec >= tv.tv_sec, "gettimeofday didn't"
121 " provide correct result");
122 zassert_true(rts.tv_nsec >= tv.tv_usec * NSEC_PER_USEC,
123 "gettimeofday didn't provide correct result");
124 }
125