1 | /* Test for support_timespec_check_in_range function. |
2 | Copyright (C) 2020-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2.1 of the License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, see |
17 | <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <support/timespec.h> |
20 | #include <support/check.h> |
21 | #include <limits.h> |
22 | #include <intprops.h> |
23 | |
24 | #define TIMESPEC_HZ 1000000000 |
25 | |
26 | struct timespec_ns_test_case |
27 | { |
28 | struct timespec time; |
29 | time_t time_ns; |
30 | }; |
31 | |
32 | struct timespec_norm_test_case |
33 | { |
34 | struct timespec time; |
35 | struct timespec norm; |
36 | }; |
37 | |
38 | struct timespec_test_case |
39 | { |
40 | struct timespec expected; |
41 | struct timespec observed; |
42 | double upper_bound; |
43 | double lower_bound; |
44 | int result; |
45 | }; |
46 | |
47 | #define TIME_T_MIN TYPE_MINIMUM (time_t) |
48 | #define TIME_T_MAX TYPE_MAXIMUM (time_t) |
49 | |
50 | /* Test cases for timespec_ns */ |
51 | struct timespec_ns_test_case ns_cases[] = { |
52 | {.time = {.tv_sec = 0, .tv_nsec = 0}, |
53 | .time_ns = 0, |
54 | }, |
55 | {.time = {.tv_sec = 0, .tv_nsec = 1}, |
56 | .time_ns = 1, |
57 | }, |
58 | {.time = {.tv_sec = 1, .tv_nsec = 0}, |
59 | .time_ns = TIMESPEC_HZ, |
60 | }, |
61 | {.time = {.tv_sec = 1, .tv_nsec = 1}, |
62 | .time_ns = TIMESPEC_HZ + 1, |
63 | }, |
64 | {.time = {.tv_sec = 0, .tv_nsec = -1}, |
65 | .time_ns = -1, |
66 | }, |
67 | {.time = {.tv_sec = -1, .tv_nsec = 0}, |
68 | .time_ns = -TIMESPEC_HZ, |
69 | }, |
70 | {.time = {.tv_sec = -1, .tv_nsec = -1}, |
71 | .time_ns = -TIMESPEC_HZ - 1, |
72 | }, |
73 | {.time = {.tv_sec = 1, .tv_nsec = -1}, |
74 | .time_ns = TIMESPEC_HZ - 1, |
75 | }, |
76 | {.time = {.tv_sec = -1, .tv_nsec = 1}, |
77 | .time_ns = -TIMESPEC_HZ + 1, |
78 | }, |
79 | /* Overflow bondary by 2 */ |
80 | {.time = {.tv_sec = TIME_T_MAX / TIMESPEC_HZ, |
81 | .tv_nsec = TIME_T_MAX % TIMESPEC_HZ - 1}, |
82 | .time_ns = TIME_T_MAX - 1, |
83 | }, |
84 | /* Overflow bondary */ |
85 | {.time = {.tv_sec = TIME_T_MAX / TIMESPEC_HZ, |
86 | .tv_nsec = TIME_T_MAX % TIMESPEC_HZ}, |
87 | .time_ns = TIME_T_MAX, |
88 | }, |
89 | /* Underflow bondary by 1 */ |
90 | {.time = {.tv_sec = TIME_T_MIN / TIMESPEC_HZ, |
91 | .tv_nsec = TIME_T_MIN % TIMESPEC_HZ + 1}, |
92 | .time_ns = TIME_T_MIN + 1, |
93 | }, |
94 | /* Underflow bondary */ |
95 | {.time = {.tv_sec = TIME_T_MIN / TIMESPEC_HZ, |
96 | .tv_nsec = TIME_T_MIN % TIMESPEC_HZ}, |
97 | .time_ns = TIME_T_MIN, |
98 | }, |
99 | /* Multiplication overflow */ |
100 | {.time = {.tv_sec = TIME_T_MAX / TIMESPEC_HZ + 1, .tv_nsec = 1}, |
101 | .time_ns = TIME_T_MAX, |
102 | }, |
103 | /* Multiplication underflow */ |
104 | {.time = {.tv_sec = TIME_T_MIN / TIMESPEC_HZ - 1, .tv_nsec = -1}, |
105 | .time_ns = TIME_T_MIN, |
106 | }, |
107 | /* Sum overflows */ |
108 | {.time = {.tv_sec = TIME_T_MAX / TIMESPEC_HZ, |
109 | .tv_nsec = TIME_T_MAX % TIMESPEC_HZ + 1}, |
110 | .time_ns = TIME_T_MAX, |
111 | }, |
112 | /* Sum underflow */ |
113 | {.time = {.tv_sec = TIME_T_MIN / TIMESPEC_HZ, |
114 | .tv_nsec = TIME_T_MIN % TIMESPEC_HZ - 1}, |
115 | .time_ns = TIME_T_MIN, |
116 | } |
117 | }; |
118 | |
119 | /* Test cases for timespec_norm */ |
120 | struct timespec_norm_test_case norm_cases[] = { |
121 | /* Positive cases */ |
122 | {.time = {.tv_sec = 0, .tv_nsec = 0}, |
123 | .norm = {.tv_sec = 0, .tv_nsec = 0} |
124 | }, |
125 | {.time = {.tv_sec = 1, .tv_nsec = 0}, |
126 | .norm = {.tv_sec = 1, .tv_nsec = 0} |
127 | }, |
128 | {.time = {.tv_sec = 0, .tv_nsec = 1}, |
129 | .norm = {.tv_sec = 0, .tv_nsec = 1} |
130 | }, |
131 | {.time = {.tv_sec = 0, .tv_nsec = TIMESPEC_HZ}, |
132 | .norm = {.tv_sec = 1, .tv_nsec = 0} |
133 | }, |
134 | {.time = {.tv_sec = 0, .tv_nsec = TIMESPEC_HZ + 1}, |
135 | .norm = {.tv_sec = 1, .tv_nsec = 1} |
136 | }, |
137 | {.time = {.tv_sec = 1, .tv_nsec = TIMESPEC_HZ}, |
138 | .norm = {.tv_sec = 2, .tv_nsec = 0} |
139 | }, |
140 | {.time = {.tv_sec = 1, .tv_nsec = TIMESPEC_HZ + 1}, |
141 | .norm = {.tv_sec = 2, .tv_nsec = 1} |
142 | }, |
143 | /* Negative cases */ |
144 | {.time = {.tv_sec = 0, .tv_nsec = -TIMESPEC_HZ}, |
145 | .norm = {.tv_sec = -1, .tv_nsec = 0} |
146 | }, |
147 | {.time = {.tv_sec = 0, .tv_nsec = -TIMESPEC_HZ - 1}, |
148 | .norm = {.tv_sec = -1, .tv_nsec = -1} |
149 | }, |
150 | {.time = {.tv_sec = -1, .tv_nsec = -TIMESPEC_HZ}, |
151 | .norm = {.tv_sec = -2, .tv_nsec = 0} |
152 | }, |
153 | {.time = {.tv_sec = -1, .tv_nsec = -TIMESPEC_HZ - 1}, |
154 | .norm = {.tv_sec = -2, .tv_nsec = -1} |
155 | }, |
156 | /* Overflow bondary by 2 */ |
157 | {.time = {.tv_sec = TIME_T_MAX - 2, .tv_nsec = TIMESPEC_HZ + 1}, |
158 | .norm = {.tv_sec = TIME_T_MAX - 1, 1}, |
159 | }, |
160 | /* Overflow bondary by 1 */ |
161 | {.time = {.tv_sec = TIME_T_MAX - 1, .tv_nsec = TIMESPEC_HZ + 1}, |
162 | .norm = {.tv_sec = TIME_T_MAX, .tv_nsec = 1}, |
163 | }, |
164 | /* Underflow bondary by 2 */ |
165 | {.time = {.tv_sec = TIME_T_MIN + 2, .tv_nsec = -TIMESPEC_HZ - 1}, |
166 | .norm = {.tv_sec = TIME_T_MIN + 1, -1}, |
167 | }, |
168 | /* Underflow bondary by 1 */ |
169 | {.time = {.tv_sec = TIME_T_MIN + 1, .tv_nsec = -TIMESPEC_HZ - 1}, |
170 | .norm = {.tv_sec = TIME_T_MIN, .tv_nsec = -1}, |
171 | }, |
172 | /* SUM overflow */ |
173 | {.time = {.tv_sec = TIME_T_MAX, .tv_nsec = TIMESPEC_HZ}, |
174 | .norm = {.tv_sec = TIME_T_MAX, .tv_nsec = TIMESPEC_HZ - 1}, |
175 | }, |
176 | /* SUM underflow */ |
177 | {.time = {.tv_sec = TIME_T_MIN, .tv_nsec = -TIMESPEC_HZ}, |
178 | .norm = {.tv_sec = TIME_T_MIN, .tv_nsec = -1 * (TIMESPEC_HZ - 1)}, |
179 | } |
180 | }; |
181 | |
182 | /* Test cases for timespec_check_in_range */ |
183 | struct timespec_test_case check_cases[] = { |
184 | /* 0 - In range */ |
185 | {.expected = {.tv_sec = 1, .tv_nsec = 0}, |
186 | .observed = {.tv_sec = 1, .tv_nsec = 0}, |
187 | .upper_bound = 1, .lower_bound = 1, .result = 1, |
188 | }, |
189 | /* 1 - Out of range */ |
190 | {.expected = {.tv_sec = 1, .tv_nsec = 0}, |
191 | .observed = {.tv_sec = 2, .tv_nsec = 0}, |
192 | .upper_bound = 1, .lower_bound = 1, .result = 0, |
193 | }, |
194 | /* 2 - Upper Bound */ |
195 | {.expected = {.tv_sec = 1, .tv_nsec = 0}, |
196 | .observed = {.tv_sec = 2, .tv_nsec = 0}, |
197 | .upper_bound = 2, .lower_bound = 1, .result = 1, |
198 | }, |
199 | /* 3 - Lower Bound */ |
200 | {.expected = {.tv_sec = 1, .tv_nsec = 0}, |
201 | .observed = {.tv_sec = 0, .tv_nsec = 0}, |
202 | .upper_bound = 1, .lower_bound = 0, .result = 1, |
203 | }, |
204 | /* 4 - Out of range by nanosecs */ |
205 | {.expected = {.tv_sec = 1, .tv_nsec = 0}, |
206 | .observed = {.tv_sec = 1, .tv_nsec = 500}, |
207 | .upper_bound = 1, .lower_bound = 1, .result = 0, |
208 | }, |
209 | /* 5 - In range by nanosecs */ |
210 | {.expected = {.tv_sec = 1, .tv_nsec = 0}, |
211 | .observed = {.tv_sec = 1, .tv_nsec = 50000}, |
212 | .upper_bound = 1.3, .lower_bound = 1, .result = 1, |
213 | }, |
214 | /* 6 - Big nanosecs */ |
215 | {.expected = {.tv_sec = 1, .tv_nsec = 0}, |
216 | .observed = {.tv_sec = 0, .tv_nsec = 4000000}, |
217 | .upper_bound = 1, .lower_bound = .001, .result = 1, |
218 | }, |
219 | /* 7 - In range Negative values */ |
220 | {.expected = {.tv_sec = -1, .tv_nsec = 0}, |
221 | .observed = {.tv_sec = -1, .tv_nsec = 0}, |
222 | .upper_bound = 1, .lower_bound = 1, .result = 1, |
223 | }, |
224 | /* 8 - Out of range Negative values */ |
225 | {.expected = {.tv_sec = -1, .tv_nsec = 0}, |
226 | .observed = {.tv_sec = -1, .tv_nsec = 0}, |
227 | .upper_bound = -1, .lower_bound = -1, .result = 0, |
228 | }, |
229 | /* 9 - Negative values with negative nanosecs */ |
230 | {.expected = {.tv_sec = -1, .tv_nsec = 0}, |
231 | .observed = {.tv_sec = -1, .tv_nsec = -2000}, |
232 | .upper_bound = 1, .lower_bound = 1, .result = 0, |
233 | }, |
234 | /* 10 - Strict bounds */ |
235 | {.expected = {.tv_sec = -1, .tv_nsec = 0}, |
236 | .observed = {.tv_sec = -1, .tv_nsec = -20000}, |
237 | .upper_bound = 1.00002, .lower_bound = 1.0000191, .result = 1, |
238 | }, |
239 | /* 11 - Strict bounds with loose upper bound */ |
240 | {.expected = {.tv_sec = 1, .tv_nsec = 20000}, |
241 | .observed = {.tv_sec = 1, .tv_nsec = 30000}, |
242 | .upper_bound = 1.0000100000, .lower_bound = 1.0000099998, .result = 1, |
243 | }, |
244 | /* 12 - Strict bounds with loose lower bound */ |
245 | {.expected = {.tv_sec = 1, .tv_nsec = 20000}, |
246 | .observed = {.tv_sec = 1, .tv_nsec = 30000}, |
247 | .upper_bound = 1.0000099999, .lower_bound = 1.00000999979, .result = 1, |
248 | }, |
249 | /* 13 - Strict bounds highest precision */ |
250 | {.expected = {.tv_sec = 1, .tv_nsec = 20000}, |
251 | .observed = {.tv_sec = 1, .tv_nsec = 30000}, |
252 | .upper_bound = 1.00000999980001, .lower_bound = 1.00000999979999, .result = 1, |
253 | }, |
254 | /* Maximum/Minimum long values */ |
255 | /* 14 */ |
256 | {.expected = {.tv_sec = TIME_T_MAX, .tv_nsec = TIMESPEC_HZ - 1}, |
257 | .observed = {.tv_sec = TIME_T_MAX, .tv_nsec = TIMESPEC_HZ - 2}, |
258 | .upper_bound = 1, .lower_bound = .9, .result = 1, |
259 | }, |
260 | /* 15 - support_timespec_ns overflow */ |
261 | {.expected = {.tv_sec = TIME_T_MAX, .tv_nsec = TIMESPEC_HZ}, |
262 | .observed = {.tv_sec = TIME_T_MAX, .tv_nsec = TIMESPEC_HZ}, |
263 | .upper_bound = 1, .lower_bound = 1, .result = 1, |
264 | }, |
265 | /* 16 - support_timespec_ns overflow + underflow */ |
266 | {.expected = {.tv_sec = TIME_T_MAX, .tv_nsec = TIMESPEC_HZ}, |
267 | .observed = {.tv_sec = TIME_T_MIN, .tv_nsec = -TIMESPEC_HZ}, |
268 | .upper_bound = 1, .lower_bound = 1, .result = 0, |
269 | }, |
270 | /* 17 - support_timespec_ns underflow */ |
271 | {.expected = {.tv_sec = TIME_T_MIN, .tv_nsec = -TIMESPEC_HZ}, |
272 | .observed = {.tv_sec = TIME_T_MIN, .tv_nsec = -TIMESPEC_HZ}, |
273 | .upper_bound = 1, .lower_bound = 1, .result = 1, |
274 | }, |
275 | /* 18 - support_timespec_ns underflow + overflow */ |
276 | {.expected = {.tv_sec = TIME_T_MIN, .tv_nsec = -TIMESPEC_HZ}, |
277 | .observed = {.tv_sec = TIME_T_MAX, .tv_nsec = TIMESPEC_HZ}, |
278 | .upper_bound = 1, .lower_bound = 1, .result = 0, |
279 | }, |
280 | /* 19 - Biggest division */ |
281 | {.expected = {.tv_sec = TIME_T_MAX / TIMESPEC_HZ, |
282 | .tv_nsec = TIMESPEC_HZ - 1}, |
283 | .observed = {.tv_sec = 0, .tv_nsec = 1}, |
284 | .upper_bound = 1, .lower_bound = 1.0842021724855044e-19, .result = 1, |
285 | }, |
286 | /* 20 - Lowest division */ |
287 | {.expected = {.tv_sec = 0, .tv_nsec = 1}, |
288 | .observed = {.tv_sec = TIME_T_MAX / TIMESPEC_HZ, |
289 | .tv_nsec = TIMESPEC_HZ - 1}, |
290 | .upper_bound = TIME_T_MAX, .lower_bound = 1, .result = 1, |
291 | }, |
292 | }; |
293 | |
294 | static int |
295 | do_test (void) |
296 | { |
297 | int i = 0; |
298 | int ntests = sizeof (ns_cases) / sizeof (ns_cases[0]); |
299 | |
300 | printf(format: "Testing support_timespec_ns\n" ); |
301 | for (i = 0; i < ntests; i++) |
302 | { |
303 | printf(format: "Test case %d\n" , i); |
304 | TEST_COMPARE (support_timespec_ns (ns_cases[i].time), |
305 | ns_cases[i].time_ns); |
306 | } |
307 | |
308 | ntests = sizeof (norm_cases) / sizeof (norm_cases[0]); |
309 | struct timespec result; |
310 | printf(format: "Testing support_timespec_normalize\n" ); |
311 | for (i = 0; i < ntests; i++) |
312 | { |
313 | printf(format: "Test case %d\n" , i); |
314 | result = support_timespec_normalize (time: norm_cases[i].time); |
315 | TEST_COMPARE (norm_cases[i].norm.tv_sec, result.tv_sec); |
316 | TEST_COMPARE (norm_cases[i].norm.tv_nsec, result.tv_nsec); |
317 | } |
318 | |
319 | ntests = sizeof (check_cases) / sizeof (check_cases[0]); |
320 | printf(format: "Testing support_timespec_check_in_range\n" ); |
321 | for (i = 0; i < ntests; i++) |
322 | { |
323 | /* Its hard to find which test failed with just the TEST_COMPARE report. |
324 | So here we print every running testcase as well. */ |
325 | printf(format: "Test case %d\n" , i); |
326 | TEST_COMPARE (support_timespec_check_in_range |
327 | (check_cases[i].expected, check_cases[i].observed, |
328 | check_cases[i].lower_bound, |
329 | check_cases[i].upper_bound), check_cases[i].result); |
330 | } |
331 | return 0; |
332 | } |
333 | |
334 | #include <support/test-driver.c> |
335 | |