xref: /netbsd-src/external/mpl/bind/dist/tests/isccfg/parser_test.c (revision 2f62cc9c12bc202c40224f32c879f81443fee079)
1 /*	$NetBSD: parser_test.c,v 1.2 2024/02/21 22:52:51 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 #include <inttypes.h>
17 #include <sched.h> /* IWYU pragma: keep */
18 #include <setjmp.h>
19 #include <stdarg.h>
20 #include <stddef.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 
26 #define UNIT_TESTING
27 #include <cmocka.h>
28 
29 #include <isc/buffer.h>
30 #include <isc/lex.h>
31 #include <isc/log.h>
32 #include <isc/mem.h>
33 #include <isc/print.h>
34 #include <isc/string.h>
35 #include <isc/types.h>
36 #include <isc/util.h>
37 
38 #include <isccfg/cfg.h>
39 #include <isccfg/grammar.h>
40 #include <isccfg/namedconf.h>
41 
42 #include <tests/isc.h>
43 
44 isc_log_t *lctx = NULL;
45 static isc_logcategory_t categories[] = { { "", 0 },
46 					  { "client", 0 },
47 					  { "network", 0 },
48 					  { "update", 0 },
49 					  { "queries", 0 },
50 					  { "unmatched", 0 },
51 					  { "update-security", 0 },
52 					  { "query-errors", 0 },
53 					  { NULL, 0 } };
54 
55 ISC_SETUP_TEST_IMPL(group) {
56 	isc_result_t result;
57 	isc_logdestination_t destination;
58 	isc_logconfig_t *logconfig = NULL;
59 
60 	isc_log_create(mctx, &lctx, &logconfig);
61 	isc_log_registercategories(lctx, categories);
62 	isc_log_setcontext(lctx);
63 
64 	destination.file.stream = stderr;
65 	destination.file.name = NULL;
66 	destination.file.versions = ISC_LOG_ROLLNEVER;
67 	destination.file.maximum_size = 0;
68 	isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC,
69 			      ISC_LOG_DYNAMIC, &destination, 0);
70 	result = isc_log_usechannel(logconfig, "stderr", NULL, NULL);
71 
72 	if (result != ISC_R_SUCCESS) {
73 		return (-1);
74 	}
75 
76 	return (0);
77 }
78 
79 ISC_TEARDOWN_TEST_IMPL(group) {
80 	if (lctx == NULL) {
81 		return (-1);
82 	}
83 
84 	isc_log_setcontext(NULL);
85 	isc_log_destroy(&lctx);
86 
87 	return (0);
88 }
89 
90 /* mimic calling nzf_append() */
91 static void
92 append(void *arg, const char *str, int len) {
93 	char *buf = arg;
94 	size_t l = strlen(buf);
95 	snprintf(buf + l, 1024 - l, "%.*s", len, str);
96 }
97 
98 ISC_RUN_TEST_IMPL(addzoneconf) {
99 	isc_result_t result;
100 	isc_buffer_t b;
101 	cfg_parser_t *p = NULL;
102 	const char *tests[] = {
103 		"zone \"test4.baz\" { type primary; file \"e.db\"; };",
104 		"zone \"test/.baz\" { type primary; file \"e.db\"; };",
105 		"zone \"test\\\".baz\" { type primary; file \"e.db\"; };",
106 		"zone \"test\\.baz\" { type primary; file \"e.db\"; };",
107 		"zone \"test\\\\.baz\" { type primary; file \"e.db\"; };",
108 		"zone \"test\\032.baz\" { type primary; file \"e.db\"; };",
109 		"zone \"test\\010.baz\" { type primary; file \"e.db\"; };"
110 	};
111 	char buf[1024];
112 
113 	/* Parse with default line numbering */
114 	result = cfg_parser_create(mctx, lctx, &p);
115 	assert_int_equal(result, ISC_R_SUCCESS);
116 
117 	for (size_t i = 0; i < ARRAY_SIZE(tests); i++) {
118 		cfg_obj_t *conf = NULL;
119 		const cfg_obj_t *obj = NULL, *zlist = NULL;
120 
121 		isc_buffer_constinit(&b, tests[i], strlen(tests[i]));
122 		isc_buffer_add(&b, strlen(tests[i]));
123 
124 		result = cfg_parse_buffer(p, &b, "text1", 0,
125 					  &cfg_type_namedconf, 0, &conf);
126 		assert_int_equal(result, ISC_R_SUCCESS);
127 
128 		/*
129 		 * Mimic calling nzf_append() from bin/named/server.c
130 		 * and check that the output matches the input.
131 		 */
132 		result = cfg_map_get(conf, "zone", &zlist);
133 		assert_int_equal(result, ISC_R_SUCCESS);
134 
135 		obj = cfg_listelt_value(cfg_list_first(zlist));
136 		assert_ptr_not_equal(obj, NULL);
137 
138 		strlcpy(buf, "zone ", sizeof(buf));
139 		cfg_printx(obj, CFG_PRINTER_ONELINE, append, buf);
140 		strlcat(buf, ";", sizeof(buf));
141 		assert_string_equal(tests[i], buf);
142 
143 		cfg_obj_destroy(p, &conf);
144 		cfg_parser_reset(p);
145 	}
146 
147 	cfg_parser_destroy(&p);
148 }
149 
150 /* test cfg_parse_buffer() */
151 ISC_RUN_TEST_IMPL(parse_buffer) {
152 	isc_result_t result;
153 	unsigned char text[] = "options\n{\nrecursion yes;\n};\n";
154 	isc_buffer_t buf1, buf2;
155 	cfg_parser_t *p1 = NULL, *p2 = NULL;
156 	cfg_obj_t *c1 = NULL, *c2 = NULL;
157 
158 	isc_buffer_init(&buf1, &text[0], sizeof(text) - 1);
159 	isc_buffer_add(&buf1, sizeof(text) - 1);
160 
161 	/* Parse with default line numbering */
162 	result = cfg_parser_create(mctx, lctx, &p1);
163 	assert_int_equal(result, ISC_R_SUCCESS);
164 
165 	result = cfg_parse_buffer(p1, &buf1, "text1", 0, &cfg_type_namedconf, 0,
166 				  &c1);
167 	assert_int_equal(result, ISC_R_SUCCESS);
168 	assert_int_equal(p1->line, 5);
169 
170 	isc_buffer_init(&buf2, &text[0], sizeof(text) - 1);
171 	isc_buffer_add(&buf2, sizeof(text) - 1);
172 
173 	/* Parse with changed line number */
174 	result = cfg_parser_create(mctx, lctx, &p2);
175 	assert_int_equal(result, ISC_R_SUCCESS);
176 
177 	result = cfg_parse_buffer(p2, &buf2, "text2", 100, &cfg_type_namedconf,
178 				  0, &c2);
179 	assert_int_equal(result, ISC_R_SUCCESS);
180 	assert_int_equal(p2->line, 104);
181 
182 	cfg_obj_destroy(p1, &c1);
183 	cfg_obj_destroy(p2, &c2);
184 
185 	cfg_parser_destroy(&p1);
186 	cfg_parser_destroy(&p2);
187 }
188 
189 /* test cfg_map_firstclause() */
190 ISC_RUN_TEST_IMPL(cfg_map_firstclause) {
191 	const char *name = NULL;
192 	const void *clauses = NULL;
193 	unsigned int idx;
194 
195 	name = cfg_map_firstclause(&cfg_type_zoneopts, &clauses, &idx);
196 	assert_non_null(name);
197 	assert_non_null(clauses);
198 	assert_int_equal(idx, 0);
199 }
200 
201 /* test cfg_map_nextclause() */
202 ISC_RUN_TEST_IMPL(cfg_map_nextclause) {
203 	const char *name = NULL;
204 	const void *clauses = NULL;
205 	unsigned int idx;
206 
207 	name = cfg_map_firstclause(&cfg_type_zoneopts, &clauses, &idx);
208 	assert_non_null(name);
209 	assert_non_null(clauses);
210 	assert_int_equal(idx, ISC_R_SUCCESS);
211 
212 	do {
213 		name = cfg_map_nextclause(&cfg_type_zoneopts, &clauses, &idx);
214 		if (name != NULL) {
215 			assert_non_null(clauses);
216 		} else {
217 			assert_null(clauses);
218 			assert_int_equal(idx, 0);
219 		}
220 	} while (name != NULL);
221 }
222 
223 ISC_TEST_LIST_START
224 
225 ISC_TEST_ENTRY(addzoneconf)
226 ISC_TEST_ENTRY(parse_buffer)
227 ISC_TEST_ENTRY(cfg_map_firstclause)
228 ISC_TEST_ENTRY(cfg_map_nextclause)
229 
230 ISC_TEST_LIST_END
231 
232 ISC_TEST_MAIN_CUSTOM(setup_test_group, teardown_test_group)
233