1 1.1 christos /* $NetBSD: time_test.c,v 1.3 2025/01/26 16:25:50 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.3 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.3 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.3 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.3 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.3 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.3 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.3 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.3 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