time_test.c revision 1.1.1.2 1 1.1 christos /* $NetBSD: time_test.c,v 1.1.1.2 2025/01/26 16:12:36 christos Exp $ */
2 1.1 christos
3 1.1 christos /*
4 1.1 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 1.1 christos *
6 1.1 christos * SPDX-License-Identifier: MPL-2.0
7 1.1 christos *
8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public
9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this
10 1.1 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 1.1 christos *
12 1.1 christos * See the COPYRIGHT file distributed with this work for additional
13 1.1 christos * information regarding copyright ownership.
14 1.1 christos */
15 1.1 christos
16 1.1 christos #include <inttypes.h>
17 1.1 christos #include <sched.h> /* IWYU pragma: keep */
18 1.1 christos #include <setjmp.h>
19 1.1 christos #include <stdarg.h>
20 1.1 christos #include <stddef.h>
21 1.1 christos #include <stdio.h>
22 1.1 christos #include <stdlib.h>
23 1.1 christos #include <string.h>
24 1.1 christos
25 1.1 christos #define UNIT_TESTING
26 1.1 christos #include <cmocka.h>
27 1.1 christos
28 1.1 christos #include <isc/result.h>
29 1.1 christos #include <isc/time.h>
30 1.1 christos #include <isc/util.h>
31 1.1 christos
32 1.1 christos #include "time.c"
33 1.1 christos
34 1.1 christos #include <tests/isc.h>
35 1.1 christos
36 1.1 christos #define MAX_NS (NS_PER_SEC - 1)
37 1.1 christos
38 1.1 christos struct time_vectors {
39 1.1 christos isc_time_t a;
40 1.1 christos isc_interval_t b;
41 1.1 christos isc_time_t r;
42 1.1 christos isc_result_t result;
43 1.1 christos };
44 1.1 christos
45 1.1 christos const struct time_vectors vectors_add[8] = {
46 1.1 christos { { 0, 0 }, { 0, 0 }, { 0, 0 }, ISC_R_SUCCESS },
47 1.1 christos { { 0, MAX_NS }, { 0, MAX_NS }, { 1, MAX_NS - 1 }, ISC_R_SUCCESS },
48 1.1 christos { { 0, NS_PER_SEC / 2 },
49 1.1 christos { 0, NS_PER_SEC / 2 },
50 1.1 christos { 1, 0 },
51 1.1 christos ISC_R_SUCCESS },
52 1.1 christos { { UINT_MAX, MAX_NS }, { 0, 0 }, { UINT_MAX, MAX_NS }, ISC_R_SUCCESS },
53 1.1 christos { { UINT_MAX, 0 }, { 0, MAX_NS }, { UINT_MAX, MAX_NS }, ISC_R_SUCCESS },
54 1.1 christos { { UINT_MAX, 0 }, { 1, 0 }, { 0, 0 }, ISC_R_RANGE },
55 1.1 christos { { UINT_MAX, MAX_NS }, { 0, 1 }, { 0, 0 }, ISC_R_RANGE },
56 1.1 christos { { UINT_MAX / 2 + 1, NS_PER_SEC / 2 },
57 1.1 christos { UINT_MAX / 2, NS_PER_SEC / 2 },
58 1.1 christos { 0, 0 },
59 1.1 christos ISC_R_RANGE },
60 1.1 christos };
61 1.1 christos
62 1.1 christos const struct time_vectors vectors_sub[7] = {
63 1.1 christos { { 0, 0 }, { 0, 0 }, { 0, 0 }, ISC_R_SUCCESS },
64 1.1 christos { { 1, 0 }, { 0, MAX_NS }, { 0, 1 }, ISC_R_SUCCESS },
65 1.1 christos { { 1, NS_PER_SEC / 2 },
66 1.1 christos { 0, MAX_NS },
67 1.1 christos { 0, NS_PER_SEC / 2 + 1 },
68 1.1 christos ISC_R_SUCCESS },
69 1.1 christos { { UINT_MAX, MAX_NS }, { UINT_MAX, 0 }, { 0, MAX_NS }, ISC_R_SUCCESS },
70 1.1 christos { { 0, 0 }, { 1, 0 }, { 0, 0 }, ISC_R_RANGE },
71 1.1 christos { { 0, 0 }, { 0, MAX_NS }, { 0, 0 }, ISC_R_RANGE },
72 1.1 christos };
73 1.1 christos
74 1.1 christos ISC_RUN_TEST_IMPL(isc_time_add_test) {
75 1.1 christos UNUSED(state);
76 1.1 christos
77 1.1 christos for (size_t i = 0; i < ARRAY_SIZE(vectors_add); i++) {
78 1.1 christos isc_time_t r = { UINT_MAX, UINT_MAX };
79 1.1 christos isc_result_t result = isc_time_add(&(vectors_add[i].a),
80 1.1 christos &(vectors_add[i].b), &r);
81 1.1 christos assert_int_equal(result, vectors_add[i].result);
82 1.1 christos if (result != ISC_R_SUCCESS) {
83 1.1 christos continue;
84 1.1 christos }
85 1.1 christos
86 1.1 christos assert_int_equal(r.seconds, vectors_add[i].r.seconds);
87 1.1 christos assert_int_equal(r.nanoseconds, vectors_add[i].r.nanoseconds);
88 1.1 christos }
89 1.1 christos
90 1.1 christos expect_assert_failure((void)isc_time_add(&(isc_time_t){ 0, MAX_NS + 1 },
91 1.1 christos &(isc_interval_t){ 0, 0 },
92 1.1 christos &(isc_time_t){ 0, 0 }));
93 1.1 christos expect_assert_failure((void)isc_time_add(
94 1.1 christos &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, MAX_NS + 1 },
95 1.1 christos &(isc_time_t){ 0, 0 }));
96 1.1 christos
97 1.1 christos expect_assert_failure((void)isc_time_add((isc_time_t *)NULL,
98 1.1 christos &(isc_interval_t){ 0, 0 },
99 1.1 christos &(isc_time_t){ 0, 0 }));
100 1.1 christos expect_assert_failure((void)isc_time_add(&(isc_time_t){ 0, 0 },
101 1.1 christos (isc_interval_t *)NULL,
102 1.1 christos &(isc_time_t){ 0, 0 }));
103 1.1 christos expect_assert_failure((void)isc_time_add(
104 1.1 christos &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, 0 }, NULL));
105 1.1 christos }
106 1.1 christos
107 1.1 christos ISC_RUN_TEST_IMPL(isc_time_sub_test) {
108 1.1 christos UNUSED(state);
109 1.1 christos
110 1.1 christos for (size_t i = 0; i < ARRAY_SIZE(vectors_sub); i++) {
111 1.1 christos isc_time_t r = { UINT_MAX, UINT_MAX };
112 1.1 christos isc_result_t result = isc_time_subtract(
113 1.1 christos &(vectors_sub[i].a), &(vectors_sub[i].b), &r);
114 1.1 christos assert_int_equal(result, vectors_sub[i].result);
115 1.1 christos if (result != ISC_R_SUCCESS) {
116 1.1 christos continue;
117 1.1 christos }
118 1.1 christos assert_int_equal(r.seconds, vectors_sub[i].r.seconds);
119 1.1 christos assert_int_equal(r.nanoseconds, vectors_sub[i].r.nanoseconds);
120 1.1 christos }
121 1.1 christos
122 1.1 christos expect_assert_failure((void)isc_time_subtract(
123 1.1 christos &(isc_time_t){ 0, MAX_NS + 1 }, &(isc_interval_t){ 0, 0 },
124 1.1 christos &(isc_time_t){ 0, 0 }));
125 1.1 christos expect_assert_failure((void)isc_time_subtract(
126 1.1 christos &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, MAX_NS + 1 },
127 1.1 christos &(isc_time_t){ 0, 0 }));
128 1.1 christos
129 1.1 christos expect_assert_failure((void)isc_time_subtract((isc_time_t *)NULL,
130 1.1 christos &(isc_interval_t){ 0, 0 },
131 1.1 christos &(isc_time_t){ 0, 0 }));
132 1.1 christos expect_assert_failure((void)isc_time_subtract(&(isc_time_t){ 0, 0 },
133 1.1 christos (isc_interval_t *)NULL,
134 1.1 christos &(isc_time_t){ 0, 0 }));
135 1.1 christos expect_assert_failure((void)isc_time_subtract(
136 1.1 christos &(isc_time_t){ 0, 0 }, &(isc_interval_t){ 0, 0 }, NULL));
137 1.1 christos }
138 1.1 christos
139 1.1 christos /* parse http time stamp */
140 1.1 christos
141 1.1 christos ISC_RUN_TEST_IMPL(isc_time_parsehttptimestamp_test) {
142 1.1 christos isc_result_t result;
143 1.1 christos isc_time_t t, x;
144 1.1 christos char buf[ISC_FORMATHTTPTIMESTAMP_SIZE];
145 1.1 christos
146 1.1 christos UNUSED(state);
147 1.1 christos
148 1.1 christos setenv("TZ", "America/Los_Angeles", 1);
149 1.1.1.2 christos t = isc_time_now();
150 1.1 christos
151 1.1 christos isc_time_formathttptimestamp(&t, buf, sizeof(buf));
152 1.1 christos result = isc_time_parsehttptimestamp(buf, &x);
153 1.1 christos assert_int_equal(result, ISC_R_SUCCESS);
154 1.1 christos assert_int_equal(isc_time_seconds(&t), isc_time_seconds(&x));
155 1.1 christos }
156 1.1 christos
157 1.1 christos /* print UTC in ISO8601 */
158 1.1 christos
159 1.1 christos ISC_RUN_TEST_IMPL(isc_time_formatISO8601_test) {
160 1.1 christos isc_time_t t;
161 1.1 christos char buf[64];
162 1.1 christos
163 1.1 christos UNUSED(state);
164 1.1 christos
165 1.1 christos setenv("TZ", "America/Los_Angeles", 1);
166 1.1.1.2 christos t = isc_time_now();
167 1.1 christos
168 1.1 christos /* check formatting: yyyy-mm-ddThh:mm:ssZ */
169 1.1 christos memset(buf, 'X', sizeof(buf));
170 1.1 christos isc_time_formatISO8601(&t, buf, sizeof(buf));
171 1.1 christos assert_int_equal(strlen(buf), 20);
172 1.1 christos assert_int_equal(buf[4], '-');
173 1.1 christos assert_int_equal(buf[7], '-');
174 1.1 christos assert_int_equal(buf[10], 'T');
175 1.1 christos assert_int_equal(buf[13], ':');
176 1.1 christos assert_int_equal(buf[16], ':');
177 1.1 christos assert_int_equal(buf[19], 'Z');
178 1.1 christos
179 1.1 christos /* check time conversion correctness */
180 1.1 christos memset(buf, 'X', sizeof(buf));
181 1.1 christos isc_time_settoepoch(&t);
182 1.1 christos isc_time_formatISO8601(&t, buf, sizeof(buf));
183 1.1 christos assert_string_equal(buf, "1970-01-01T00:00:00Z");
184 1.1 christos
185 1.1 christos memset(buf, 'X', sizeof(buf));
186 1.1 christos isc_time_set(&t, 1450000000, 123000000);
187 1.1 christos isc_time_formatISO8601(&t, buf, sizeof(buf));
188 1.1 christos assert_string_equal(buf, "2015-12-13T09:46:40Z");
189 1.1 christos }
190 1.1 christos
191 1.1 christos /* print UTC in ISO8601 with milliseconds */
192 1.1 christos
193 1.1 christos ISC_RUN_TEST_IMPL(isc_time_formatISO8601ms_test) {
194 1.1 christos isc_time_t t;
195 1.1 christos char buf[64];
196 1.1 christos
197 1.1 christos UNUSED(state);
198 1.1 christos
199 1.1 christos setenv("TZ", "America/Los_Angeles", 1);
200 1.1.1.2 christos t = isc_time_now();
201 1.1 christos
202 1.1 christos /* check formatting: yyyy-mm-ddThh:mm:ss.sssZ */
203 1.1 christos memset(buf, 'X', sizeof(buf));
204 1.1 christos isc_time_formatISO8601ms(&t, buf, sizeof(buf));
205 1.1 christos assert_int_equal(strlen(buf), 24);
206 1.1 christos assert_int_equal(buf[4], '-');
207 1.1 christos assert_int_equal(buf[7], '-');
208 1.1 christos assert_int_equal(buf[10], 'T');
209 1.1 christos assert_int_equal(buf[13], ':');
210 1.1 christos assert_int_equal(buf[16], ':');
211 1.1 christos assert_int_equal(buf[19], '.');
212 1.1 christos assert_int_equal(buf[23], 'Z');
213 1.1 christos
214 1.1 christos /* check time conversion correctness */
215 1.1 christos memset(buf, 'X', sizeof(buf));
216 1.1 christos isc_time_settoepoch(&t);
217 1.1 christos isc_time_formatISO8601ms(&t, buf, sizeof(buf));
218 1.1 christos assert_string_equal(buf, "1970-01-01T00:00:00.000Z");
219 1.1 christos
220 1.1 christos memset(buf, 'X', sizeof(buf));
221 1.1 christos isc_time_set(&t, 1450000000, 123000000);
222 1.1 christos isc_time_formatISO8601ms(&t, buf, sizeof(buf));
223 1.1 christos assert_string_equal(buf, "2015-12-13T09:46:40.123Z");
224 1.1 christos }
225 1.1 christos
226 1.1 christos /* print UTC in ISO8601 with microseconds */
227 1.1 christos
228 1.1 christos ISC_RUN_TEST_IMPL(isc_time_formatISO8601us_test) {
229 1.1 christos isc_time_t t;
230 1.1 christos char buf[64];
231 1.1 christos
232 1.1 christos UNUSED(state);
233 1.1 christos
234 1.1 christos setenv("TZ", "America/Los_Angeles", 1);
235 1.1.1.2 christos t = isc_time_now_hires();
236 1.1 christos
237 1.1 christos /* check formatting: yyyy-mm-ddThh:mm:ss.ssssssZ */
238 1.1 christos memset(buf, 'X', sizeof(buf));
239 1.1 christos isc_time_formatISO8601us(&t, buf, sizeof(buf));
240 1.1 christos assert_int_equal(strlen(buf), 27);
241 1.1 christos assert_int_equal(buf[4], '-');
242 1.1 christos assert_int_equal(buf[7], '-');
243 1.1 christos assert_int_equal(buf[10], 'T');
244 1.1 christos assert_int_equal(buf[13], ':');
245 1.1 christos assert_int_equal(buf[16], ':');
246 1.1 christos assert_int_equal(buf[19], '.');
247 1.1 christos assert_int_equal(buf[26], 'Z');
248 1.1 christos
249 1.1 christos /* check time conversion correctness */
250 1.1 christos memset(buf, 'X', sizeof(buf));
251 1.1 christos isc_time_settoepoch(&t);
252 1.1 christos isc_time_formatISO8601us(&t, buf, sizeof(buf));
253 1.1 christos assert_string_equal(buf, "1970-01-01T00:00:00.000000Z");
254 1.1 christos
255 1.1 christos memset(buf, 'X', sizeof(buf));
256 1.1 christos isc_time_set(&t, 1450000000, 123456000);
257 1.1 christos isc_time_formatISO8601us(&t, buf, sizeof(buf));
258 1.1 christos assert_string_equal(buf, "2015-12-13T09:46:40.123456Z");
259 1.1 christos }
260 1.1 christos
261 1.1 christos /* print local time in ISO8601 */
262 1.1 christos
263 1.1 christos ISC_RUN_TEST_IMPL(isc_time_formatISO8601L_test) {
264 1.1 christos isc_time_t t;
265 1.1 christos char buf[64];
266 1.1 christos
267 1.1 christos UNUSED(state);
268 1.1 christos
269 1.1 christos setenv("TZ", "America/Los_Angeles", 1);
270 1.1.1.2 christos t = isc_time_now();
271 1.1 christos
272 1.1 christos /* check formatting: yyyy-mm-ddThh:mm:ss */
273 1.1 christos memset(buf, 'X', sizeof(buf));
274 1.1 christos isc_time_formatISO8601L(&t, buf, sizeof(buf));
275 1.1 christos assert_int_equal(strlen(buf), 19);
276 1.1 christos assert_int_equal(buf[4], '-');
277 1.1 christos assert_int_equal(buf[7], '-');
278 1.1 christos assert_int_equal(buf[10], 'T');
279 1.1 christos assert_int_equal(buf[13], ':');
280 1.1 christos assert_int_equal(buf[16], ':');
281 1.1 christos
282 1.1 christos /* check time conversion correctness */
283 1.1 christos memset(buf, 'X', sizeof(buf));
284 1.1 christos isc_time_settoepoch(&t);
285 1.1 christos isc_time_formatISO8601L(&t, buf, sizeof(buf));
286 1.1 christos assert_string_equal(buf, "1969-12-31T16:00:00");
287 1.1 christos
288 1.1 christos memset(buf, 'X', sizeof(buf));
289 1.1 christos isc_time_set(&t, 1450000000, 123000000);
290 1.1 christos isc_time_formatISO8601L(&t, buf, sizeof(buf));
291 1.1 christos assert_string_equal(buf, "2015-12-13T01:46:40");
292 1.1 christos }
293 1.1 christos
294 1.1 christos /* print local time in ISO8601 with milliseconds */
295 1.1 christos
296 1.1 christos ISC_RUN_TEST_IMPL(isc_time_formatISO8601Lms_test) {
297 1.1 christos isc_time_t t;
298 1.1 christos char buf[64];
299 1.1 christos
300 1.1 christos UNUSED(state);
301 1.1 christos
302 1.1 christos setenv("TZ", "America/Los_Angeles", 1);
303 1.1.1.2 christos t = isc_time_now();
304 1.1 christos
305 1.1 christos /* check formatting: yyyy-mm-ddThh:mm:ss.sss */
306 1.1 christos memset(buf, 'X', sizeof(buf));
307 1.1 christos isc_time_formatISO8601Lms(&t, buf, sizeof(buf));
308 1.1 christos assert_int_equal(strlen(buf), 23);
309 1.1 christos assert_int_equal(buf[4], '-');
310 1.1 christos assert_int_equal(buf[7], '-');
311 1.1 christos assert_int_equal(buf[10], 'T');
312 1.1 christos assert_int_equal(buf[13], ':');
313 1.1 christos assert_int_equal(buf[16], ':');
314 1.1 christos assert_int_equal(buf[19], '.');
315 1.1 christos
316 1.1 christos /* check time conversion correctness */
317 1.1 christos memset(buf, 'X', sizeof(buf));
318 1.1 christos isc_time_settoepoch(&t);
319 1.1 christos isc_time_formatISO8601Lms(&t, buf, sizeof(buf));
320 1.1 christos assert_string_equal(buf, "1969-12-31T16:00:00.000");
321 1.1 christos
322 1.1 christos memset(buf, 'X', sizeof(buf));
323 1.1 christos isc_time_set(&t, 1450000000, 123000000);
324 1.1 christos isc_time_formatISO8601Lms(&t, buf, sizeof(buf));
325 1.1 christos assert_string_equal(buf, "2015-12-13T01:46:40.123");
326 1.1 christos }
327 1.1 christos
328 1.1 christos /* print local time in ISO8601 with microseconds */
329 1.1 christos
330 1.1 christos ISC_RUN_TEST_IMPL(isc_time_formatISO8601Lus_test) {
331 1.1 christos isc_time_t t;
332 1.1 christos char buf[64];
333 1.1 christos
334 1.1 christos UNUSED(state);
335 1.1 christos
336 1.1 christos setenv("TZ", "America/Los_Angeles", 1);
337 1.1.1.2 christos t = isc_time_now_hires();
338 1.1 christos
339 1.1 christos /* check formatting: yyyy-mm-ddThh:mm:ss.ssssss */
340 1.1 christos memset(buf, 'X', sizeof(buf));
341 1.1 christos isc_time_formatISO8601Lus(&t, buf, sizeof(buf));
342 1.1 christos assert_int_equal(strlen(buf), 26);
343 1.1 christos assert_int_equal(buf[4], '-');
344 1.1 christos assert_int_equal(buf[7], '-');
345 1.1 christos assert_int_equal(buf[10], 'T');
346 1.1 christos assert_int_equal(buf[13], ':');
347 1.1 christos assert_int_equal(buf[16], ':');
348 1.1 christos assert_int_equal(buf[19], '.');
349 1.1 christos
350 1.1 christos /* check time conversion correctness */
351 1.1 christos memset(buf, 'X', sizeof(buf));
352 1.1 christos isc_time_settoepoch(&t);
353 1.1 christos isc_time_formatISO8601Lus(&t, buf, sizeof(buf));
354 1.1 christos assert_string_equal(buf, "1969-12-31T16:00:00.000000");
355 1.1 christos
356 1.1 christos memset(buf, 'X', sizeof(buf));
357 1.1 christos isc_time_set(&t, 1450000000, 123456000);
358 1.1 christos isc_time_formatISO8601Lus(&t, buf, sizeof(buf));
359 1.1 christos assert_string_equal(buf, "2015-12-13T01:46:40.123456");
360 1.1 christos }
361 1.1 christos
362 1.1 christos /* print UTC time as yyyymmddhhmmsssss */
363 1.1 christos
364 1.1 christos ISC_RUN_TEST_IMPL(isc_time_formatshorttimestamp_test) {
365 1.1 christos isc_time_t t;
366 1.1 christos char buf[64];
367 1.1 christos
368 1.1 christos UNUSED(state);
369 1.1 christos
370 1.1 christos setenv("TZ", "America/Los_Angeles", 1);
371 1.1.1.2 christos t = isc_time_now();
372 1.1 christos
373 1.1 christos /* check formatting: yyyymmddhhmmsssss */
374 1.1 christos memset(buf, 'X', sizeof(buf));
375 1.1 christos isc_time_formatshorttimestamp(&t, buf, sizeof(buf));
376 1.1 christos assert_int_equal(strlen(buf), 17);
377 1.1 christos
378 1.1 christos /* check time conversion correctness */
379 1.1 christos memset(buf, 'X', sizeof(buf));
380 1.1 christos isc_time_settoepoch(&t);
381 1.1 christos isc_time_formatshorttimestamp(&t, buf, sizeof(buf));
382 1.1 christos assert_string_equal(buf, "19700101000000000");
383 1.1 christos
384 1.1 christos memset(buf, 'X', sizeof(buf));
385 1.1 christos isc_time_set(&t, 1450000000, 123000000);
386 1.1 christos isc_time_formatshorttimestamp(&t, buf, sizeof(buf));
387 1.1 christos assert_string_equal(buf, "20151213094640123");
388 1.1 christos }
389 1.1 christos
390 1.1 christos ISC_TEST_LIST_START
391 1.1 christos
392 1.1 christos ISC_TEST_ENTRY(isc_time_add_test)
393 1.1 christos ISC_TEST_ENTRY(isc_time_sub_test)
394 1.1 christos ISC_TEST_ENTRY(isc_time_parsehttptimestamp_test)
395 1.1 christos ISC_TEST_ENTRY(isc_time_formatISO8601_test)
396 1.1 christos ISC_TEST_ENTRY(isc_time_formatISO8601ms_test)
397 1.1 christos ISC_TEST_ENTRY(isc_time_formatISO8601us_test)
398 1.1 christos ISC_TEST_ENTRY(isc_time_formatISO8601L_test)
399 1.1 christos ISC_TEST_ENTRY(isc_time_formatISO8601Lms_test)
400 1.1 christos ISC_TEST_ENTRY(isc_time_formatISO8601Lus_test)
401 1.1 christos ISC_TEST_ENTRY(isc_time_formatshorttimestamp_test)
402 1.1 christos
403 1.1 christos ISC_TEST_LIST_END
404 1.1 christos
405 1.1 christos ISC_TEST_MAIN
406