xref: /netbsd/external/mpl/bind/dist/lib/isc/tests/isctest.c (revision c0b5d9fb)
1 /*	$NetBSD: isctest.c,v 1.7 2022/09/23 12:15:34 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 /*! \file */
17 
18 #include "isctest.h"
19 #include <inttypes.h>
20 #include <stdbool.h>
21 #include <stdlib.h>
22 #include <time.h>
23 
24 #include <isc/buffer.h>
25 #include <isc/hash.h>
26 #include <isc/managers.h>
27 #include <isc/mem.h>
28 #include <isc/os.h>
29 #include <isc/socket.h>
30 #include <isc/string.h>
31 #include <isc/task.h>
32 #include <isc/timer.h>
33 #include <isc/util.h>
34 
35 isc_mem_t *test_mctx = NULL;
36 isc_log_t *test_lctx = NULL;
37 isc_taskmgr_t *taskmgr = NULL;
38 isc_timermgr_t *timermgr = NULL;
39 isc_socketmgr_t *socketmgr = NULL;
40 isc_nm_t *netmgr = NULL;
41 isc_task_t *maintask = NULL;
42 int ncpus;
43 
44 static bool test_running = false;
45 
46 /*
47  * Logging categories: this needs to match the list in bin/named/log.c.
48  */
49 static isc_logcategory_t categories[] = { { "", 0 },
50 					  { "client", 0 },
51 					  { "network", 0 },
52 					  { "update", 0 },
53 					  { "queries", 0 },
54 					  { "unmatched", 0 },
55 					  { "update-security", 0 },
56 					  { "query-errors", 0 },
57 					  { NULL, 0 } };
58 
59 static void
cleanup_managers(void)60 cleanup_managers(void) {
61 	if (maintask != NULL) {
62 		isc_task_shutdown(maintask);
63 		isc_task_destroy(&maintask);
64 	}
65 
66 	isc_managers_destroy(netmgr == NULL ? NULL : &netmgr,
67 			     taskmgr == NULL ? NULL : &taskmgr);
68 
69 	if (socketmgr != NULL) {
70 		isc_socketmgr_destroy(&socketmgr);
71 	}
72 	if (timermgr != NULL) {
73 		isc_timermgr_destroy(&timermgr);
74 	}
75 }
76 
77 static isc_result_t
create_managers(unsigned int workers)78 create_managers(unsigned int workers) {
79 	isc_result_t result;
80 	char *p;
81 
82 	if (workers == 0) {
83 		workers = isc_os_ncpus();
84 	}
85 
86 	p = getenv("ISC_TASK_WORKERS");
87 	if (p != NULL) {
88 		workers = atoi(p);
89 	}
90 
91 	CHECK(isc_managers_create(test_mctx, workers, 0, &netmgr, &taskmgr));
92 	CHECK(isc_task_create_bound(taskmgr, 0, &maintask, 0));
93 	isc_taskmgr_setexcltask(taskmgr, maintask);
94 
95 	CHECK(isc_timermgr_create(test_mctx, &timermgr));
96 	CHECK(isc_socketmgr_create(test_mctx, &socketmgr));
97 	return (ISC_R_SUCCESS);
98 
99 cleanup:
100 	cleanup_managers();
101 	return (result);
102 }
103 
104 isc_result_t
isc_test_begin(FILE * logfile,bool start_managers,unsigned int workers)105 isc_test_begin(FILE *logfile, bool start_managers, unsigned int workers) {
106 	isc_result_t result;
107 
108 	INSIST(!test_running);
109 	test_running = true;
110 
111 	isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
112 
113 	INSIST(test_mctx == NULL);
114 	isc_mem_create(&test_mctx);
115 
116 	if (logfile != NULL) {
117 		isc_logdestination_t destination;
118 		isc_logconfig_t *logconfig = NULL;
119 
120 		INSIST(test_lctx == NULL);
121 		isc_log_create(test_mctx, &test_lctx, &logconfig);
122 		isc_log_registercategories(test_lctx, categories);
123 		isc_log_setcontext(test_lctx);
124 
125 		destination.file.stream = logfile;
126 		destination.file.name = NULL;
127 		destination.file.versions = ISC_LOG_ROLLNEVER;
128 		destination.file.maximum_size = 0;
129 		isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC,
130 				      ISC_LOG_DYNAMIC, &destination, 0);
131 		CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL));
132 	}
133 
134 	ncpus = isc_os_ncpus();
135 
136 	if (start_managers) {
137 		CHECK(create_managers(workers));
138 	}
139 
140 	return (ISC_R_SUCCESS);
141 
142 cleanup:
143 	isc_test_end();
144 	return (result);
145 }
146 
147 void
isc_test_end(void)148 isc_test_end(void) {
149 	if (maintask != NULL) {
150 		isc_task_detach(&maintask);
151 	}
152 
153 	cleanup_managers();
154 
155 	if (test_lctx != NULL) {
156 		isc_log_destroy(&test_lctx);
157 	}
158 	if (test_mctx != NULL) {
159 		isc_mem_destroy(&test_mctx);
160 	}
161 
162 	test_running = false;
163 }
164 
165 /*
166  * Sleep for 'usec' microseconds.
167  */
168 void
isc_test_nap(uint32_t usec)169 isc_test_nap(uint32_t usec) {
170 	struct timespec ts;
171 
172 	ts.tv_sec = usec / 1000000;
173 	ts.tv_nsec = (usec % 1000000) * 1000;
174 	nanosleep(&ts, NULL);
175 }
176