Annotation of src/external/mpl/bind/dist/lib/dns/tests/dispatch_test.c, Revision 1.4.4.1
1.4.4.1 ! martin 1: /* $NetBSD: dispatch_test.c,v 1.5 2019/09/05 19:32:58 christos Exp $ */
1.1 christos 2:
3: /*
4: * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
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 http://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: #include <config.h>
15:
1.3 christos 16: #if HAVE_CMOCKA
1.1 christos 17:
1.3 christos 18: #include <stdarg.h>
19: #include <stddef.h>
20: #include <setjmp.h>
21:
22: #include <inttypes.h>
1.4.4.1 ! martin 23: #include <sched.h> /* IWYU pragma: keep */
1.3 christos 24: #include <stdbool.h>
25: #include <stdlib.h>
26: #include <string.h>
1.1 christos 27: #include <unistd.h>
28:
1.3 christos 29: #define UNIT_TESTING
30: #include <cmocka.h>
31:
1.1 christos 32: #include <isc/app.h>
33: #include <isc/buffer.h>
34: #include <isc/socket.h>
35: #include <isc/task.h>
36: #include <isc/timer.h>
1.3 christos 37: #include <isc/util.h>
1.1 christos 38:
39: #include <dns/dispatch.h>
40: #include <dns/name.h>
41: #include <dns/view.h>
42:
43: #include "dnstest.h"
44:
45: dns_dispatchmgr_t *dispatchmgr = NULL;
46: dns_dispatchset_t *dset = NULL;
47:
1.3 christos 48: static int
49: _setup(void **state) {
50: isc_result_t result;
51:
52: UNUSED(state);
53:
54: result = dns_test_begin(NULL, true);
55: assert_int_equal(result, ISC_R_SUCCESS);
56:
57: return (0);
58: }
59:
60: static int
61: _teardown(void **state) {
62: UNUSED(state);
63:
64: dns_test_end();
65:
66: return (0);
67: }
68:
1.1 christos 69: static isc_result_t
70: make_dispatchset(unsigned int ndisps) {
71: isc_result_t result;
72: isc_sockaddr_t any;
73: unsigned int attrs;
74: dns_dispatch_t *disp = NULL;
75:
1.3 christos 76: result = dns_dispatchmgr_create(mctx, &dispatchmgr);
1.1 christos 77: if (result != ISC_R_SUCCESS)
78: return (result);
79:
80: isc_sockaddr_any(&any);
81: attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
82: result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
83: &any, 512, 6, 1024, 17, 19, attrs,
84: attrs, &disp);
85: if (result != ISC_R_SUCCESS)
86: return (result);
87:
88: result = dns_dispatchset_create(mctx, socketmgr, taskmgr, disp,
89: &dset, ndisps);
90: dns_dispatch_detach(&disp);
91:
92: return (result);
93: }
94:
95: static void
1.3 christos 96: reset(void) {
97: if (dset != NULL) {
1.1 christos 98: dns_dispatchset_destroy(&dset);
1.3 christos 99: }
100: if (dispatchmgr != NULL) {
1.1 christos 101: dns_dispatchmgr_destroy(&dispatchmgr);
1.3 christos 102: }
1.1 christos 103: }
104:
1.3 christos 105: /* create dispatch set */
106: static void
107: dispatchset_create(void **state) {
1.1 christos 108: isc_result_t result;
109:
1.3 christos 110: UNUSED(state);
1.1 christos 111:
112: result = make_dispatchset(1);
1.3 christos 113: assert_int_equal(result, ISC_R_SUCCESS);
114: reset();
1.1 christos 115:
116: result = make_dispatchset(10);
1.3 christos 117: assert_int_equal(result, ISC_R_SUCCESS);
118: reset();
1.1 christos 119: }
120:
1.3 christos 121: /* test dispatch set round-robin */
122: static void
123: dispatchset_get(void **state) {
1.1 christos 124: isc_result_t result;
125: dns_dispatch_t *d1, *d2, *d3, *d4, *d5;
126:
1.3 christos 127: UNUSED(state);
1.1 christos 128:
129: result = make_dispatchset(1);
1.3 christos 130: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 131:
132: d1 = dns_dispatchset_get(dset);
133: d2 = dns_dispatchset_get(dset);
134: d3 = dns_dispatchset_get(dset);
135: d4 = dns_dispatchset_get(dset);
136: d5 = dns_dispatchset_get(dset);
137:
1.3 christos 138: assert_int_equal(d1, d2);
139: assert_int_equal(d2, d3);
140: assert_int_equal(d3, d4);
141: assert_int_equal(d4, d5);
1.1 christos 142:
1.3 christos 143: reset();
1.1 christos 144:
145: result = make_dispatchset(4);
1.3 christos 146: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 147:
148: d1 = dns_dispatchset_get(dset);
149: d2 = dns_dispatchset_get(dset);
150: d3 = dns_dispatchset_get(dset);
151: d4 = dns_dispatchset_get(dset);
152: d5 = dns_dispatchset_get(dset);
153:
1.3 christos 154: assert_int_equal(d1, d5);
155: assert_true(d1 != d2);
156: assert_true(d2 != d3);
157: assert_true(d3 != d4);
158: assert_true(d4 != d5);
1.1 christos 159:
1.3 christos 160: reset();
1.1 christos 161: }
162:
163: static void
164: senddone(isc_task_t *task, isc_event_t *event) {
165: isc_socket_t *sock = event->ev_arg;
166:
167: UNUSED(task);
168:
169: isc_socket_detach(&sock);
170: isc_event_free(&event);
171: }
172:
173: static void
174: nameserver(isc_task_t *task, isc_event_t *event) {
175: isc_result_t result;
176: isc_region_t region;
177: isc_socket_t *dummy;
178: isc_socket_t *sock = event->ev_arg;
179: isc_socketevent_t *ev = (isc_socketevent_t *)event;
180: static unsigned char buf1[16];
181: static unsigned char buf2[16];
182:
183: memmove(buf1, ev->region.base, 12);
184: memset(buf1 + 12, 0, 4);
185: buf1[2] |= 0x80; /* qr=1 */
186:
187: memmove(buf2, ev->region.base, 12);
188: memset(buf2 + 12, 1, 4);
189: buf2[2] |= 0x80; /* qr=1 */
190:
191: /*
192: * send message to be discarded.
193: */
194: region.base = buf1;
195: region.length = sizeof(buf1);
196: dummy = NULL;
197: isc_socket_attach(sock, &dummy);
198: result = isc_socket_sendto(sock, ®ion, task, senddone, sock,
199: &ev->address, NULL);
200: if (result != ISC_R_SUCCESS)
201: isc_socket_detach(&dummy);
202:
203: /*
204: * send nextitem message.
205: */
206: region.base = buf2;
207: region.length = sizeof(buf2);
208: dummy = NULL;
209: isc_socket_attach(sock, &dummy);
210: result = isc_socket_sendto(sock, ®ion, task, senddone, sock,
211: &ev->address, NULL);
212: if (result != ISC_R_SUCCESS)
213: isc_socket_detach(&dummy);
214: isc_event_free(&event);
215: }
216:
217: static dns_dispatch_t *dispatch = NULL;
218: static dns_dispentry_t *dispentry = NULL;
1.3 christos 219: static bool first = true;
1.1 christos 220: static isc_mutex_t lock;
221: static isc_sockaddr_t local;
222: static unsigned int responses = 0;
223:
224: static void
225: response(isc_task_t *task, isc_event_t *event) {
226: dns_dispatchevent_t *devent = (dns_dispatchevent_t *)event;
227: isc_result_t result;
1.3 christos 228: bool wasfirst;
1.1 christos 229:
230: UNUSED(task);
231:
232: LOCK(&lock);
233: wasfirst = first;
1.3 christos 234: first = false;
1.1 christos 235: responses++;
236: UNLOCK(&lock);
237:
238: if (wasfirst) {
239: result = dns_dispatch_getnext(dispentry, &devent);
1.3 christos 240: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 241: } else {
242: dns_dispatch_removeresponse(&dispentry, &devent);
243: isc_app_shutdown();
244: }
245: }
246:
247: static void
248: startit(isc_task_t *task, isc_event_t *event) {
249: isc_result_t result;
250: isc_socket_t *sock = NULL;
251:
252: isc_socket_attach(dns_dispatch_getsocket(dispatch), &sock);
253: result = isc_socket_sendto(sock, event->ev_arg, task, senddone, sock,
254: &local, NULL);
1.3 christos 255: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 256: isc_event_free(&event);
257: }
258:
1.3 christos 259: /* test dispatch getnext */
260: static void
261: dispatch_getnext(void **state) {
1.1 christos 262: isc_region_t region;
263: isc_result_t result;
264: isc_socket_t *sock = NULL;
265: isc_task_t *task = NULL;
1.3 christos 266: uint16_t id;
1.1 christos 267: struct in_addr ina;
268: unsigned char message[12];
269: unsigned int attrs;
270: unsigned char rbuf[12];
271:
1.3 christos 272: UNUSED(state);
1.1 christos 273:
1.3 christos 274: isc_mutex_init(&lock);
1.1 christos 275:
276: result = isc_task_create(taskmgr, 0, &task);
1.3 christos 277: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 278:
1.3 christos 279: result = dns_dispatchmgr_create(mctx, &dispatchmgr);
280: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 281:
282: ina.s_addr = htonl(INADDR_LOOPBACK);
283: isc_sockaddr_fromin(&local, &ina, 0);
284: attrs = DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_UDP;
285: result = dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
286: &local, 512, 6, 1024, 17, 19, attrs,
287: attrs, &dispatch);
1.3 christos 288: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 289:
290: /*
291: * Create a local udp nameserver on the loopback.
292: */
293: result = isc_socket_create(socketmgr, AF_INET, isc_sockettype_udp,
294: &sock);
1.3 christos 295: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 296:
297: ina.s_addr = htonl(INADDR_LOOPBACK);
298: isc_sockaddr_fromin(&local, &ina, 0);
299: result = isc_socket_bind(sock, &local, 0);
1.3 christos 300: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 301:
302: result = isc_socket_getsockname(sock, &local);
1.3 christos 303: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 304:
1.3 christos 305: first = true;
1.1 christos 306: region.base = rbuf;
307: region.length = sizeof(rbuf);
308: result = isc_socket_recv(sock, ®ion, 1, task, nameserver, sock);
1.3 christos 309: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 310:
1.3 christos 311: result = dns_dispatch_addresponse(dispatch, 0, &local, task, response,
312: NULL, &id, &dispentry, NULL);
313: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 314:
315: memset(message, 0, sizeof(message));
316: message[0] = (id >> 8) & 0xff;
317: message[1] = id & 0xff;
318:
319: region.base = message;
320: region.length = sizeof(message);
321: result = isc_app_onrun(mctx, task, startit, ®ion);
1.3 christos 322: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 323:
324: result = isc_app_run();
1.3 christos 325: assert_int_equal(result, ISC_R_SUCCESS);
1.1 christos 326:
1.3 christos 327: assert_int_equal(responses, 2);
1.1 christos 328:
329: /*
330: * Shutdown nameserver.
331: */
332: isc_socket_cancel(sock, task, ISC_SOCKCANCEL_RECV);
333: isc_socket_detach(&sock);
334: isc_task_detach(&task);
335:
336: /*
337: * Shutdown the dispatch.
338: */
339: dns_dispatch_detach(&dispatch);
340: dns_dispatchmgr_destroy(&dispatchmgr);
1.3 christos 341: }
342:
343: int
344: main(void) {
345: const struct CMUnitTest tests[] = {
346: cmocka_unit_test_setup_teardown(dispatchset_create,
347: _setup, _teardown),
348: cmocka_unit_test_setup_teardown(dispatchset_get,
349: _setup, _teardown),
350: cmocka_unit_test_setup_teardown(dispatch_getnext,
351: _setup, _teardown),
352: };
1.1 christos 353:
1.3 christos 354: return (cmocka_run_group_tests(tests, NULL, NULL));
1.1 christos 355: }
356:
1.3 christos 357: #else /* HAVE_CMOCKA */
358:
359: #include <stdio.h>
360:
361: int
362: main(void) {
363: printf("1..0 # Skipped: cmocka not available\n");
364: return (0);
1.1 christos 365: }
1.3 christos 366:
367: #endif
CVSweb <webmaster@jp.NetBSD.org>