1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2016 Joyent, Inc. 14 * Copyright 2025 Oxide Computer Company 15 */ 16 17 /* 18 * Basic tests for timespec_get(3C). 19 */ 20 21 #include <time.h> 22 #include <limits.h> 23 #include <err.h> 24 #include <stdlib.h> 25 #include <stdbool.h> 26 #include <sys/sysmacros.h> 27 28 typedef struct { 29 int gc_base; 30 clockid_t gc_clock; 31 const char *gc_desc; 32 } get_cmp_t; 33 34 static const get_cmp_t ts_gets[] = { 35 { TIME_UTC, CLOCK_REALTIME, "real time clock" }, 36 { TIME_MONOTONIC, CLOCK_HIGHRES, "highres clock" }, 37 { TIME_ACTIVE, CLOCK_PROCESS_CPUTIME_ID, "process clock" }, 38 { TIME_THREAD_ACTIVE, CLOCK_THREAD_CPUTIME_ID, "thread clock" }, 39 { TIME_THREAD_ACTIVE_USR, CLOCK_VIRTUAL, "thread (usr) clock" }, 40 }; 41 42 static const int bad_clocks[] = { 7777, -7777, INT16_MIN, CHAR_MAX }; 43 44 static int 45 timespec_cmp(const struct timespec *ls, const struct timespec *rs) 46 { 47 if (ls->tv_sec > rs->tv_sec) 48 return (-1); 49 if (ls->tv_sec < rs->tv_sec) 50 return (1); 51 if (ls->tv_nsec > rs->tv_nsec) 52 return (-1); 53 if (ls->tv_nsec > rs->tv_nsec) 54 return (-1); 55 if (ls->tv_nsec < rs->tv_nsec) 56 return (1); 57 58 return (0); 59 } 60 61 static bool 62 timespec_test_one(const char *desc, int base, clockid_t clock) 63 { 64 int ret; 65 struct timespec ts, pre, post; 66 67 if (clock_gettime(clock, &pre) != 0) { 68 warn("TEST FAILED: %s: pre clock_gettime(%d) failed", desc, 69 clock); 70 return (false); 71 } 72 73 if ((ret = timespec_get(&ts, base)) != base) { 74 warnx("TEST FAILED: %s timespec_get did not return %d: got %d", 75 desc, base, ret); 76 return (false); 77 } 78 79 if (clock_gettime(clock, &post) != 0) { 80 warn("TEST FAILED: %s: post clock_gettime(%d) failed", desc, 81 clock); 82 return (false); 83 } 84 85 if (timespec_cmp(&pre, &ts) != 1) { 86 warnx("TEST FAILED: %s: timespec_get did not come after " 87 "pre-clock_gettime: found clock 0x%lx/0x%lx vs. timespec " 88 "0x%lx/0x%lx", desc, pre.tv_sec, pre.tv_nsec, ts.tv_sec, 89 ts.tv_nsec); 90 return (false); 91 } 92 93 if (timespec_cmp(&ts, &post) != 1) { 94 warnx("TEST FAILED: %s: timespec_get did not come before " 95 "post-clock_gettime: found timespec 0x%lx/0x%lx vs. clock " 96 "0x%lx/0x%lx", desc, ts.tv_sec, ts.tv_nsec, post.tv_sec, 97 post.tv_nsec); 98 return (false); 99 } 100 101 (void) printf("TEST PASSED: %s: basic timespec_get works\n", desc); 102 return (true); 103 } 104 105 int 106 main(void) 107 { 108 int ret = EXIT_SUCCESS; 109 110 for (size_t i = 0; i < ARRAY_SIZE(ts_gets); i++) { 111 if (!timespec_test_one(ts_gets[i].gc_desc, ts_gets[i].gc_base, 112 ts_gets[i].gc_clock)) { 113 ret = EXIT_FAILURE; 114 } 115 } 116 117 for (size_t i = 0; i < ARRAY_SIZE(bad_clocks); i++) { 118 struct timespec ts; 119 120 if (timespec_getres(&ts, bad_clocks[i]) != 0) { 121 warnx("TEST FAILED: timespec_get didn't fail " 122 "with bad clock (%d)", bad_clocks[i]); 123 ret = EXIT_FAILURE; 124 } else { 125 (void) printf("TEST PASSED: timespec_get failed " 126 "with bad clock (%d)\n", bad_clocks[i]); 127 } 128 } 129 130 if (ret == EXIT_SUCCESS) { 131 (void) printf("All tests passed successfully\n"); 132 } 133 134 return (ret); 135 } 136