1 /* $NetBSD: isc.h,v 1.4 2025/01/26 16:25:49 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 /* clang-format off */ 72 /* Copied from cmocka */ 73 #define ISC_TEST_ENTRY(name) \ 74 { #name, run_test_##name, NULL, NULL, NULL }, 75 #define ISC_TEST_ENTRY_SETUP(name) \ 76 { #name, run_test_##name, setup_test_##name, NULL, NULL }, 77 #define ISC_TEST_ENTRY_TEARDOWN(name) \ 78 { #name, run_test_##name, NULL, teardown_test_##name, NULL }, 79 #define ISC_TEST_ENTRY_SETUP_TEARDOWN(name) \ 80 { #name, run_test_##name, setup_test_##name, teardown_test_##name, NULL }, 81 #define ISC_TEST_ENTRY_CUSTOM(name, setup, teardown) \ 82 { #name, run_test_##name, setup, teardown, NULL }, 83 /* clang-format on */ 84 85 #define ISC_SETUP_TEST_DECLARE(name) \ 86 int setup_test_##name(void **state ISC_ATTR_UNUSED); 87 88 #define ISC_RUN_TEST_DECLARE(name) \ 89 void run_test_##name(void **state ISC_ATTR_UNUSED); 90 91 #define ISC_TEARDOWN_TEST_DECLARE(name) \ 92 int teardown_test_##name(void **state ISC_ATTR_UNUSED) 93 94 #define ISC_LOOP_TEST_CUSTOM_DECLARE(name, setup, teardown) \ 95 void run_test_##name(void **state ISC_ATTR_UNUSED); \ 96 void loop_test_##name(void *arg ISC_ATTR_UNUSED); 97 98 #define ISC_LOOP_TEST_DECLARE(name) \ 99 ISC_LOOP_TEST_CUSTOM_DECLARE(name, NULL, NULL) 100 101 #define ISC_LOOP_TEST_SETUP_DECLARE(name) \ 102 ISC_LOOP_TEST_CUSTOM_DECLARE(name, setup_loop_##name, NULL) 103 104 #define ISC_LOOP_TEST_SETUP_TEARDOWN_DECLARE(name) \ 105 ISC_LOOP_TEST_CUSTOM_DECLARE(name, setup_loop_##name, \ 106 teardown_loop_##name) 107 108 #define ISC_LOOP_TEST_TEARDOWN_DECLARE(name) \ 109 ISC_LOOP_TEST_CUSTOM_DECLARE(name, NULL, teardown_loop_##name) 110 111 #define ISC_LOOP_SETUP_DECLARE(name) \ 112 void setup_loop_##name(void *arg ISC_ATTR_UNUSED); 113 114 #define ISC_SETUP_TEST_IMPL(name) \ 115 int setup_test_##name(void **state ISC_ATTR_UNUSED); \ 116 int setup_test_##name(void **state ISC_ATTR_UNUSED) 117 118 #define ISC_RUN_TEST_IMPL(name) \ 119 void run_test_##name(void **state ISC_ATTR_UNUSED); \ 120 void run_test_##name(void **state ISC_ATTR_UNUSED) 121 122 #define ISC_TEARDOWN_TEST_IMPL(name) \ 123 int teardown_test_##name(void **state ISC_ATTR_UNUSED); \ 124 int teardown_test_##name(void **state ISC_ATTR_UNUSED) 125 126 #define ISC_TEST_LIST_START const struct CMUnitTest tests[] = { 127 #define ISC_TEST_LIST_END \ 128 } \ 129 ; 130 131 #define ISC_LOOP_TEST_CUSTOM_IMPL(name, setup, teardown) \ 132 void run_test_##name(void **state ISC_ATTR_UNUSED); \ 133 void loop_test_##name(void *arg ISC_ATTR_UNUSED); \ 134 void run_test_##name(void **state ISC_ATTR_UNUSED) { \ 135 isc_job_cb setup_loop = setup; \ 136 isc_job_cb teardown_loop = teardown; \ 137 if (setup_loop != NULL) { \ 138 isc_loop_setup(mainloop, setup_loop, state); \ 139 } \ 140 if (teardown_loop != NULL) { \ 141 isc_loop_teardown(mainloop, teardown_loop, state); \ 142 } \ 143 isc_loop_setup(mainloop, loop_test_##name, state); \ 144 isc_loopmgr_run(loopmgr); \ 145 } \ 146 void loop_test_##name(void *arg ISC_ATTR_UNUSED) 147 148 #define ISC_LOOP_TEST_IMPL(name) ISC_LOOP_TEST_CUSTOM_IMPL(name, NULL, NULL) 149 150 #define ISC_LOOP_TEST_SETUP_IMPL(name) \ 151 ISC_LOOP_TEST_CUSTOM_IMPL(name, setup_loop_##name, NULL) 152 153 #define ISC_LOOP_TEST_SETUP_TEARDOWN_IMPL(name) \ 154 ISC_LOOP_TEST_CUSTOM_IMPL(name, setup_loop_##name, teardown_loop_##name) 155 156 #define ISC_LOOP_TEST_TEARDOWN_IMPL(name) \ 157 ISC_LOOP_TEST_CUSTOM_IMPL(name, NULL, teardown_loop_##name) 158 159 #define ISC_LOOP_SETUP_IMPL(name) \ 160 void setup_loop_##name(void *arg ISC_ATTR_UNUSED); \ 161 void setup_loop_##name(void *arg ISC_ATTR_UNUSED) 162 163 #define ISC_LOOP_TEARDOWN_IMPL(name) \ 164 void teardown_loop_##name(void *arg ISC_ATTR_UNUSED); \ 165 void teardown_loop_##name(void *arg ISC_ATTR_UNUSED) 166 167 #define ISC_TEST_DECLARE(name) void run_test_##name(void **state); 168 169 #define ISC_TEST_LIST_START const struct CMUnitTest tests[] = { 170 #define ISC_TEST_LIST_END \ 171 } \ 172 ; 173 174 #define ISC_TEST_MAIN ISC_TEST_MAIN_CUSTOM(NULL, NULL) 175 176 #define ISC_TEST_MAIN_CUSTOM(setup, teardown) \ 177 int main(int argc, char **argv) { \ 178 int c, r; \ 179 size_t i, j; \ 180 struct CMUnitTest selected[ARRAY_SIZE(tests)]; \ 181 \ 182 signal(SIGPIPE, SIG_IGN); \ 183 \ 184 memset(selected, 0, sizeof(selected)); \ 185 \ 186 setup_mctx(NULL); \ 187 setup_workers(NULL); \ 188 \ 189 while ((c = isc_commandline_parse(argc, argv, "dlt:")) != -1) \ 190 { \ 191 switch (c) { \ 192 case 'd': \ 193 debug = true; \ 194 break; \ 195 case 'l': \ 196 for (i = 0; \ 197 i < (sizeof(tests) / sizeof(tests[0])); \ 198 i++) \ 199 { \ 200 if (tests[i].name != NULL) { \ 201 fprintf(stdout, "%s\n", \ 202 tests[i].name); \ 203 } \ 204 } \ 205 return (0); \ 206 case 't': \ 207 for (i = 0; i < ARRAY_SIZE(tests) && \ 208 tests[i].name != NULL; \ 209 i++) \ 210 { \ 211 if (strcmp(tests[i].name, \ 212 isc_commandline_argument) != \ 213 0) \ 214 { \ 215 continue; \ 216 } \ 217 for (j = 0; \ 218 j < ARRAY_SIZE(selected) && \ 219 selected[j].name != NULL; \ 220 j++) \ 221 { \ 222 if (strcmp(tests[j].name, \ 223 isc_commandline_argument) == \ 224 0) \ 225 { \ 226 break; \ 227 } \ 228 } \ 229 if (j < ARRAY_SIZE(selected) && \ 230 selected[j].name == NULL) \ 231 { \ 232 selected[j] = tests[i]; \ 233 break; \ 234 } \ 235 } \ 236 if (i == ARRAY_SIZE(tests)) { \ 237 fprintf(stderr, "unknown test '%s'\n", \ 238 isc_commandline_argument); \ 239 exit(1); \ 240 } \ 241 break; \ 242 default: \ 243 fprintf(stderr, "Usage: %s [-dl] [-t test]\n", \ 244 argv[0]); \ 245 exit(1); \ 246 } \ 247 } \ 248 \ 249 if (selected[0].name != NULL) { \ 250 r = cmocka_run_group_tests(selected, setup, teardown); \ 251 } else { \ 252 r = cmocka_run_group_tests(tests, setup, teardown); \ 253 } \ 254 \ 255 isc_mem_destroy(&mctx); \ 256 \ 257 return (r); \ 258 } 259