1 /* $NetBSD: rbt_test.c,v 1.6 2014/12/10 04:37:53 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007, 2009, 2011, 2012, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2001 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: rbt_test.c,v 1.52 2011/08/28 23:46:41 tbox Exp */
26 #include <isc/commandline.h>
28 #include <isc/string.h>
32 #include <dns/fixedname.h>
33 #include <dns/result.h>
38 #define DNSNAMELEN 255
41 create_name(char *s
) {
44 isc_buffer_t source
, target
;
45 static dns_name_t
*name
;
47 if (s
== NULL
|| *s
== '\0') {
48 printf("missing name argument\n");
54 isc_buffer_init(&source
, s
, length
);
55 isc_buffer_add(&source
, length
);
58 * It isn't really necessary in this program to create individual
59 * memory spaces for each name structure and its associated character
60 * string. It is done here to provide a relatively easy way to test
61 * the callback from dns_rbt_deletename that is supposed to free the
62 * data associated with a node.
64 * The buffer for the actual name will immediately follow the
67 name
= isc_mem_get(mctx
, sizeof(*name
) + DNSNAMELEN
);
69 printf("out of memory!\n");
73 dns_name_init(name
, NULL
);
74 isc_buffer_init(&target
, name
+ 1, DNSNAMELEN
);
76 result
= dns_name_fromtext(name
, &source
, dns_rootname
, 0, &target
);
78 if (result
!= ISC_R_SUCCESS
) {
79 printf("dns_name_fromtext(%s) failed: %s\n",
80 s
, dns_result_totext(result
));
88 delete_name(void *data
, void *arg
) {
93 isc_mem_put(mctx
, name
, sizeof(*name
) + DNSNAMELEN
);
97 print_name(dns_name_t
*name
) {
101 isc_buffer_init(&target
, buffer
, sizeof(buffer
));
104 * ISC_FALSE means absolute names have the final dot added.
106 dns_name_totext(name
, ISC_FALSE
, &target
);
108 printf("%.*s", (int)target
.used
, (char *)target
.base
);
112 detail(dns_rbt_t
*rbt
, dns_name_t
*name
) {
113 dns_name_t
*foundname
, *origin
, *fullname
;
114 dns_fixedname_t fixedfoundname
, fixedorigin
, fixedfullname
;
115 dns_rbtnode_t
*node1
, *node2
;
116 dns_rbtnodechain_t chain
;
118 isc_boolean_t nodes_should_match
= ISC_FALSE
;
120 dns_rbtnodechain_init(&chain
, mctx
);
122 dns_fixedname_init(&fixedorigin
);
123 dns_fixedname_init(&fixedfullname
);
124 dns_fixedname_init(&fixedfoundname
);
126 origin
= dns_fixedname_name(&fixedorigin
);
127 fullname
= dns_fixedname_name(&fixedfullname
);
128 foundname
= dns_fixedname_name(&fixedfoundname
);
130 node1
= node2
= NULL
;
132 printf("checking chain information for ");
136 result
= dns_rbt_findnode(rbt
, name
, foundname
, &node1
, &chain
,
137 DNS_RBTFIND_EMPTYDATA
, NULL
, NULL
);
141 printf(" found exact.");
142 nodes_should_match
= ISC_TRUE
;
144 case DNS_R_PARTIALMATCH
:
145 printf(" found parent.");
148 printf(" name not found.");
151 printf(" unexpected result: %s\n", dns_result_totext(result
));
155 if (node1
!= NULL
&& node1
->data
!= NULL
) {
156 printf(" data at node: ");
157 print_name(node1
->data
);
159 printf(" no data at node.");
161 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_PARTIALMATCH
) {
162 printf("\n name from dns_rbt_findnode: ");
163 print_name(foundname
);
166 result
= dns_rbtnodechain_current(&chain
, foundname
, origin
, &node2
);
168 if (result
== ISC_R_SUCCESS
) {
169 printf("\n name from dns_rbtnodechain_current: ");
171 result
= dns_name_concatenate(foundname
, origin
,
173 if (result
== ISC_R_SUCCESS
)
174 print_name(fullname
);
176 printf("%s\n", dns_result_totext(result
));
177 printf("\n (foundname = ");
178 print_name(foundname
);
179 printf(", origin = ");
182 if (nodes_should_match
&& node1
!= node2
)
183 printf(" nodes returned from each function "
187 printf("\n result from dns_rbtnodechain_current: %s\n",
188 dns_result_totext(result
));
190 printf(" level_matches = %d, level_count = %d\n",
191 chain
.level_matches
, chain
.level_count
);
195 iterate(dns_rbt_t
*rbt
, isc_boolean_t forward
) {
196 dns_name_t foundname
, *origin
;
197 dns_rbtnodechain_t chain
;
198 dns_fixedname_t fixedorigin
;
200 isc_result_t (*move
)(dns_rbtnodechain_t
*chain
, dns_name_t
*name
,
203 dns_rbtnodechain_init(&chain
, mctx
);
205 dns_name_init(&foundname
, NULL
);
206 dns_fixedname_init(&fixedorigin
);
207 origin
= dns_fixedname_name(&fixedorigin
);
210 printf("iterating forward\n" );
211 move
= dns_rbtnodechain_next
;
213 result
= dns_rbtnodechain_first(&chain
, rbt
, &foundname
,
217 printf("iterating backward\n" );
218 move
= dns_rbtnodechain_prev
;
220 result
= dns_rbtnodechain_last(&chain
, rbt
, &foundname
,
224 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_NEWORIGIN
)
225 printf("start not found!\n");
229 if (result
== DNS_R_NEWORIGIN
) {
230 printf(" new origin: ");
235 if (result
== ISC_R_SUCCESS
||
236 result
== DNS_R_NEWORIGIN
) {
237 print_name(&foundname
);
241 if (result
!= ISC_R_NOMORE
)
242 printf("UNEXEPCTED ITERATION ERROR: %s",
243 dns_result_totext(result
));
247 result
= move(&chain
, &foundname
, origin
);
253 #define CMDCHECK(s) (strncasecmp(command, (s), length) == 0)
254 #define PRINTERR(r) if (r != ISC_R_SUCCESS) \
255 printf("... %s\n", dns_result_totext(r));
258 main(int argc
, char **argv
) {
259 char *command
, *arg
, buffer
[1024];
260 const char *whitespace
;
261 dns_name_t
*name
, *foundname
;
262 dns_fixedname_t fixedname
;
263 dns_rbt_t
*rbt
= NULL
;
265 isc_boolean_t show_final_mem
= ISC_FALSE
;
269 progname
= strrchr(*argv
, '/');
270 if (progname
!= NULL
)
275 while ((ch
= isc_commandline_parse(argc
, argv
, "m")) != -1) {
278 show_final_mem
= ISC_TRUE
;
283 argc
-= isc_commandline_index
;
284 argv
+= isc_commandline_index
;
288 printf("Usage: %s [-m]\n", progname
);
292 setbuf(stdout
, NULL
);
295 * So isc_mem_stats() can report any allocation leaks.
297 isc_mem_debugging
= ISC_MEM_DEBUGRECORD
;
299 result
= isc_mem_create(0, 0, &mctx
);
300 if (result
!= ISC_R_SUCCESS
) {
301 printf("isc_mem_create: %s: exiting\n",
302 dns_result_totext(result
));
306 result
= dns_rbt_create(mctx
, delete_name
, NULL
, &rbt
);
307 if (result
!= ISC_R_SUCCESS
) {
308 printf("dns_rbt_create: %s: exiting\n",
309 dns_result_totext(result
));
315 while (fgets(buffer
, sizeof(buffer
), stdin
) != NULL
) {
316 length
= strlen(buffer
);
318 if (buffer
[length
- 1] != '\n') {
319 printf("line to long (%lu max), ignored\n",
320 (unsigned long)sizeof(buffer
) - 2);
324 buffer
[length
- 1] = '\0';
326 command
= buffer
+ strspn(buffer
, whitespace
);
331 arg
= strpbrk(command
, whitespace
);
334 arg
+= strspn(arg
, whitespace
);
337 length
= strlen(command
);
338 if (*command
!= '\0') {
339 if (CMDCHECK("add")) {
340 name
= create_name(arg
);
342 printf("adding name %s\n", arg
);
343 result
= dns_rbt_addname(rbt
,
348 } else if (CMDCHECK("delete")) {
349 name
= create_name(arg
);
351 printf("deleting name %s\n", arg
);
352 result
= dns_rbt_deletename(rbt
, name
,
355 delete_name(name
, NULL
);
358 } else if (CMDCHECK("nuke")) {
359 name
= create_name(arg
);
361 printf("nuking name %s "
362 "and its descendants\n", arg
);
363 result
= dns_rbt_deletename(rbt
, name
,
366 delete_name(name
, NULL
);
369 } else if (CMDCHECK("search")) {
370 name
= create_name(arg
);
372 printf("searching for name %s ... ",
375 dns_fixedname_init(&fixedname
);
377 dns_fixedname_name(&fixedname
);
380 result
= dns_rbt_findname(rbt
, name
, 0,
385 printf("found exact: ");
389 case DNS_R_PARTIALMATCH
:
390 printf("found parent: ");
392 printf("\n\t(foundname: ");
393 print_name(foundname
);
397 printf("NOT FOUND!\n");
400 printf("OUT OF MEMORY!\n");
403 printf("UNEXPECTED RESULT\n");
406 delete_name(name
, NULL
);
409 } else if (CMDCHECK("check")) {
411 * Or "chain". I know, I know. Lame name.
412 * I was having a hard time thinking of a
413 * name (especially one that did not have
414 * a conflicting first letter with another
415 * command) that would differentiate this
416 * from the search command.
418 * But it is just a test program, eh?
420 name
= create_name(arg
);
424 delete_name(name
, NULL
);
427 } else if (CMDCHECK("forward")) {
428 iterate(rbt
, ISC_TRUE
);
430 } else if (CMDCHECK("backward")) {
431 iterate(rbt
, ISC_FALSE
);
433 } else if (CMDCHECK("print")) {
434 if (arg
== NULL
|| *arg
== '\0')
435 dns_rbt_printtext(rbt
, NULL
, stdout
);
437 printf("usage: print\n");
439 } else if (CMDCHECK("quit")) {
440 if (arg
== NULL
|| *arg
== '\0')
443 printf("usage: quit\n");
445 printf("a(dd) NAME, d(elete) NAME, "
446 "s(earch) NAME, p(rint), or q(uit)\n");
453 dns_rbt_destroy(&rbt
);
456 isc_mem_stats(mctx
, stderr
);