1/* $NetBSD: time_test.c,v 1.2 2024/02/21 22:52:51 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 38struct time_vectors { 39 isc_time_t a; 40 isc_interval_t b; 41 isc_time_t r; 42 isc_result_t result; 43}; 44 45const 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 62const 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 74ISC_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 107ISC_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 141ISC_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 result = isc_time_now(&t); 150 assert_int_equal(result, ISC_R_SUCCESS); 151 152 isc_time_formathttptimestamp(&t, buf, sizeof(buf)); 153 result = isc_time_parsehttptimestamp(buf, &x); 154 assert_int_equal(result, ISC_R_SUCCESS); 155 assert_int_equal(isc_time_seconds(&t), isc_time_seconds(&x)); 156} 157 158/* print UTC in ISO8601 */ 159 160ISC_RUN_TEST_IMPL(isc_time_formatISO8601_test) { 161 isc_result_t result; 162 isc_time_t t; 163 char buf[64]; 164 165 UNUSED(state); 166 167 setenv("TZ", "America/Los_Angeles", 1); 168 result = isc_time_now(&t); 169 assert_int_equal(result, ISC_R_SUCCESS); 170 171 /* check formatting: yyyy-mm-ddThh:mm:ssZ */ 172 memset(buf, 'X', sizeof(buf)); 173 isc_time_formatISO8601(&t, buf, sizeof(buf)); 174 assert_int_equal(strlen(buf), 20); 175 assert_int_equal(buf[4], '-'); 176 assert_int_equal(buf[7], '-'); 177 assert_int_equal(buf[10], 'T'); 178 assert_int_equal(buf[13], ':'); 179 assert_int_equal(buf[16], ':'); 180 assert_int_equal(buf[19], 'Z'); 181 182 /* check time conversion correctness */ 183 memset(buf, 'X', sizeof(buf)); 184 isc_time_settoepoch(&t); 185 isc_time_formatISO8601(&t, buf, sizeof(buf)); 186 assert_string_equal(buf, "1970-01-01T00:00:00Z"); 187 188 memset(buf, 'X', sizeof(buf)); 189 isc_time_set(&t, 1450000000, 123000000); 190 isc_time_formatISO8601(&t, buf, sizeof(buf)); 191 assert_string_equal(buf, "2015-12-13T09:46:40Z"); 192} 193 194/* print UTC in ISO8601 with milliseconds */ 195 196ISC_RUN_TEST_IMPL(isc_time_formatISO8601ms_test) { 197 isc_result_t result; 198 isc_time_t t; 199 char buf[64]; 200 201 UNUSED(state); 202 203 setenv("TZ", "America/Los_Angeles", 1); 204 result = isc_time_now(&t); 205 assert_int_equal(result, ISC_R_SUCCESS); 206 207 /* check formatting: yyyy-mm-ddThh:mm:ss.sssZ */ 208 memset(buf, 'X', sizeof(buf)); 209 isc_time_formatISO8601ms(&t, buf, sizeof(buf)); 210 assert_int_equal(strlen(buf), 24); 211 assert_int_equal(buf[4], '-'); 212 assert_int_equal(buf[7], '-'); 213 assert_int_equal(buf[10], 'T'); 214 assert_int_equal(buf[13], ':'); 215 assert_int_equal(buf[16], ':'); 216 assert_int_equal(buf[19], '.'); 217 assert_int_equal(buf[23], 'Z'); 218 219 /* check time conversion correctness */ 220 memset(buf, 'X', sizeof(buf)); 221 isc_time_settoepoch(&t); 222 isc_time_formatISO8601ms(&t, buf, sizeof(buf)); 223 assert_string_equal(buf, "1970-01-01T00:00:00.000Z"); 224 225 memset(buf, 'X', sizeof(buf)); 226 isc_time_set(&t, 1450000000, 123000000); 227 isc_time_formatISO8601ms(&t, buf, sizeof(buf)); 228 assert_string_equal(buf, "2015-12-13T09:46:40.123Z"); 229} 230 231/* print UTC in ISO8601 with microseconds */ 232 233ISC_RUN_TEST_IMPL(isc_time_formatISO8601us_test) { 234 isc_result_t result; 235 isc_time_t t; 236 char buf[64]; 237 238 UNUSED(state); 239 240 setenv("TZ", "America/Los_Angeles", 1); 241 result = isc_time_now_hires(&t); 242 assert_int_equal(result, ISC_R_SUCCESS); 243 244 /* check formatting: yyyy-mm-ddThh:mm:ss.ssssssZ */ 245 memset(buf, 'X', sizeof(buf)); 246 isc_time_formatISO8601us(&t, buf, sizeof(buf)); 247 assert_int_equal(strlen(buf), 27); 248 assert_int_equal(buf[4], '-'); 249 assert_int_equal(buf[7], '-'); 250 assert_int_equal(buf[10], 'T'); 251 assert_int_equal(buf[13], ':'); 252 assert_int_equal(buf[16], ':'); 253 assert_int_equal(buf[19], '.'); 254 assert_int_equal(buf[26], 'Z'); 255 256 /* check time conversion correctness */ 257 memset(buf, 'X', sizeof(buf)); 258 isc_time_settoepoch(&t); 259 isc_time_formatISO8601us(&t, buf, sizeof(buf)); 260 assert_string_equal(buf, "1970-01-01T00:00:00.000000Z"); 261 262 memset(buf, 'X', sizeof(buf)); 263 isc_time_set(&t, 1450000000, 123456000); 264 isc_time_formatISO8601us(&t, buf, sizeof(buf)); 265 assert_string_equal(buf, "2015-12-13T09:46:40.123456Z"); 266} 267 268/* print local time in ISO8601 */ 269 270ISC_RUN_TEST_IMPL(isc_time_formatISO8601L_test) { 271 isc_result_t result; 272 isc_time_t t; 273 char buf[64]; 274 275 UNUSED(state); 276 277 setenv("TZ", "America/Los_Angeles", 1); 278 result = isc_time_now(&t); 279 assert_int_equal(result, ISC_R_SUCCESS); 280 281 /* check formatting: yyyy-mm-ddThh:mm:ss */ 282 memset(buf, 'X', sizeof(buf)); 283 isc_time_formatISO8601L(&t, buf, sizeof(buf)); 284 assert_int_equal(strlen(buf), 19); 285 assert_int_equal(buf[4], '-'); 286 assert_int_equal(buf[7], '-'); 287 assert_int_equal(buf[10], 'T'); 288 assert_int_equal(buf[13], ':'); 289 assert_int_equal(buf[16], ':'); 290 291 /* check time conversion correctness */ 292 memset(buf, 'X', sizeof(buf)); 293 isc_time_settoepoch(&t); 294 isc_time_formatISO8601L(&t, buf, sizeof(buf)); 295 assert_string_equal(buf, "1969-12-31T16:00:00"); 296 297 memset(buf, 'X', sizeof(buf)); 298 isc_time_set(&t, 1450000000, 123000000); 299 isc_time_formatISO8601L(&t, buf, sizeof(buf)); 300 assert_string_equal(buf, "2015-12-13T01:46:40"); 301} 302 303/* print local time in ISO8601 with milliseconds */ 304 305ISC_RUN_TEST_IMPL(isc_time_formatISO8601Lms_test) { 306 isc_result_t result; 307 isc_time_t t; 308 char buf[64]; 309 310 UNUSED(state); 311 312 setenv("TZ", "America/Los_Angeles", 1); 313 result = isc_time_now(&t); 314 assert_int_equal(result, ISC_R_SUCCESS); 315 316 /* check formatting: yyyy-mm-ddThh:mm:ss.sss */ 317 memset(buf, 'X', sizeof(buf)); 318 isc_time_formatISO8601Lms(&t, buf, sizeof(buf)); 319 assert_int_equal(strlen(buf), 23); 320 assert_int_equal(buf[4], '-'); 321 assert_int_equal(buf[7], '-'); 322 assert_int_equal(buf[10], 'T'); 323 assert_int_equal(buf[13], ':'); 324 assert_int_equal(buf[16], ':'); 325 assert_int_equal(buf[19], '.'); 326 327 /* check time conversion correctness */ 328 memset(buf, 'X', sizeof(buf)); 329 isc_time_settoepoch(&t); 330 isc_time_formatISO8601Lms(&t, buf, sizeof(buf)); 331 assert_string_equal(buf, "1969-12-31T16:00:00.000"); 332 333 memset(buf, 'X', sizeof(buf)); 334 isc_time_set(&t, 1450000000, 123000000); 335 isc_time_formatISO8601Lms(&t, buf, sizeof(buf)); 336 assert_string_equal(buf, "2015-12-13T01:46:40.123"); 337} 338 339/* print local time in ISO8601 with microseconds */ 340 341ISC_RUN_TEST_IMPL(isc_time_formatISO8601Lus_test) { 342 isc_result_t result; 343 isc_time_t t; 344 char buf[64]; 345 346 UNUSED(state); 347 348 setenv("TZ", "America/Los_Angeles", 1); 349 result = isc_time_now_hires(&t); 350 assert_int_equal(result, ISC_R_SUCCESS); 351 352 /* check formatting: yyyy-mm-ddThh:mm:ss.ssssss */ 353 memset(buf, 'X', sizeof(buf)); 354 isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); 355 assert_int_equal(strlen(buf), 26); 356 assert_int_equal(buf[4], '-'); 357 assert_int_equal(buf[7], '-'); 358 assert_int_equal(buf[10], 'T'); 359 assert_int_equal(buf[13], ':'); 360 assert_int_equal(buf[16], ':'); 361 assert_int_equal(buf[19], '.'); 362 363 /* check time conversion correctness */ 364 memset(buf, 'X', sizeof(buf)); 365 isc_time_settoepoch(&t); 366 isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); 367 assert_string_equal(buf, "1969-12-31T16:00:00.000000"); 368 369 memset(buf, 'X', sizeof(buf)); 370 isc_time_set(&t, 1450000000, 123456000); 371 isc_time_formatISO8601Lus(&t, buf, sizeof(buf)); 372 assert_string_equal(buf, "2015-12-13T01:46:40.123456"); 373} 374 375/* print UTC time as yyyymmddhhmmsssss */ 376 377ISC_RUN_TEST_IMPL(isc_time_formatshorttimestamp_test) { 378 isc_result_t result; 379 isc_time_t t; 380 char buf[64]; 381 382 UNUSED(state); 383 384 setenv("TZ", "America/Los_Angeles", 1); 385 result = isc_time_now(&t); 386 assert_int_equal(result, ISC_R_SUCCESS); 387 388 /* check formatting: yyyymmddhhmmsssss */ 389 memset(buf, 'X', sizeof(buf)); 390 isc_time_formatshorttimestamp(&t, buf, sizeof(buf)); 391 assert_int_equal(strlen(buf), 17); 392 393 /* check time conversion correctness */ 394 memset(buf, 'X', sizeof(buf)); 395 isc_time_settoepoch(&t); 396 isc_time_formatshorttimestamp(&t, buf, sizeof(buf)); 397 assert_string_equal(buf, "19700101000000000"); 398 399 memset(buf, 'X', sizeof(buf)); 400 isc_time_set(&t, 1450000000, 123000000); 401 isc_time_formatshorttimestamp(&t, buf, sizeof(buf)); 402 assert_string_equal(buf, "20151213094640123"); 403} 404 405ISC_TEST_LIST_START 406 407ISC_TEST_ENTRY(isc_time_add_test) 408ISC_TEST_ENTRY(isc_time_sub_test) 409ISC_TEST_ENTRY(isc_time_parsehttptimestamp_test) 410ISC_TEST_ENTRY(isc_time_formatISO8601_test) 411ISC_TEST_ENTRY(isc_time_formatISO8601ms_test) 412ISC_TEST_ENTRY(isc_time_formatISO8601us_test) 413ISC_TEST_ENTRY(isc_time_formatISO8601L_test) 414ISC_TEST_ENTRY(isc_time_formatISO8601Lms_test) 415ISC_TEST_ENTRY(isc_time_formatISO8601Lus_test) 416ISC_TEST_ENTRY(isc_time_formatshorttimestamp_test) 417 418ISC_TEST_LIST_END 419 420ISC_TEST_MAIN 421