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