1 /* $NetBSD: resconf_test.c,v 1.3 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 #if HAVE_CMOCKA 17 18 #include <inttypes.h> 19 #include <sched.h> /* IWYU pragma: keep */ 20 #include <setjmp.h> 21 #include <stdarg.h> 22 #include <stddef.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 #define UNIT_TESTING 29 #include <cmocka.h> 30 31 #include <isc/mem.h> 32 #include <isc/util.h> 33 34 #include <irs/resconf.h> 35 36 static isc_mem_t *mctx = NULL; 37 38 static void 39 setup_test(void) { 40 isc_mem_create(&mctx); 41 42 /* 43 * the caller might run from another directory, but tests 44 * that access test data files must first chdir to the proper 45 * location. 46 */ 47 assert_return_code(chdir(TESTS_DIR), 0); 48 } 49 50 static isc_result_t 51 check_number(unsigned int n, unsigned int expected) { 52 return (n == expected) ? ISC_R_SUCCESS : ISC_R_BADNUMBER; 53 } 54 55 static isc_result_t 56 check_attempts(irs_resconf_t *resconf) { 57 return check_number(irs_resconf_getattempts(resconf), 4); 58 } 59 60 static isc_result_t 61 check_timeout(irs_resconf_t *resconf) { 62 return check_number(irs_resconf_gettimeout(resconf), 1); 63 } 64 65 static isc_result_t 66 check_ndots(irs_resconf_t *resconf) { 67 return check_number(irs_resconf_getndots(resconf), 2); 68 } 69 70 static isc_result_t 71 check_options(irs_resconf_t *resconf) { 72 if (irs_resconf_getattempts(resconf) != 3) { 73 return ISC_R_BADNUMBER; /* default value only */ 74 } 75 76 if (irs_resconf_getndots(resconf) != 2) { 77 return ISC_R_BADNUMBER; 78 } 79 80 if (irs_resconf_gettimeout(resconf) != 1) { 81 return ISC_R_BADNUMBER; 82 } 83 84 return ISC_R_SUCCESS; 85 } 86 87 /* test irs_resconf_load() */ 88 static void 89 irs_resconf_load_test(void **state) { 90 isc_result_t result; 91 irs_resconf_t *resconf = NULL; 92 unsigned int i; 93 struct { 94 const char *file; 95 isc_result_t loadres; 96 isc_result_t (*check)(irs_resconf_t *resconf); 97 isc_result_t checkres; 98 } tests[] = { 99 { "testdata/domain.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS }, 100 { "testdata/nameserver-v4.conf", ISC_R_SUCCESS, NULL, 101 ISC_R_SUCCESS }, 102 { "testdata/nameserver-v6.conf", ISC_R_SUCCESS, NULL, 103 ISC_R_SUCCESS }, 104 { "testdata/nameserver-v6-scoped.conf", ISC_R_SUCCESS, NULL, 105 ISC_R_SUCCESS }, 106 { "testdata/options-attempts.conf", ISC_R_SUCCESS, 107 check_attempts, ISC_R_SUCCESS }, 108 { "testdata/options-debug.conf", ISC_R_SUCCESS, NULL, 109 ISC_R_SUCCESS }, 110 { "testdata/options-ndots.conf", ISC_R_SUCCESS, check_ndots, 111 ISC_R_SUCCESS }, 112 { "testdata/options-timeout.conf", ISC_R_SUCCESS, check_timeout, 113 ISC_R_SUCCESS }, 114 { "testdata/options-unknown.conf", ISC_R_SUCCESS, NULL, 115 ISC_R_SUCCESS }, 116 { "testdata/options.conf", ISC_R_SUCCESS, check_options, 117 ISC_R_SUCCESS }, 118 { "testdata/options-bad-ndots.conf", ISC_R_RANGE, NULL, 119 ISC_R_SUCCESS }, 120 { "testdata/options-empty.conf", ISC_R_UNEXPECTEDEND, NULL, 121 ISC_R_SUCCESS }, 122 { "testdata/port.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS }, 123 { "testdata/resolv.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS }, 124 { "testdata/search.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS }, 125 { "testdata/sortlist-v4.conf", ISC_R_SUCCESS, NULL, 126 ISC_R_SUCCESS }, 127 { "testdata/timeout.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS }, 128 { "testdata/unknown.conf", ISC_R_SUCCESS, NULL, ISC_R_SUCCESS } 129 }; 130 131 UNUSED(state); 132 133 setup_test(); 134 135 for (i = 0; i < sizeof(tests) / sizeof(tests[1]); i++) { 136 result = irs_resconf_load(mctx, tests[i].file, &resconf); 137 if (result != tests[i].loadres) { 138 fail_msg("# unexpected result %s loading %s", 139 isc_result_totext(result), tests[i].file); 140 } 141 142 if (result == ISC_R_SUCCESS && resconf == NULL) { 143 fail_msg("# NULL on success loading %s", tests[i].file); 144 } else if (result != ISC_R_SUCCESS && resconf != NULL) { 145 fail_msg("# non-NULL on failure loading %s", 146 tests[i].file); 147 } 148 149 if (resconf != NULL && tests[i].check != NULL) { 150 result = (tests[i].check)(resconf); 151 if (result != tests[i].checkres) { 152 fail_msg("# unexpected result %s loading %s", 153 isc_result_totext(result), 154 tests[i].file); 155 } 156 } 157 if (resconf != NULL) { 158 irs_resconf_destroy(&resconf); 159 } 160 } 161 162 isc_mem_detach(&mctx); 163 } 164 165 int 166 main(void) { 167 const struct CMUnitTest tests[] = { 168 cmocka_unit_test(irs_resconf_load_test), 169 }; 170 171 return cmocka_run_group_tests(tests, NULL, NULL); 172 } 173 174 #else /* HAVE_CMOCKA */ 175 176 #include <stdio.h> 177 178 int 179 main(void) { 180 printf("1..0 # Skipped: cmocka not available\n"); 181 return SKIPPED_TEST_EXIT_CODE; 182 } 183 184 #endif /* if HAVE_CMOCKA */ 185