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
do_test(void)295 do_test (void)
296 {
297 int i = 0;
298 int ntests = sizeof (ns_cases) / sizeof (ns_cases[0]);
299
300 printf("Testing support_timespec_ns\n");
301 for (i = 0; i < ntests; i++)
302 {
303 printf("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("Testing support_timespec_normalize\n");
311 for (i = 0; i < ntests; i++)
312 {
313 printf("Test case %d\n", i);
314 result = support_timespec_normalize (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("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("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