1 /* $NetBSD: isc.h,v 1.6 2026/04/08 00:16:17 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 #pragma once 17 18 /*! \file */ 19 20 #include <inttypes.h> 21 #include <stdbool.h> 22 23 #include <isc/buffer.h> 24 #include <isc/commandline.h> 25 #include <isc/hash.h> 26 #include <isc/log.h> 27 #include <isc/mem.h> 28 #include <isc/netmgr.h> 29 #include <isc/result.h> 30 #include <isc/string.h> 31 #include <isc/timer.h> 32 #include <isc/util.h> 33 #include <isc/uv.h> 34 35 extern isc_mem_t *mctx; 36 extern isc_log_t *lctx; 37 extern isc_loop_t *mainloop; 38 extern isc_loopmgr_t *loopmgr; 39 extern isc_nm_t *netmgr; 40 extern int ncpus; 41 extern unsigned int workers; 42 extern bool debug; 43 44 int 45 setup_mctx(void **state); 46 int 47 teardown_mctx(void **state); 48 49 int 50 setup_workers(void **state); 51 52 int 53 setup_loopmgr(void **state); 54 int 55 teardown_loopmgr(void **state); 56 57 int 58 setup_netmgr(void **state); 59 int 60 teardown_netmgr(void **state); 61 62 int 63 setup_managers(void **state); 64 int 65 teardown_managers(void **state); 66 67 #ifndef TESTS_DIR 68 #define TESTS_DIR "./" 69 #endif 70 71 /* cmocka<2.0.0 compatibility */ 72 #ifndef assert_int_in_range 73 #define assert_int_in_range(value, min, max) \ 74 assert_in_range((value), (min), (max)) 75 #endif 76 #ifndef assert_uint_in_range 77 #define assert_uint_in_range(value, min, max) \ 78 assert_in_range((value), (min), (max)) 79 #endif 80 81 /* clang-format off */ 82 /* Copied from cmocka */ 83 #define ISC_TEST_ENTRY(name) \ 84 { #name, run_test_##name, NULL, NULL, NULL }, 85 #define ISC_TEST_ENTRY_SETUP(name) \ 86 { #name, run_test_##name, setup_test_##name, NULL, NULL }, 87 #define ISC_TEST_ENTRY_TEARDOWN(name) \ 88 { #name, run_test_##name, NULL, teardown_test_##name, NULL }, 89 #define ISC_TEST_ENTRY_SETUP_TEARDOWN(name) \ 90 { #name, run_test_##name, setup_test_##name, teardown_test_##name, NULL }, 91 #define ISC_TEST_ENTRY_CUSTOM(name, setup, teardown) \ 92 { #name, run_test_##name, setup, teardown, NULL }, 93 /* clang-format on */ 94 95 #define ISC_SETUP_TEST_DECLARE(name) \ 96 int setup_test_##name(void **state ISC_ATTR_UNUSED); 97 98 #define ISC_RUN_TEST_DECLARE(name) \ 99 static void run_test_##name(void **state ISC_ATTR_UNUSED); 100 101 #define ISC_TEARDOWN_TEST_DECLARE(name) \ 102 int teardown_test_##name(void **state ISC_ATTR_UNUSED) 103 104 #define ISC_LOOP_TEST_CUSTOM_DECLARE(name, setup, teardown) \ 105 void run_test_##name(void **state ISC_ATTR_UNUSED); \ 106 void loop_test_##name(void *arg ISC_ATTR_UNUSED); 107 108 #define ISC_LOOP_TEST_DECLARE(name) \ 109 ISC_LOOP_TEST_CUSTOM_DECLARE(name, NULL, NULL) 110 111 #define ISC_LOOP_TEST_SETUP_DECLARE(name) \ 112 ISC_LOOP_TEST_CUSTOM_DECLARE(name, setup_loop_##name, NULL) 113 114 #define ISC_LOOP_TEST_SETUP_TEARDOWN_DECLARE(name) \ 115 ISC_LOOP_TEST_CUSTOM_DECLARE(name, setup_loop_##name, \ 116 teardown_loop_##name) 117 118 #define ISC_LOOP_TEST_TEARDOWN_DECLARE(name) \ 119 ISC_LOOP_TEST_CUSTOM_DECLARE(name, NULL, teardown_loop_##name) 120 121 #define ISC_LOOP_SETUP_DECLARE(name) \ 122 void setup_loop_##name(void *arg ISC_ATTR_UNUSED); 123 124 #define ISC_SETUP_TEST_IMPL(name) \ 125 int setup_test_##name(void **state ISC_ATTR_UNUSED); \ 126 int setup_test_##name(void **state ISC_ATTR_UNUSED) 127 128 #define ISC_RUN_TEST_IMPL(name) \ 129 static void run_test_##name(void **state ISC_ATTR_UNUSED); \ 130 static void run_test_##name(void **state ISC_ATTR_UNUSED) 131 132 #define ISC_TEARDOWN_TEST_IMPL(name) \ 133 int teardown_test_##name(void **state ISC_ATTR_UNUSED); \ 134 int teardown_test_##name(void **state ISC_ATTR_UNUSED) 135 136 #define ISC_TEST_LIST_START const struct CMUnitTest tests[] = { 137 #define ISC_TEST_LIST_END \ 138 } \ 139 ; 140 141 #define ISC_LOOP_TEST_CUSTOM_IMPL(name, setup, teardown) \ 142 static void run_test_##name(void **state ISC_ATTR_UNUSED); \ 143 static void loop_test_##name(void *arg ISC_ATTR_UNUSED); \ 144 static void run_test_##name(void **state ISC_ATTR_UNUSED) { \ 145 isc_job_cb setup_loop = setup; \ 146 isc_job_cb teardown_loop = teardown; \ 147 if (setup_loop != NULL) { \ 148 isc_loop_setup(mainloop, setup_loop, state); \ 149 } \ 150 if (teardown_loop != NULL) { \ 151 isc_loop_teardown(mainloop, teardown_loop, state); \ 152 } \ 153 isc_loop_setup(mainloop, loop_test_##name, state); \ 154 isc_loopmgr_run(loopmgr); \ 155 } \ 156 static void loop_test_##name(void *arg ISC_ATTR_UNUSED) 157 158 #define ISC_LOOP_TEST_IMPL(name) ISC_LOOP_TEST_CUSTOM_IMPL(name, NULL, NULL) 159 160 #define ISC_LOOP_TEST_SETUP_IMPL(name) \ 161 ISC_LOOP_TEST_CUSTOM_IMPL(name, setup_loop_##name, NULL) 162 163 #define ISC_LOOP_TEST_SETUP_TEARDOWN_IMPL(name) \ 164 ISC_LOOP_TEST_CUSTOM_IMPL(name, setup_loop_##name, teardown_loop_##name) 165 166 #define ISC_LOOP_TEST_TEARDOWN_IMPL(name) \ 167 ISC_LOOP_TEST_CUSTOM_IMPL(name, NULL, teardown_loop_##name) 168 169 #define ISC_LOOP_SETUP_IMPL(name) \ 170 void setup_loop_##name(void *arg ISC_ATTR_UNUSED); \ 171 void setup_loop_##name(void *arg ISC_ATTR_UNUSED) 172 173 #define ISC_LOOP_TEARDOWN_IMPL(name) \ 174 void teardown_loop_##name(void *arg ISC_ATTR_UNUSED); \ 175 void teardown_loop_##name(void *arg ISC_ATTR_UNUSED) 176 177 #define ISC_TEST_DECLARE(name) void run_test_##name(void **state); 178 179 #define ISC_TEST_LIST_START const struct CMUnitTest tests[] = { 180 #define ISC_TEST_LIST_END \ 181 } \ 182 ; 183 184 #define ISC_TEST_MAIN ISC_TEST_MAIN_CUSTOM(NULL, NULL) 185 186 #define ISC_TEST_MAIN_CUSTOM(setup, teardown) \ 187 int main(int argc, char **argv) { \ 188 int c, r; \ 189 size_t i, j; \ 190 struct CMUnitTest selected[ARRAY_SIZE(tests)]; \ 191 \ 192 signal(SIGPIPE, SIG_IGN); \ 193 \ 194 memset(selected, 0, sizeof(selected)); \ 195 \ 196 setup_mctx(NULL); \ 197 setup_workers(NULL); \ 198 \ 199 while ((c = isc_commandline_parse(argc, argv, "dlt:")) != \ 200 -1) { \ 201 switch (c) { \ 202 case 'd': \ 203 debug = true; \ 204 break; \ 205 case 'l': \ 206 for (i = 0; \ 207 i < (sizeof(tests) / sizeof(tests[0])); \ 208 i++) \ 209 { \ 210 if (tests[i].name != NULL) { \ 211 fprintf(stdout, "%s\n", \ 212 tests[i].name); \ 213 } \ 214 } \ 215 return (0); \ 216 case 't': \ 217 for (i = 0; i < ARRAY_SIZE(tests) && \ 218 tests[i].name != NULL; \ 219 i++) \ 220 { \ 221 if (strcmp(tests[i].name, \ 222 isc_commandline_argument) != \ 223 0) \ 224 { \ 225 continue; \ 226 } \ 227 for (j = 0; \ 228 j < ARRAY_SIZE(selected) && \ 229 selected[j].name != NULL; \ 230 j++) \ 231 { \ 232 if (strcmp(tests[j].name, \ 233 isc_commandline_argument) == \ 234 0) \ 235 { \ 236 break; \ 237 } \ 238 } \ 239 if (j < ARRAY_SIZE(selected) && \ 240 selected[j].name == NULL) \ 241 { \ 242 selected[j] = tests[i]; \ 243 break; \ 244 } \ 245 } \ 246 if (i == ARRAY_SIZE(tests)) { \ 247 fprintf(stderr, "unknown test '%s'\n", \ 248 isc_commandline_argument); \ 249 exit(1); \ 250 } \ 251 break; \ 252 default: \ 253 fprintf(stderr, "Usage: %s [-dl] [-t test]\n", \ 254 argv[0]); \ 255 exit(1); \ 256 } \ 257 } \ 258 \ 259 if (selected[0].name != NULL) { \ 260 r = cmocka_run_group_tests(selected, setup, teardown); \ 261 } else { \ 262 r = cmocka_run_group_tests(tests, setup, teardown); \ 263 } \ 264 \ 265 isc_mem_destroy(&mctx); \ 266 \ 267 return (r); \ 268 } 269