1 /*	$NetBSD: dbiterator_test.c,v 1.1.1.5 2014/12/10 03:34:42 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /* Id */
20 
21 /*! \file */
22 
23 #include <config.h>
24 
25 #include <atf-c.h>
26 
27 #include <unistd.h>
28 #include <stdlib.h>
29 
30 #include <dns/db.h>
31 #include <dns/dbiterator.h>
32 #include <dns/name.h>
33 
34 #include "dnstest.h"
35 
36 /*
37  * Helper functions
38  */
39 
40 #define	BUFLEN		255
41 #define	BIGBUFLEN	(64 * 1024)
42 #define TEST_ORIGIN	"test"
43 
44 static isc_result_t
45 make_name(const char *src, dns_name_t *name) {
46 	isc_buffer_t b;
47 	isc_buffer_constinit(&b, src, strlen(src));
48 	isc_buffer_add(&b, strlen(src));
49 	return (dns_name_fromtext(name, &b, dns_rootname, 0, NULL));
50 }
51 
52 /*
53  * Individual unit tests
54  */
55 
56 /* create: make sure we can create a dbiterator */
57 static void
58 test_create(const atf_tc_t *tc) {
59 	isc_result_t result;
60 	dns_db_t *db = NULL;
61 	dns_dbiterator_t *iter = NULL;
62 
63 	result = dns_test_begin(NULL, ISC_FALSE);
64 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
65 
66 	result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN,
67 				 atf_tc_get_md_var(tc, "X-filename"));
68 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
69 
70 	result = dns_db_createiterator(db, 0, &iter);
71 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
72 
73 	dns_dbiterator_destroy(&iter);
74 	dns_db_detach(&db);
75 	dns_test_end();
76 }
77 
78 ATF_TC(create);
79 ATF_TC_HEAD(create, tc) {
80 	atf_tc_set_md_var(tc, "descr", "create a database iterator");
81 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data");
82 }
83 ATF_TC_BODY(create, tc) {
84 	test_create(tc);
85 }
86 
87 ATF_TC(create_nsec3);
88 ATF_TC_HEAD(create_nsec3, tc) {
89 	atf_tc_set_md_var(tc, "descr", "create a database iterator (NSEC3)");
90 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data");
91 }
92 ATF_TC_BODY(create_nsec3, tc) {
93 	test_create(tc);
94 }
95 
96 /* walk: walk a database */
97 static void
98 test_walk(const atf_tc_t *tc) {
99 	isc_result_t result;
100 	dns_db_t *db = NULL;
101 	dns_dbiterator_t *iter = NULL;
102 	dns_dbnode_t *node = NULL;
103 	dns_name_t *name;
104 	dns_fixedname_t f;
105 	int i = 0;
106 
107 	UNUSED(tc);
108 
109 	dns_fixedname_init(&f);
110 	name = dns_fixedname_name(&f);
111 
112 	result = dns_test_begin(NULL, ISC_FALSE);
113 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
114 
115 	result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN,
116 				 atf_tc_get_md_var(tc, "X-filename"));
117 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
118 
119 	result = dns_db_createiterator(db, 0, &iter);
120 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
121 
122 	for (result = dns_dbiterator_first(iter);
123 	     result == ISC_R_SUCCESS;
124 	     result = dns_dbiterator_next(iter)) {
125 		result = dns_dbiterator_current(iter, &node, name);
126 		if (result == DNS_R_NEWORIGIN)
127 			result = ISC_R_SUCCESS;
128 		ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
129 		dns_db_detachnode(db, &node);
130 		i++;
131 	}
132 
133 	ATF_CHECK_EQ(i, atoi(atf_tc_get_md_var(tc, "X-nodes")));
134 
135 	dns_dbiterator_destroy(&iter);
136 	dns_db_detach(&db);
137 	dns_test_end();
138 }
139 
140 ATF_TC(walk);
141 ATF_TC_HEAD(walk, tc) {
142 	atf_tc_set_md_var(tc, "descr", "walk database");
143 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data");
144 	atf_tc_set_md_var(tc, "X-nodes", "12");
145 }
146 ATF_TC_BODY(walk, tc) {
147 	test_walk(tc);
148 }
149 
150 ATF_TC(walk_nsec3);
151 ATF_TC_HEAD(walk_nsec3, tc) {
152 	atf_tc_set_md_var(tc, "descr", "walk database");
153 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data");
154 	atf_tc_set_md_var(tc, "X-nodes", "33");
155 }
156 ATF_TC_BODY(walk_nsec3, tc) {
157 	test_walk(tc);
158 }
159 
160 /* reverse: walk database backwards */
161 static void test_reverse(const atf_tc_t *tc) {
162 	isc_result_t result;
163 	dns_db_t *db = NULL;
164 	dns_dbiterator_t *iter = NULL;
165 	dns_dbnode_t *node = NULL;
166 	dns_name_t *name;
167 	dns_fixedname_t f;
168 	int i = 0;
169 
170 	UNUSED(tc);
171 
172 	dns_fixedname_init(&f);
173 	name = dns_fixedname_name(&f);
174 
175 	result = dns_test_begin(NULL, ISC_FALSE);
176 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
177 
178 	result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN,
179 				 atf_tc_get_md_var(tc, "X-filename"));
180 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
181 
182 	result = dns_db_createiterator(db, 0, &iter);
183 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
184 
185 	for (result = dns_dbiterator_last(iter);
186 	     result == ISC_R_SUCCESS;
187 	     result = dns_dbiterator_prev(iter)) {
188 		result = dns_dbiterator_current(iter, &node, name);
189 		if (result == DNS_R_NEWORIGIN)
190 			result = ISC_R_SUCCESS;
191 		ATF_CHECK_EQ(result, ISC_R_SUCCESS);
192 		dns_db_detachnode(db, &node);
193 		i++;
194 	}
195 
196 	ATF_CHECK_EQ(i, 12);
197 
198 	dns_dbiterator_destroy(&iter);
199 	dns_db_detach(&db);
200 	dns_test_end();
201 }
202 
203 ATF_TC(reverse);
204 ATF_TC_HEAD(reverse, tc) {
205 	atf_tc_set_md_var(tc, "descr", "walk database backwards");
206 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data");
207 }
208 ATF_TC_BODY(reverse, tc) {
209 	test_reverse(tc);
210 }
211 
212 ATF_TC(reverse_nsec3);
213 ATF_TC_HEAD(reverse_nsec3, tc) {
214 	atf_tc_set_md_var(tc, "descr", "walk database backwards");
215 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data");
216 }
217 ATF_TC_BODY(reverse_nsec3, tc) {
218 	test_reverse(tc);
219 }
220 
221 /* seek: walk database starting at a particular node */
222 static void test_seek(const atf_tc_t *tc) {
223 	isc_result_t result;
224 	dns_db_t *db = NULL;
225 	dns_dbiterator_t *iter = NULL;
226 	dns_dbnode_t *node = NULL;
227 	dns_name_t *name, *seekname;
228 	dns_fixedname_t f1, f2;
229 	int i = 0;
230 
231 	UNUSED(tc);
232 
233 	dns_fixedname_init(&f1);
234 	name = dns_fixedname_name(&f1);
235 	dns_fixedname_init(&f2);
236 	seekname = dns_fixedname_name(&f2);
237 
238 	result = dns_test_begin(NULL, ISC_FALSE);
239 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
240 
241 	result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN,
242 				 atf_tc_get_md_var(tc, "X-filename"));
243 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
244 
245 	result = dns_db_createiterator(db, 0, &iter);
246 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
247 
248 	result = make_name("c." TEST_ORIGIN, seekname);
249 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
250 
251 	result = dns_dbiterator_seek(iter, seekname);
252 	ATF_CHECK_EQ(result, ISC_R_SUCCESS);
253 
254 	while (result == ISC_R_SUCCESS) {
255 		result = dns_dbiterator_current(iter, &node, name);
256 		if (result == DNS_R_NEWORIGIN)
257 			result = ISC_R_SUCCESS;
258 		ATF_CHECK_EQ(result, ISC_R_SUCCESS);
259 		dns_db_detachnode(db, &node);
260 		result = dns_dbiterator_next(iter);
261 		i++;
262 	}
263 
264 	ATF_CHECK_EQ(i, atoi(atf_tc_get_md_var(tc, "X-nodes")));
265 
266 	dns_dbiterator_destroy(&iter);
267 	dns_db_detach(&db);
268 	dns_test_end();
269 }
270 
271 ATF_TC(seek);
272 ATF_TC_HEAD(seek, tc) {
273 	atf_tc_set_md_var(tc, "descr", "walk database starting at "
274 				       "a particular node");
275 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data");
276 	atf_tc_set_md_var(tc, "X-nodes", "9");
277 }
278 ATF_TC_BODY(seek, tc) {
279 	test_seek(tc);
280 }
281 
282 ATF_TC(seek_nsec3);
283 ATF_TC_HEAD(seek_nsec3, tc) {
284 	atf_tc_set_md_var(tc, "descr", "walk database starting at "
285 				       "a particular node");
286 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data");
287 	atf_tc_set_md_var(tc, "X-nodes", "30");
288 }
289 ATF_TC_BODY(seek_nsec3, tc) {
290 	test_seek(tc);
291 }
292 
293 /*
294  * seek_emty: walk database starting at an empty nonterminal node
295  * (should fail)
296  */
297 static void test_seek_empty(const atf_tc_t *tc) {
298 	isc_result_t result;
299 	dns_db_t *db = NULL;
300 	dns_dbiterator_t *iter = NULL;
301 	dns_name_t *seekname;
302 	dns_fixedname_t f1;
303 
304 	UNUSED(tc);
305 
306 	dns_fixedname_init(&f1);
307 	seekname = dns_fixedname_name(&f1);
308 
309 	result = dns_test_begin(NULL, ISC_FALSE);
310 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
311 
312 	result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN,
313 				 atf_tc_get_md_var(tc, "X-filename"));
314 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
315 
316 	result = dns_db_createiterator(db, 0, &iter);
317 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
318 
319 	result = make_name("d." TEST_ORIGIN, seekname);
320 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
321 
322 	result = dns_dbiterator_seek(iter, seekname);
323 	ATF_CHECK_EQ(result, ISC_R_NOTFOUND);
324 
325 	dns_dbiterator_destroy(&iter);
326 	dns_db_detach(&db);
327 	dns_test_end();
328 }
329 
330 ATF_TC(seek_empty);
331 ATF_TC_HEAD(seek_empty, tc) {
332 	atf_tc_set_md_var(tc, "descr", "walk database starting at an "
333 				       "empty nonterminal node");
334 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data");
335 }
336 ATF_TC_BODY(seek_empty, tc) {
337 	test_seek_empty(tc);
338 }
339 
340 ATF_TC(seek_empty_nsec3);
341 ATF_TC_HEAD(seek_empty_nsec3, tc) {
342 	atf_tc_set_md_var(tc, "descr", "walk database starting at an "
343 				       "empty nonterminal node");
344 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data");
345 }
346 ATF_TC_BODY(seek_empty_nsec3, tc) {
347 	test_seek_empty(tc);
348 }
349 
350 /*
351  * seek_emty: walk database starting at an empty nonterminal node
352  * (should fail)
353  */
354 static void test_seek_nx(const atf_tc_t *tc) {
355 	isc_result_t result;
356 	dns_db_t *db = NULL;
357 	dns_dbiterator_t *iter = NULL;
358 	dns_name_t *seekname;
359 	dns_fixedname_t f1;
360 
361 	UNUSED(tc);
362 
363 	dns_fixedname_init(&f1);
364 	seekname = dns_fixedname_name(&f1);
365 
366 	result = dns_test_begin(NULL, ISC_FALSE);
367 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
368 
369 	result = dns_test_loaddb(&db, dns_dbtype_cache, TEST_ORIGIN,
370 				 atf_tc_get_md_var(tc, "X-filename"));
371 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
372 
373 	result = dns_db_createiterator(db, 0, &iter);
374 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
375 
376 	result = make_name("nonexistent." TEST_ORIGIN, seekname);
377 	ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
378 
379 	result = dns_dbiterator_seek(iter, seekname);
380 	ATF_CHECK_EQ(result, ISC_R_NOTFOUND);
381 
382 	dns_dbiterator_destroy(&iter);
383 	dns_db_detach(&db);
384 	dns_test_end();
385 }
386 
387 ATF_TC(seek_nx);
388 ATF_TC_HEAD(seek_nx, tc) {
389 	atf_tc_set_md_var(tc, "descr", "attempt to walk database starting "
390 				       "at a nonexistent node");
391 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone1.data");
392 }
393 ATF_TC_BODY(seek_nx, tc) {
394 	test_seek_nx(tc);
395 }
396 
397 ATF_TC(seek_nx_nsec3);
398 ATF_TC_HEAD(seek_nx_nsec3, tc) {
399 	atf_tc_set_md_var(tc, "descr", "attempt to walk database starting "
400 				       "at a nonexistent node");
401 	atf_tc_set_md_var(tc, "X-filename", "testdata/dbiterator/zone2.data");
402 }
403 ATF_TC_BODY(seek_nx_nsec3, tc) {
404 	test_seek_nx(tc);
405 }
406 
407 /*
408  * Main
409  */
410 ATF_TP_ADD_TCS(tp) {
411 	ATF_TP_ADD_TC(tp, create);
412 	ATF_TP_ADD_TC(tp, create_nsec3);
413 	ATF_TP_ADD_TC(tp, walk);
414 	ATF_TP_ADD_TC(tp, walk_nsec3);
415 	ATF_TP_ADD_TC(tp, reverse);
416 	ATF_TP_ADD_TC(tp, reverse_nsec3);
417 	ATF_TP_ADD_TC(tp, seek);
418 	ATF_TP_ADD_TC(tp, seek_nsec3);
419 	ATF_TP_ADD_TC(tp, seek_empty);
420 	ATF_TP_ADD_TC(tp, seek_empty_nsec3);
421 	ATF_TP_ADD_TC(tp, seek_nx);
422 	ATF_TP_ADD_TC(tp, seek_nx_nsec3);
423 	return (atf_no_error());
424 }
425 
426 /*
427  * XXX:
428  * dns_dbiterator API calls that are not yet part of this unit test:
429  *
430  * dns_dbiterator_pause
431  * dns_dbiterator_origin
432  * dns_dbiterator_setcleanmode
433  */
434