1 /*
2  * Copyright (c) 2018 Friedt Professional Engineering Services, Inc
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <ztest.h>
8 #include <errno.h>
9 #include <posix/time.h>
10 #include <stdint.h>
11 #include <sys_clock.h>
12 
13 /** req and rem are both NULL */
test_nanosleep_NULL_NULL(void)14 void test_nanosleep_NULL_NULL(void)
15 {
16 	int r = nanosleep(NULL, NULL);
17 
18 	zassert_equal(r, -1, "actual: %d expected: %d", r, -1);
19 	zassert_equal(errno, EFAULT, "actual: %d expected: %d", errno, EFAULT);
20 }
21 
22 /**
23  * req is NULL, rem is non-NULL (all-zero)
24  *
25  * Expect rem to be the same when function returns
26  */
test_nanosleep_NULL_notNULL(void)27 void test_nanosleep_NULL_notNULL(void)
28 {
29 	struct timespec rem = {};
30 
31 	errno = 0;
32 	int r = nanosleep(NULL, &rem);
33 
34 	zassert_equal(r, -1, "actual: %d expected: %d", r, -1);
35 	zassert_equal(errno, EFAULT, "actual: %d expected: %d",
36 	errno, EFAULT);
37 	zassert_equal(rem.tv_sec, 0, "actual: %d expected: %d",
38 	rem.tv_sec, 0);
39 	zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d",
40 	rem.tv_nsec, 0);
41 }
42 
43 /**
44  * req is non-NULL (all-zero), rem is NULL
45  *
46  * Expect req to be the same when function returns
47  */
test_nanosleep_notNULL_NULL(void)48 void test_nanosleep_notNULL_NULL(void)
49 {
50 	struct timespec req = {};
51 
52 	errno = 0;
53 	int r = nanosleep(&req, NULL);
54 
55 	zassert_equal(req.tv_sec, 0, "actual: %d expected: %d",
56 		req.tv_sec, 0);
57 	zassert_equal(req.tv_nsec, 0, "actual: %d expected: %d",
58 		req.tv_nsec, 0);
59 	zassert_equal(r, 0, "actual: %d expected: %d", r, -1);
60 	zassert_equal(errno, 0, "actual: %d expected: %d", errno, 0);
61 }
62 
63 /**
64  * req is non-NULL (all-zero), rem is non-NULL (all-zero)
65  *
66  * Expect req & rem to be the same when function returns
67  */
test_nanosleep_notNULL_notNULL(void)68 void test_nanosleep_notNULL_notNULL(void)
69 {
70 	struct timespec req = {};
71 	struct timespec rem = {};
72 
73 	errno = 0;
74 	int r = nanosleep(&req, &rem);
75 
76 	zassert_equal(r, 0, "actual: %d expected: %d", r, -1);
77 	zassert_equal(errno, 0, "actual: %d expected: %d", errno, 0);
78 	zassert_equal(req.tv_sec, 0, "actual: %d expected: %d",
79 		req.tv_sec, 0);
80 	zassert_equal(req.tv_nsec, 0, "actual: %d expected: %d",
81 		req.tv_nsec, 0);
82 	zassert_equal(rem.tv_sec, 0, "actual: %d expected: %d",
83 		rem.tv_sec, 0);
84 	zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d",
85 		rem.tv_nsec, 0);
86 }
87 
88 /**
89  * req and rem point to the same timespec
90  *
91  * Normative spec says they may be the same.
92  * Expect rem to be zero after returning.
93  */
test_nanosleep_req_is_rem(void)94 void test_nanosleep_req_is_rem(void)
95 {
96 	struct timespec ts = {0, 1};
97 
98 	errno = 0;
99 	int r = nanosleep(&ts, &ts);
100 
101 	zassert_equal(r, 0, "actual: %d expected: %d", r, -1);
102 	zassert_equal(errno, 0, "actual: %d expected: %d", errno, 0);
103 	zassert_equal(ts.tv_sec, 0, "actual: %d expected: %d",
104 		ts.tv_sec, 0);
105 	zassert_equal(ts.tv_nsec, 0, "actual: %d expected: %d",
106 		ts.tv_nsec, 0);
107 }
108 
109 /** req tv_sec is -1 */
test_nanosleep_n1_0(void)110 void test_nanosleep_n1_0(void)
111 {
112 	struct timespec req = {-1, 0};
113 
114 	errno = 0;
115 	int r = nanosleep(&req, NULL);
116 
117 	zassert_equal(r, -1, "actual: %d expected: %d", r, -1);
118 	zassert_equal(errno, EINVAL, "actual: %d expected: %d", errno, EFAULT);
119 }
120 
121 /** req tv_nsec is -1 */
test_nanosleep_0_n1(void)122 void test_nanosleep_0_n1(void)
123 {
124 	struct timespec req = {0, -1};
125 
126 	errno = 0;
127 	int r = nanosleep(&req, NULL);
128 
129 	zassert_equal(r, -1, "actual: %d expected: %d", r, -1);
130 	zassert_equal(errno, EINVAL, "actual: %d expected: %d", errno, EFAULT);
131 }
132 
133 /** req tv_sec and tv_nsec are both -1 */
test_nanosleep_n1_n1(void)134 void test_nanosleep_n1_n1(void)
135 {
136 	struct timespec req = {-1, -1};
137 
138 	errno = 0;
139 	int r = nanosleep(&req, NULL);
140 
141 	zassert_equal(r, -1, "actual: %d expected: %d", r, -1);
142 	zassert_equal(errno, EINVAL, "actual: %d expected: %d", errno, EFAULT);
143 }
144 
145 /** req tv_sec is 0 tv_nsec is 10^9 */
test_nanosleep_0_1000000000(void)146 void test_nanosleep_0_1000000000(void)
147 {
148 	struct timespec req = {0, 1000000000};
149 
150 	errno = 0;
151 	int r = nanosleep(&req, NULL);
152 
153 	zassert_equal(r, -1, "actual: %d expected: %d", r, -1);
154 	zassert_equal(errno, EINVAL, "actual: %d expected: %d", errno, EFAULT);
155 }
156 
common(const uint32_t s,uint32_t ns)157 static void common(const uint32_t s, uint32_t ns)
158 {
159 	uint32_t then;
160 	uint32_t now;
161 	int r;
162 	struct timespec req = {s, ns};
163 	struct timespec rem = {0, 0};
164 
165 	errno = 0;
166 	then = k_cycle_get_32();
167 	r = nanosleep(&req, &rem);
168 	now = k_cycle_get_32();
169 
170 	zassert_equal(r, 0, "actual: %d expected: %d", r, -1);
171 	zassert_equal(errno, 0, "actual: %d expected: %d", errno, 0);
172 	zassert_equal(req.tv_sec, s, "actual: %d expected: %d",
173 		req.tv_sec, s);
174 	zassert_equal(req.tv_nsec, ns, "actual: %d expected: %d",
175 		req.tv_nsec, ns);
176 	zassert_equal(rem.tv_sec, 0, "actual: %d expected: %d",
177 	rem.tv_sec, 0);
178 	zassert_equal(rem.tv_nsec, 0, "actual: %d expected: %d",
179 		rem.tv_nsec, 0);
180 
181 	uint64_t actual_ns = k_cyc_to_ns_ceil64((now - then));
182 	uint64_t exp_ns = (uint64_t)s * NSEC_PER_SEC + ns;
183 	/* round up to the nearest microsecond for k_busy_wait() */
184 	exp_ns = ceiling_fraction(exp_ns, NSEC_PER_USEC) * NSEC_PER_USEC;
185 
186 	/* lower bounds check */
187 	zassert_true(actual_ns >= exp_ns,
188 		"actual: %llu expected: %llu", actual_ns, exp_ns);
189 
190 	/* TODO: Upper bounds check when hr timers are available */
191 }
192 
193 /** sleep for 1ns */
test_nanosleep_0_1(void)194 void test_nanosleep_0_1(void)
195 {
196 	common(0, 1);
197 }
198 
199 /** sleep for 1us + 1ns */
test_nanosleep_0_1001(void)200 void test_nanosleep_0_1001(void)
201 {
202 	common(0, 1001);
203 }
204 
205 /** sleep for 500000000ns */
test_nanosleep_0_500000000(void)206 void test_nanosleep_0_500000000(void)
207 {
208 	common(0, 500000000);
209 }
210 
211 /** sleep for 1s */
test_nanosleep_1_0(void)212 void test_nanosleep_1_0(void)
213 {
214 	common(1, 0);
215 }
216 
217 /** sleep for 1s + 1ns */
test_nanosleep_1_1(void)218 void test_nanosleep_1_1(void)
219 {
220 	common(1, 1);
221 }
222 
223 /** sleep for 1s + 1us + 1ns */
test_nanosleep_1_1001(void)224 void test_nanosleep_1_1001(void)
225 {
226 	common(1, 1001);
227 }
228