1 /*
2  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * SPDX-License-Identifier: MPL-2.0
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9  *
10  * See the COPYRIGHT file distributed with this work for additional
11  * information regarding copyright ownership.
12  */
13 
14 #if HAVE_CMOCKA
15 
16 #include <sched.h> /* IWYU pragma: keep */
17 #include <setjmp.h>
18 #include <stdarg.h>
19 #include <stddef.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 
23 #define UNIT_TESTING
24 #include <cmocka.h>
25 
26 #include <isc/app.h>
27 #include <isc/buffer.h>
28 #include <isc/print.h>
29 #include <isc/socket.h>
30 #include <isc/task.h>
31 #include <isc/timer.h>
32 #include <isc/util.h>
33 
34 #include <dns/dispatch.h>
35 #include <dns/name.h>
36 #include <dns/resolver.h>
37 #include <dns/view.h>
38 
39 #include "dnstest.h"
40 
41 static dns_dispatchmgr_t *dispatchmgr = NULL;
42 static dns_dispatch_t *dispatch = NULL;
43 static dns_view_t *view = NULL;
44 
45 static int
_setup(void ** state)46 _setup(void **state) {
47 	isc_result_t result;
48 	isc_sockaddr_t local;
49 
50 	UNUSED(state);
51 
52 	result = dns_test_begin(NULL, true);
53 	assert_int_equal(result, ISC_R_SUCCESS);
54 
55 	result = dns_dispatchmgr_create(dt_mctx, &dispatchmgr);
56 	assert_int_equal(result, ISC_R_SUCCESS);
57 
58 	result = dns_test_makeview("view", &view);
59 	assert_int_equal(result, ISC_R_SUCCESS);
60 
61 	isc_sockaddr_any(&local);
62 	result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr, &local,
63 				     4096, 100, 100, 100, 500, 0, 0, &dispatch);
64 	assert_int_equal(result, ISC_R_SUCCESS);
65 
66 	return (0);
67 }
68 
69 static int
_teardown(void ** state)70 _teardown(void **state) {
71 	UNUSED(state);
72 
73 	dns_dispatch_detach(&dispatch);
74 	dns_view_detach(&view);
75 	dns_dispatchmgr_destroy(&dispatchmgr);
76 	dns_test_end();
77 
78 	return (0);
79 }
80 
81 static void
mkres(dns_resolver_t ** resolverp)82 mkres(dns_resolver_t **resolverp) {
83 	isc_result_t result;
84 
85 	result = dns_resolver_create(view, taskmgr, 1, 1, socketmgr, timermgr,
86 				     0, dispatchmgr, dispatch, NULL, resolverp);
87 	assert_int_equal(result, ISC_R_SUCCESS);
88 }
89 
90 static void
destroy_resolver(dns_resolver_t ** resolverp)91 destroy_resolver(dns_resolver_t **resolverp) {
92 	dns_resolver_shutdown(*resolverp);
93 	dns_resolver_detach(resolverp);
94 }
95 
96 /* dns_resolver_create */
97 static void
create_test(void ** state)98 create_test(void **state) {
99 	dns_resolver_t *resolver = NULL;
100 
101 	UNUSED(state);
102 
103 	mkres(&resolver);
104 	destroy_resolver(&resolver);
105 }
106 
107 /* dns_resolver_gettimeout */
108 static void
gettimeout_test(void ** state)109 gettimeout_test(void **state) {
110 	dns_resolver_t *resolver = NULL;
111 	unsigned int timeout;
112 
113 	UNUSED(state);
114 
115 	mkres(&resolver);
116 
117 	timeout = dns_resolver_gettimeout(resolver);
118 	assert_true(timeout > 0);
119 
120 	destroy_resolver(&resolver);
121 }
122 
123 /* dns_resolver_settimeout */
124 static void
settimeout_test(void ** state)125 settimeout_test(void **state) {
126 	dns_resolver_t *resolver = NULL;
127 	unsigned int default_timeout, timeout;
128 
129 	UNUSED(state);
130 
131 	mkres(&resolver);
132 
133 	default_timeout = dns_resolver_gettimeout(resolver);
134 	dns_resolver_settimeout(resolver, default_timeout + 1);
135 	timeout = dns_resolver_gettimeout(resolver);
136 	assert_true(timeout == default_timeout + 1);
137 
138 	destroy_resolver(&resolver);
139 }
140 
141 /* dns_resolver_settimeout */
142 static void
settimeout_default_test(void ** state)143 settimeout_default_test(void **state) {
144 	dns_resolver_t *resolver = NULL;
145 	unsigned int default_timeout, timeout;
146 
147 	UNUSED(state);
148 
149 	mkres(&resolver);
150 
151 	default_timeout = dns_resolver_gettimeout(resolver);
152 	dns_resolver_settimeout(resolver, default_timeout + 100);
153 
154 	timeout = dns_resolver_gettimeout(resolver);
155 	assert_int_equal(timeout, default_timeout + 100);
156 
157 	dns_resolver_settimeout(resolver, 0);
158 	timeout = dns_resolver_gettimeout(resolver);
159 	assert_int_equal(timeout, default_timeout);
160 
161 	destroy_resolver(&resolver);
162 }
163 
164 /* dns_resolver_settimeout below minimum */
165 static void
settimeout_belowmin_test(void ** state)166 settimeout_belowmin_test(void **state) {
167 	dns_resolver_t *resolver = NULL;
168 	unsigned int default_timeout, timeout;
169 
170 	UNUSED(state);
171 
172 	mkres(&resolver);
173 
174 	default_timeout = dns_resolver_gettimeout(resolver);
175 	dns_resolver_settimeout(resolver, 9000);
176 
177 	timeout = dns_resolver_gettimeout(resolver);
178 	assert_int_equal(timeout, default_timeout);
179 
180 	destroy_resolver(&resolver);
181 }
182 
183 /* dns_resolver_settimeout over maximum */
184 static void
settimeout_overmax_test(void ** state)185 settimeout_overmax_test(void **state) {
186 	dns_resolver_t *resolver = NULL;
187 	unsigned int timeout;
188 
189 	UNUSED(state);
190 
191 	mkres(&resolver);
192 
193 	dns_resolver_settimeout(resolver, 4000000);
194 	timeout = dns_resolver_gettimeout(resolver);
195 	assert_in_range(timeout, 0, 3999999);
196 	destroy_resolver(&resolver);
197 }
198 
199 int
main(void)200 main(void) {
201 	const struct CMUnitTest tests[] = {
202 		cmocka_unit_test_setup_teardown(create_test, _setup, _teardown),
203 		cmocka_unit_test_setup_teardown(gettimeout_test, _setup,
204 						_teardown),
205 		cmocka_unit_test_setup_teardown(settimeout_test, _setup,
206 						_teardown),
207 		cmocka_unit_test_setup_teardown(settimeout_default_test, _setup,
208 						_teardown),
209 		cmocka_unit_test_setup_teardown(settimeout_belowmin_test,
210 						_setup, _teardown),
211 		cmocka_unit_test_setup_teardown(settimeout_overmax_test, _setup,
212 						_teardown),
213 	};
214 
215 	return (cmocka_run_group_tests(tests, NULL, NULL));
216 }
217 
218 #else /* HAVE_CMOCKA */
219 
220 #include <stdio.h>
221 
222 int
main(void)223 main(void) {
224 	printf("1..0 # Skipped: cmocka not available\n");
225 	return (SKIPPED_TEST_EXIT_CODE);
226 }
227 
228 #endif /* if HAVE_CMOCKA */
229