Home | History | Annotate | Line # | Download | only in isc
      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