]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-time-util.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / test / test-time-util.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
cb0dac05
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
1bb4b028
LP
21#include "random-util.h"
22#include "string-util.h"
6accc7a2 23#include "strv.h"
cf0fbc49 24#include "time-util.h"
cb0dac05
LP
25
26static void test_parse_sec(void) {
27 usec_t u;
28
29 assert_se(parse_sec("5s", &u) >= 0);
30 assert_se(u == 5 * USEC_PER_SEC);
31 assert_se(parse_sec("5s500ms", &u) >= 0);
32 assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC);
33 assert_se(parse_sec(" 5s 500ms ", &u) >= 0);
34 assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC);
35 assert_se(parse_sec(" 5.5s ", &u) >= 0);
36 assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC);
37 assert_se(parse_sec(" 5.5s 0.5ms ", &u) >= 0);
38 assert_se(u == 5 * USEC_PER_SEC + 500 * USEC_PER_MSEC + 500);
39 assert_se(parse_sec(" .22s ", &u) >= 0);
40 assert_se(u == 220 * USEC_PER_MSEC);
41 assert_se(parse_sec(" .50y ", &u) >= 0);
42 assert_se(u == USEC_PER_YEAR / 2);
43 assert_se(parse_sec("2.5", &u) >= 0);
44 assert_se(u == 2500 * USEC_PER_MSEC);
45 assert_se(parse_sec(".7", &u) >= 0);
46 assert_se(u == 700 * USEC_PER_MSEC);
5efdbf11
LP
47 assert_se(parse_sec("23us", &u) >= 0);
48 assert_se(u == 23);
49 assert_se(parse_sec("23µs", &u) >= 0);
50 assert_se(u == 23);
b1d6dcf5
ZJS
51 assert_se(parse_sec("infinity", &u) >= 0);
52 assert_se(u == USEC_INFINITY);
53 assert_se(parse_sec(" infinity ", &u) >= 0);
54 assert_se(u == USEC_INFINITY);
cb0dac05
LP
55
56 assert_se(parse_sec(" xyz ", &u) < 0);
57 assert_se(parse_sec("", &u) < 0);
58 assert_se(parse_sec(" . ", &u) < 0);
59 assert_se(parse_sec(" 5. ", &u) < 0);
60 assert_se(parse_sec(".s ", &u) < 0);
b1d6dcf5
ZJS
61 assert_se(parse_sec(" infinity .7", &u) < 0);
62 assert_se(parse_sec(".3 infinity", &u) < 0);
cb0dac05
LP
63}
64
0004f698
ZJS
65static void test_parse_sec_fix_0(void) {
66 usec_t u;
67
68 assert_se(parse_sec_fix_0("5s", &u) >= 0);
69 assert_se(u == 5 * USEC_PER_SEC);
70 assert_se(parse_sec_fix_0("0s", &u) >= 0);
71 assert_se(u == 0 * USEC_PER_SEC);
72 assert_se(parse_sec_fix_0("0", &u) >= 0);
73 assert_se(u == USEC_INFINITY);
74 assert_se(parse_sec_fix_0(" 0", &u) >= 0);
75 assert_se(u == USEC_INFINITY);
76}
77
519cffec
LP
78static void test_parse_time(void) {
79 usec_t u;
80
81 assert_se(parse_time("5", &u, 1) >= 0);
82 assert_se(u == 5);
83
84 assert_se(parse_time("5", &u, USEC_PER_MSEC) >= 0);
85 assert_se(u == 5 * USEC_PER_MSEC);
86
87 assert_se(parse_time("5", &u, USEC_PER_SEC) >= 0);
88 assert_se(u == 5 * USEC_PER_SEC);
89
90 assert_se(parse_time("5s", &u, 1) >= 0);
91 assert_se(u == 5 * USEC_PER_SEC);
92
93 assert_se(parse_time("5s", &u, USEC_PER_SEC) >= 0);
94 assert_se(u == 5 * USEC_PER_SEC);
95
96 assert_se(parse_time("5s", &u, USEC_PER_MSEC) >= 0);
97 assert_se(u == 5 * USEC_PER_SEC);
98}
99
cb0dac05
LP
100static void test_parse_nsec(void) {
101 nsec_t u;
102
103 assert_se(parse_nsec("5s", &u) >= 0);
104 assert_se(u == 5 * NSEC_PER_SEC);
105 assert_se(parse_nsec("5s500ms", &u) >= 0);
106 assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC);
107 assert_se(parse_nsec(" 5s 500ms ", &u) >= 0);
108 assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC);
109 assert_se(parse_nsec(" 5.5s ", &u) >= 0);
110 assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC);
111 assert_se(parse_nsec(" 5.5s 0.5ms ", &u) >= 0);
112 assert_se(u == 5 * NSEC_PER_SEC + 500 * NSEC_PER_MSEC + 500 * NSEC_PER_USEC);
113 assert_se(parse_nsec(" .22s ", &u) >= 0);
114 assert_se(u == 220 * NSEC_PER_MSEC);
115 assert_se(parse_nsec(" .50y ", &u) >= 0);
116 assert_se(u == NSEC_PER_YEAR / 2);
117 assert_se(parse_nsec("2.5", &u) >= 0);
118 assert_se(u == 2);
119 assert_se(parse_nsec(".7", &u) >= 0);
120 assert_se(u == 0);
fdd30a15
DM
121 assert_se(parse_nsec("infinity", &u) >= 0);
122 assert_se(u == NSEC_INFINITY);
123 assert_se(parse_nsec(" infinity ", &u) >= 0);
124 assert_se(u == NSEC_INFINITY);
cb0dac05
LP
125
126 assert_se(parse_nsec(" xyz ", &u) < 0);
127 assert_se(parse_nsec("", &u) < 0);
128 assert_se(parse_nsec(" . ", &u) < 0);
129 assert_se(parse_nsec(" 5. ", &u) < 0);
130 assert_se(parse_nsec(".s ", &u) < 0);
fdd30a15
DM
131 assert_se(parse_nsec(" infinity .7", &u) < 0);
132 assert_se(parse_nsec(".3 infinity", &u) < 0);
cb0dac05
LP
133}
134
2fa4092c
LP
135static void test_format_timespan_one(usec_t x, usec_t accuracy) {
136 char *r;
137 char l[FORMAT_TIMESPAN_MAX];
138 usec_t y;
139
de0671ee 140 log_info(USEC_FMT" (at accuracy "USEC_FMT")", x, accuracy);
2fa4092c
LP
141
142 r = format_timespan(l, sizeof(l), x, accuracy);
143 assert_se(r);
144
145 log_info(" = <%s>", l);
146
147 assert_se(parse_sec(l, &y) >= 0);
148
de0671ee 149 log_info(" = "USEC_FMT, y);
2fa4092c
LP
150
151 if (accuracy <= 0)
152 accuracy = 1;
153
154 assert_se(x / accuracy == y / accuracy);
155}
156
157static void test_format_timespan(usec_t accuracy) {
158 test_format_timespan_one(0, accuracy);
159 test_format_timespan_one(1, accuracy);
160 test_format_timespan_one(1*USEC_PER_SEC, accuracy);
161 test_format_timespan_one(999*USEC_PER_MSEC, accuracy);
162 test_format_timespan_one(1234567, accuracy);
163 test_format_timespan_one(12, accuracy);
164 test_format_timespan_one(123, accuracy);
165 test_format_timespan_one(1234, accuracy);
166 test_format_timespan_one(12345, accuracy);
167 test_format_timespan_one(123456, accuracy);
168 test_format_timespan_one(1234567, accuracy);
169 test_format_timespan_one(12345678, accuracy);
170 test_format_timespan_one(1200000, accuracy);
171 test_format_timespan_one(1230000, accuracy);
172 test_format_timespan_one(1230000, accuracy);
173 test_format_timespan_one(1234000, accuracy);
174 test_format_timespan_one(1234500, accuracy);
175 test_format_timespan_one(1234560, accuracy);
176 test_format_timespan_one(1234567, accuracy);
177 test_format_timespan_one(986087, accuracy);
178 test_format_timespan_one(500 * USEC_PER_MSEC, accuracy);
179 test_format_timespan_one(9*USEC_PER_YEAR/5 - 23, accuracy);
b1d6dcf5 180 test_format_timespan_one(USEC_INFINITY, accuracy);
2fa4092c
LP
181}
182
6accc7a2
RC
183static void test_timezone_is_valid(void) {
184 assert_se(timezone_is_valid("Europe/Berlin"));
185 assert_se(timezone_is_valid("Australia/Sydney"));
186 assert_se(!timezone_is_valid("Europe/Do not exist"));
187}
188
189static void test_get_timezones(void) {
190 _cleanup_strv_free_ char **zones = NULL;
191 int r;
192 char **zone;
193
194 r = get_timezones(&zones);
195 assert_se(r == 0);
196
53f555b6 197 STRV_FOREACH(zone, zones)
6accc7a2 198 assert_se(timezone_is_valid(*zone));
53f555b6
LP
199}
200
201static void test_usec_add(void) {
202 assert_se(usec_add(0, 0) == 0);
203 assert_se(usec_add(1, 4) == 5);
204 assert_se(usec_add(USEC_INFINITY, 5) == USEC_INFINITY);
205 assert_se(usec_add(5, USEC_INFINITY) == USEC_INFINITY);
206 assert_se(usec_add(USEC_INFINITY-5, 2) == USEC_INFINITY-3);
207 assert_se(usec_add(USEC_INFINITY-2, 2) == USEC_INFINITY);
208 assert_se(usec_add(USEC_INFINITY-1, 2) == USEC_INFINITY);
209 assert_se(usec_add(USEC_INFINITY, 2) == USEC_INFINITY);
6accc7a2
RC
210}
211
54d8ef14
LP
212static void test_usec_sub_unsigned(void) {
213 assert_se(usec_sub_unsigned(0, 0) == 0);
214 assert_se(usec_sub_unsigned(0, 2) == 0);
215 assert_se(usec_sub_unsigned(0, USEC_INFINITY) == 0);
216 assert_se(usec_sub_unsigned(1, 0) == 1);
217 assert_se(usec_sub_unsigned(1, 1) == 0);
218 assert_se(usec_sub_unsigned(1, 2) == 0);
219 assert_se(usec_sub_unsigned(1, 3) == 0);
220 assert_se(usec_sub_unsigned(1, USEC_INFINITY) == 0);
221 assert_se(usec_sub_unsigned(USEC_INFINITY-1, 0) == USEC_INFINITY-1);
222 assert_se(usec_sub_unsigned(USEC_INFINITY-1, 1) == USEC_INFINITY-2);
223 assert_se(usec_sub_unsigned(USEC_INFINITY-1, 2) == USEC_INFINITY-3);
224 assert_se(usec_sub_unsigned(USEC_INFINITY-1, USEC_INFINITY-2) == 1);
225 assert_se(usec_sub_unsigned(USEC_INFINITY-1, USEC_INFINITY-1) == 0);
226 assert_se(usec_sub_unsigned(USEC_INFINITY-1, USEC_INFINITY) == 0);
227 assert_se(usec_sub_unsigned(USEC_INFINITY, 0) == USEC_INFINITY);
228 assert_se(usec_sub_unsigned(USEC_INFINITY, 1) == USEC_INFINITY);
229 assert_se(usec_sub_unsigned(USEC_INFINITY, 2) == USEC_INFINITY);
230 assert_se(usec_sub_unsigned(USEC_INFINITY, USEC_INFINITY) == USEC_INFINITY);
231}
232
233static void test_usec_sub_signed(void) {
234 assert_se(usec_sub_signed(0, 0) == 0);
235 assert_se(usec_sub_signed(4, 1) == 3);
236 assert_se(usec_sub_signed(4, 4) == 0);
237 assert_se(usec_sub_signed(4, 5) == 0);
238 assert_se(usec_sub_signed(USEC_INFINITY-3, -3) == USEC_INFINITY);
239 assert_se(usec_sub_signed(USEC_INFINITY-3, -3) == USEC_INFINITY);
240 assert_se(usec_sub_signed(USEC_INFINITY-3, -4) == USEC_INFINITY);
241 assert_se(usec_sub_signed(USEC_INFINITY-3, -5) == USEC_INFINITY);
242 assert_se(usec_sub_signed(USEC_INFINITY, 5) == USEC_INFINITY);
04a1d84c
LP
243}
244
21b3a0fc
LP
245static void test_format_timestamp(void) {
246 unsigned i;
247
248 for (i = 0; i < 100; i++) {
249 char buf[MAX(FORMAT_TIMESTAMP_MAX, FORMAT_TIMESPAN_MAX)];
250 usec_t x, y;
251
252 random_bytes(&x, sizeof(x));
253 x = x % (2147483600 * USEC_PER_SEC) + 1;
254
255 assert_se(format_timestamp(buf, sizeof(buf), x));
256 log_info("%s", buf);
257 assert_se(parse_timestamp(buf, &y) >= 0);
258 assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
259
260 assert_se(format_timestamp_utc(buf, sizeof(buf), x));
261 log_info("%s", buf);
262 assert_se(parse_timestamp(buf, &y) >= 0);
263 assert_se(x / USEC_PER_SEC == y / USEC_PER_SEC);
264
265 assert_se(format_timestamp_us(buf, sizeof(buf), x));
266 log_info("%s", buf);
267 assert_se(parse_timestamp(buf, &y) >= 0);
268 assert_se(x == y);
269
270 assert_se(format_timestamp_us_utc(buf, sizeof(buf), x));
271 log_info("%s", buf);
272 assert_se(parse_timestamp(buf, &y) >= 0);
273 assert_se(x == y);
274
275 assert_se(format_timestamp_relative(buf, sizeof(buf), x));
276 log_info("%s", buf);
277 assert_se(parse_timestamp(buf, &y) >= 0);
278
279 /* The two calls above will run with a slightly different local time. Make sure we are in the same
280 * range however, but give enough leeway that this is unlikely to explode. And of course,
281 * format_timestamp_relative() scales the accuracy with the distance from the current time up to one
282 * month, cover for that too. */
283 assert_se(y > x ? y - x : x - y <= USEC_PER_MONTH + USEC_PER_DAY);
284 }
285}
286
1bb4b028
LP
287static void test_format_timestamp_utc_one(usec_t t, const char *result) {
288 char buf[FORMAT_TIMESTAMP_MAX];
289
290 assert_se(!format_timestamp_utc(buf, sizeof(buf), t) == !result);
291
292 if (result)
293 assert_se(streq(result, buf));
294}
295
296static void test_format_timestamp_utc(void) {
297 test_format_timestamp_utc_one(0, NULL);
298 test_format_timestamp_utc_one(1, "Thu 1970-01-01 00:00:00 UTC");
299 test_format_timestamp_utc_one(USEC_PER_SEC, "Thu 1970-01-01 00:00:01 UTC");
300
301#if SIZEOF_TIME_T == 8
302 test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Thu 9999-12-30 23:59:59 UTC");
303#elif SIZEOF_TIME_T == 4
304 test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX, "Tue 2038-01-19 03:14:07 UTC");
305#endif
306
307 test_format_timestamp_utc_one(USEC_TIMESTAMP_FORMATTABLE_MAX+1, NULL);
308 test_format_timestamp_utc_one(USEC_INFINITY, NULL);
309}
310
9c0565b2
ZJS
311static void test_dual_timestamp_deserialize(void) {
312 int r;
313 dual_timestamp t;
314
315 r = dual_timestamp_deserialize("1234 5678", &t);
316 assert_se(r == 0);
317 assert_se(t.realtime == 1234);
318 assert_se(t.monotonic == 5678);
319
320 r = dual_timestamp_deserialize("1234x 5678", &t);
321 assert_se(r == -EINVAL);
322
323 r = dual_timestamp_deserialize("1234 5678y", &t);
324 assert_se(r == -EINVAL);
325
326 r = dual_timestamp_deserialize("-1234 5678", &t);
327 assert_se(r == -EINVAL);
328
329 r = dual_timestamp_deserialize("1234 -5678", &t);
330 assert_se(r == -EINVAL);
331
332 /* Check that output wasn't modified. */
333 assert_se(t.realtime == 1234);
334 assert_se(t.monotonic == 5678);
335
336 r = dual_timestamp_deserialize("+123 567", &t);
337 assert_se(r == 0);
338 assert_se(t.realtime == 123);
339 assert_se(t.monotonic == 567);
340
341 /* Check that we get "infinity" on overflow. */
342 r = dual_timestamp_deserialize("18446744073709551617 0", &t);
343 assert_se(r == 0);
344 assert_se(t.realtime == USEC_INFINITY);
345 assert_se(t.monotonic == 0);
346}
347
1007ec60
LP
348static void assert_similar(usec_t a, usec_t b) {
349 usec_t d;
350
351 if (a > b)
352 d = a - b;
353 else
354 d = b - a;
355
356 assert(d < 10*USEC_PER_SEC);
357}
358
359static void test_usec_shift_clock(void) {
360 usec_t rt, mn, bt;
361
362 rt = now(CLOCK_REALTIME);
363 mn = now(CLOCK_MONOTONIC);
364 bt = now(clock_boottime_or_monotonic());
365
366 assert_se(usec_shift_clock(USEC_INFINITY, CLOCK_REALTIME, CLOCK_MONOTONIC) == USEC_INFINITY);
367
368 assert_similar(usec_shift_clock(rt + USEC_PER_HOUR, CLOCK_REALTIME, CLOCK_MONOTONIC), mn + USEC_PER_HOUR);
369 assert_similar(usec_shift_clock(rt + 2*USEC_PER_HOUR, CLOCK_REALTIME, clock_boottime_or_monotonic()), bt + 2*USEC_PER_HOUR);
370 assert_se(usec_shift_clock(rt + 3*USEC_PER_HOUR, CLOCK_REALTIME, CLOCK_REALTIME_ALARM) == rt + 3*USEC_PER_HOUR);
371
372 assert_similar(usec_shift_clock(mn + 4*USEC_PER_HOUR, CLOCK_MONOTONIC, CLOCK_REALTIME_ALARM), rt + 4*USEC_PER_HOUR);
373 assert_similar(usec_shift_clock(mn + 5*USEC_PER_HOUR, CLOCK_MONOTONIC, clock_boottime_or_monotonic()), bt + 5*USEC_PER_HOUR);
374 assert_se(usec_shift_clock(mn + 6*USEC_PER_HOUR, CLOCK_MONOTONIC, CLOCK_MONOTONIC) == mn + 6*USEC_PER_HOUR);
375
376 assert_similar(usec_shift_clock(bt + 7*USEC_PER_HOUR, clock_boottime_or_monotonic(), CLOCK_MONOTONIC), mn + 7*USEC_PER_HOUR);
377 assert_similar(usec_shift_clock(bt + 8*USEC_PER_HOUR, clock_boottime_or_monotonic(), CLOCK_REALTIME_ALARM), rt + 8*USEC_PER_HOUR);
378 assert_se(usec_shift_clock(bt + 9*USEC_PER_HOUR, clock_boottime_or_monotonic(), clock_boottime_or_monotonic()) == bt + 9*USEC_PER_HOUR);
379
380 if (mn > USEC_PER_MINUTE) {
381 assert_similar(usec_shift_clock(rt - 30 * USEC_PER_SEC, CLOCK_REALTIME_ALARM, CLOCK_MONOTONIC), mn - 30 * USEC_PER_SEC);
382 assert_similar(usec_shift_clock(rt - 50 * USEC_PER_SEC, CLOCK_REALTIME, clock_boottime_or_monotonic()), bt - 50 * USEC_PER_SEC);
383 }
384}
385
cb0dac05 386int main(int argc, char *argv[]) {
2d60169d
LP
387 uintmax_t x;
388
c4834ffa
LP
389 log_info("realtime=" USEC_FMT "\n"
390 "monotonic=" USEC_FMT "\n"
391 "boottime=" USEC_FMT "\n",
392 now(CLOCK_REALTIME),
393 now(CLOCK_MONOTONIC),
394 now(clock_boottime_or_monotonic()));
395
cb0dac05 396 test_parse_sec();
0004f698 397 test_parse_sec_fix_0();
519cffec 398 test_parse_time();
cb0dac05 399 test_parse_nsec();
2fa4092c
LP
400 test_format_timespan(1);
401 test_format_timespan(USEC_PER_MSEC);
402 test_format_timespan(USEC_PER_SEC);
6accc7a2
RC
403 test_timezone_is_valid();
404 test_get_timezones();
53f555b6 405 test_usec_add();
54d8ef14
LP
406 test_usec_sub_signed();
407 test_usec_sub_unsigned();
21b3a0fc 408 test_format_timestamp();
1bb4b028 409 test_format_timestamp_utc();
9c0565b2 410 test_dual_timestamp_deserialize();
1007ec60 411 test_usec_shift_clock();
6accc7a2 412
2d60169d
LP
413 /* Ensure time_t is signed */
414 assert_cc((time_t) -1 < (time_t) 1);
415
416 /* Ensure TIME_T_MAX works correctly */
417 x = (uintmax_t) TIME_T_MAX;
313cefa1 418 x++;
2d60169d
LP
419 assert((time_t) x < 0);
420
cb0dac05
LP
421 return 0;
422}