1 /* $NetBSD: t_rbt.c,v 1.7 2014/12/10 04:37:53 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007, 2009, 2011-2013 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1998-2001, 2003 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: t_rbt.c,v 1.35 2011/03/12 04:59:46 tbox Exp */
27 #include <isc/entropy.h>
31 #include <isc/string.h>
33 #include <dns/fixedname.h>
35 #include <dns/result.h>
37 #include <tests/t_api.h>
40 #define DNSNAMELEN 255
43 char *Tokens
[T_MAXTOKS
];
46 t_dns_rbtnodechain_init(char *dbfile
, char *findname
,
47 char *firstname
, char *firstorigin
,
48 char *nextname
, char *nextorigin
,
49 char *prevname
, char *prevorigin
,
50 char *lastname
, char *lastorigin
);
52 fixedname_totext(dns_fixedname_t
*name
);
55 fixedname_cmp(dns_fixedname_t
*dns_name
, char *txtname
);
58 dnsname_totext(dns_name_t
*name
);
61 t_namechk(isc_result_t dns_result
, dns_fixedname_t
*dns_name
, char *exp_name
,
62 dns_fixedname_t
*dns_origin
, char *exp_origin
,
63 isc_result_t exp_result
);
66 * Parts adapted from the original rbt_test.c.
69 fixedname_cmp(dns_fixedname_t
*dns_name
, char *txtname
) {
72 name
= dnsname_totext(dns_fixedname_name(dns_name
));
73 if (strcmp(txtname
, "NULL") == 0) {
74 if ((name
== NULL
) || (*name
== '\0'))
78 return(strcmp(name
, txtname
));
83 dnsname_totext(dns_name_t
*name
) {
84 static char buf
[BUFLEN
];
87 isc_buffer_init(&target
, buf
, BUFLEN
);
88 dns_name_totext(name
, ISC_FALSE
, &target
);
89 *((char *)(target
.base
) + target
.used
) = '\0';
94 fixedname_totext(dns_fixedname_t
*name
) {
95 static char buf
[BUFLEN
];
98 memset(buf
, 0, BUFLEN
);
99 isc_buffer_init(&target
, buf
, BUFLEN
);
100 dns_name_totext(dns_fixedname_name(name
), ISC_FALSE
, &target
);
101 *((char *)(target
.base
) + target
.used
) = '\0';
105 #ifdef NEED_PRINT_DATA
108 print_data(void *data
) {
109 isc_result_t dns_result
;
111 char *buffer
[DNSNAMELEN
];
113 isc_buffer_init(&target
, buffer
, sizeof(buffer
));
115 dns_result
= dns_name_totext(data
, ISC_FALSE
, &target
);
116 if (dns_result
!= ISC_R_SUCCESS
) {
117 t_info("dns_name_totext failed %s\n",
118 dns_result_totext(dns_result
));
123 #endif /* NEED_PRINT_DATA */
126 create_name(char *s
, isc_mem_t
*mctx
, dns_name_t
**dns_name
) {
140 isc_buffer_init(&source
, s
, length
);
141 isc_buffer_add(&source
, length
);
144 * The buffer for the actual name will immediately follow the
147 name
= isc_mem_get(mctx
, sizeof(*name
) + DNSNAMELEN
);
149 t_info("isc_mem_get failed\n");
153 dns_name_init(name
, NULL
);
154 isc_buffer_init(&target
, name
+ 1, DNSNAMELEN
);
156 result
= dns_name_fromtext(name
, &source
, dns_rootname
,
159 if (result
!= ISC_R_SUCCESS
) {
161 t_info("dns_name_fromtext(%s) failed %s\n",
162 s
, dns_result_totext(result
));
163 isc_mem_put(mctx
, name
,
164 sizeof(*name
) + DNSNAMELEN
);
170 t_info("create_name: empty name\n");
177 delete_name(void *data
, void *arg
) {
178 isc_mem_put((isc_mem_t
*)arg
, data
, sizeof(dns_name_t
) + DNSNAMELEN
);
183 * Adapted from the original rbt_test.c.
186 t1_add(char *name
, dns_rbt_t
*rbt
, isc_mem_t
*mctx
, isc_result_t
*dns_result
) {
188 dns_name_t
*dns_name
;
191 if (name
&& dns_result
) {
192 if (create_name(name
, mctx
, &dns_name
) == 0) {
194 t_info("dns_rbt_addname succeeded\n");
195 *dns_result
= dns_rbt_addname(rbt
, dns_name
, dns_name
);
196 if (*dns_result
!= ISC_R_SUCCESS
) {
197 delete_name(dns_name
, mctx
);
198 t_info("dns_rbt_addname failed %s\n",
199 dns_result_totext(*dns_result
));
212 t1_delete(char *name
, dns_rbt_t
*rbt
, isc_mem_t
*mctx
,
213 isc_result_t
*dns_result
)
216 dns_name_t
*dns_name
;
219 if (name
&& dns_result
) {
220 if (create_name(name
, mctx
, &dns_name
) == 0) {
221 *dns_result
= dns_rbt_deletename(rbt
, dns_name
,
223 delete_name(dns_name
, mctx
);
234 t1_search(char *name
, dns_rbt_t
*rbt
, isc_mem_t
*mctx
,
235 isc_result_t
*dns_result
)
238 dns_name_t
*dns_searchname
;
239 dns_name_t
*dns_foundname
;
240 dns_fixedname_t dns_fixedname
;
244 if (name
&& dns_result
) {
245 if (create_name(name
, mctx
, &dns_searchname
) == 0) {
246 dns_fixedname_init(&dns_fixedname
);
247 dns_foundname
= dns_fixedname_name(&dns_fixedname
);
249 *dns_result
= dns_rbt_findname(rbt
, dns_searchname
, 0,
250 dns_foundname
, &data
);
251 delete_name(dns_searchname
, mctx
);
262 * Initialize a database from filename.
265 rbt_init(char *filename
, dns_rbt_t
**rbt
, isc_mem_t
*mctx
) {
267 isc_result_t dns_result
;
271 fp
= fopen(filename
, "r");
273 t_info("No such file %s\n", filename
);
277 dns_result
= dns_rbt_create(mctx
, delete_name
, mctx
, rbt
);
278 if (dns_result
!= ISC_R_SUCCESS
) {
279 t_info("dns_rbt_create failed %s\n",
280 dns_result_totext(dns_result
));
285 while ((p
= t_fgetbs(fp
)) != NULL
) {
288 * Skip any comment lines.
290 if ((*p
== '#') || (*p
== '\0') || (*p
== ' ')) {
296 t_info("adding name %s to the rbt\n", p
);
298 rval
= t1_add(p
, *rbt
, mctx
, &dns_result
);
299 if ((rval
!= 0) || (dns_result
!= ISC_R_SUCCESS
)) {
300 t_info("add of %s failed\n", p
);
301 dns_rbt_destroy(rbt
);
312 test_rbt_gen(char *filename
, char *command
, char *testname
,
313 isc_result_t exp_result
)
318 isc_result_t isc_result
;
319 isc_result_t dns_result
;
322 dns_name_t
*dns_name
;
324 result
= T_UNRESOLVED
;
326 if (strcmp(command
, "create") != 0)
327 t_info("testing using name %s\n", testname
);
332 isc_result
= isc_mem_create(0, 0, &mctx
);
333 if (isc_result
!= ISC_R_SUCCESS
) {
334 t_info("isc_mem_create: %s: exiting\n",
335 dns_result_totext(isc_result
));
336 return(T_UNRESOLVED
);
339 isc_result
= isc_entropy_create(mctx
, &ectx
);
340 if (isc_result
!= ISC_R_SUCCESS
) {
341 t_info("isc_entropy_create: %s: exiting\n",
342 dns_result_totext(isc_result
));
343 isc_mem_destroy(&mctx
);
344 return(T_UNRESOLVED
);
347 isc_result
= isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
);
348 if (isc_result
!= ISC_R_SUCCESS
) {
349 t_info("isc_hash_create: %s: exiting\n",
350 dns_result_totext(isc_result
));
351 isc_entropy_detach(&ectx
);
352 isc_mem_destroy(&mctx
);
353 return(T_UNRESOLVED
);
357 if (rbt_init(filename
, &rbt
, mctx
) != 0) {
358 if (strcmp(command
, "create") == 0)
361 isc_entropy_detach(&ectx
);
362 isc_mem_destroy(&mctx
);
367 * Now try the database command.
369 if (strcmp(command
, "create") == 0) {
371 } else if (strcmp(command
, "add") == 0) {
372 if (create_name(testname
, mctx
, &dns_name
) == 0) {
373 dns_result
= dns_rbt_addname(rbt
, dns_name
, dns_name
);
375 if (dns_result
!= ISC_R_SUCCESS
)
376 delete_name(dns_name
, mctx
);
378 if (dns_result
== exp_result
) {
379 if (dns_result
== ISC_R_SUCCESS
) {
380 rval
= t1_search(testname
, rbt
, mctx
,
383 if (dns_result
== ISC_R_SUCCESS
) {
389 t_info("t1_search failed\n");
390 result
= T_UNRESOLVED
;
396 t_info("dns_rbt_addname returned %s, "
398 dns_result_totext(dns_result
),
399 dns_result_totext(exp_result
));
403 t_info("create_name failed\n");
404 result
= T_UNRESOLVED
;
406 } else if ((strcmp(command
, "delete") == 0) ||
407 (strcmp(command
, "nuke") == 0)) {
408 rval
= t1_delete(testname
, rbt
, mctx
, &dns_result
);
410 if (dns_result
== exp_result
) {
411 rval
= t1_search(testname
, rbt
, mctx
,
414 if (dns_result
== ISC_R_SUCCESS
) {
415 t_info("dns_rbt_deletename "
424 t_info("delete returned %s, expected %s\n",
425 dns_result_totext(dns_result
),
426 dns_result_totext(exp_result
));
430 } else if (strcmp(command
, "search") == 0) {
431 rval
= t1_search(testname
, rbt
, mctx
, &dns_result
);
433 if (dns_result
== exp_result
) {
436 t_info("find returned %s, expected %s\n",
437 dns_result_totext(dns_result
),
438 dns_result_totext(exp_result
));
444 dns_rbt_destroy(&rbt
);
446 isc_entropy_detach(&ectx
);
447 isc_mem_destroy(&mctx
);
452 test_dns_rbt_x(const char *filename
) {
464 fp
= fopen(filename
, "r");
467 while ((p
= t_fgetbs(fp
)) != NULL
) {
472 * Skip comment lines.
474 if ((isspace((unsigned char)*p
)) || (*p
== '#')) {
480 * Name of db file, command, testname,
483 cnt
= t_bustline(p
, Tokens
);
485 result
= test_rbt_gen(Tokens
[0], Tokens
[1],
487 t_dns_result_fromtext(Tokens
[3]));
488 if (result
!= T_PASS
)
491 t_info("bad format in %s at line %d\n",
500 t_info("Missing datafile %s\n", filename
);
504 result
= T_UNRESOLVED
;
505 if ((nfails
== 0) && (nprobs
== 0))
514 static const char *a1
= "dns_rbt_create creates a rbt and returns "
515 "ISC_R_SUCCESS on success";
521 t_assert("dns_rbt_create", 1, T_REQUIRED
, "%s", a1
);
522 result
= test_dns_rbt_x("dns_rbt_create_1_data");
526 static const char *a2
= "dns_rbt_addname adds a name to a database and "
527 "returns ISC_R_SUCCESS on success";
533 t_assert("dns_rbt_addname", 2, T_REQUIRED
, "%s", a2
);
534 result
= test_dns_rbt_x("dns_rbt_addname_1_data");
538 static const char *a3
= "when name already exists, dns_rbt_addname() "
539 "returns ISC_R_EXISTS";
545 t_assert("dns_rbt_addname", 3, T_REQUIRED
, "%s", a3
);
546 result
= test_dns_rbt_x("dns_rbt_addname_2_data");
550 static const char *a4
= "when name exists, dns_rbt_deletename() returns "
557 t_assert("dns_rbt_deletename", 4, T_REQUIRED
, "%s", a4
);
558 result
= test_dns_rbt_x("dns_rbt_deletename_1_data");
562 static const char *a5
= "when name does not exist, dns_rbt_deletename() "
563 "returns ISC_R_NOTFOUND";
568 t_assert("dns_rbt_deletename", 5, T_REQUIRED
, "%s", a5
);
569 result
= test_dns_rbt_x("dns_rbt_deletename_2_data");
573 static const char *a6
= "when name exists and exactly matches the "
574 "search name dns_rbt_findname() returns ISC_R_SUCCESS";
580 t_assert("dns_rbt_findname", 6, T_REQUIRED
, "%s", a6
);
581 result
= test_dns_rbt_x("dns_rbt_findname_1_data");
585 static const char *a7
= "when a name does not exist, "
586 "dns_rbt_findname returns ISC_R_NOTFOUND";
592 t_assert("dns_rbt_findname", 7, T_REQUIRED
, "%s", a7
);
593 result
= test_dns_rbt_x("dns_rbt_findname_2_data");
597 static const char *a8
= "when a superdomain is found with data matching name, "
598 "dns_rbt_findname returns DNS_R_PARTIALMATCH";
604 t_assert("dns_rbt_findname", 8, T_REQUIRED
, "%s", a8
);
605 result
= test_dns_rbt_x("dns_rbt_findname_3_data");
610 static const char *a9
= "a call to dns_rbtnodechain_init(chain, mctx) "
614 t9_walkchain(dns_rbtnodechain_t
*chain
, dns_rbt_t
*rbt
) {
617 unsigned int nlabels
;
619 isc_result_t dns_result
;
621 dns_fixedname_t name
;
622 dns_fixedname_t origin
;
623 dns_fixedname_t fullname1
;
624 dns_fixedname_t fullname2
;
632 dns_fixedname_init(&name
);
633 dns_fixedname_init(&origin
);
634 dns_result
= dns_rbtnodechain_first(chain
, rbt
,
635 dns_fixedname_name(&name
),
636 dns_fixedname_name(&origin
));
637 if (dns_result
!= DNS_R_NEWORIGIN
) {
638 t_info("dns_rbtnodechain_first returned %s, "
639 "expecting DNS_R_NEWORIGIN\n",
640 dns_result_totext(dns_result
));
644 t_info("first name:\t<%s>\n", fixedname_totext(&name
));
645 t_info("first origin:\t<%s>\n",
646 fixedname_totext(&origin
));
648 dns_fixedname_init(&fullname1
);
649 dns_result
= dns_name_concatenate(
650 dns_fixedname_name(&name
),
651 dns_name_isabsolute(dns_fixedname_name(&name
)) ?
652 NULL
: dns_fixedname_name(&origin
),
653 dns_fixedname_name(&fullname1
), NULL
);
654 if (dns_result
!= ISC_R_SUCCESS
) {
655 t_info("dns_name_concatenate failed %s\n",
656 dns_result_totext(dns_result
));
662 * Expecting origin not to get touched if next
663 * doesn't return NEWORIGIN.
665 dns_fixedname_init(&name
);
666 dns_result
= dns_rbtnodechain_next(chain
,
667 dns_fixedname_name(&name
),
668 dns_fixedname_name(&origin
));
669 if ((dns_result
!= ISC_R_SUCCESS
) &&
670 (dns_result
!= DNS_R_NEWORIGIN
)) {
671 if (dns_result
!= ISC_R_NOMORE
) {
672 t_info("dns_rbtnodechain_next "
674 dns_result_totext(dns_result
));
680 t_info("next name:\t<%s>\n", fixedname_totext(&name
));
681 t_info("next origin:\t<%s>\n",
682 fixedname_totext(&origin
));
684 dns_fixedname_init(&fullname2
);
685 dns_result
= dns_name_concatenate(
686 dns_fixedname_name(&name
),
687 dns_name_isabsolute(dns_fixedname_name(&name
)) ?
688 NULL
: dns_fixedname_name(&origin
),
689 dns_fixedname_name(&fullname2
), NULL
);
690 if (dns_result
!= ISC_R_SUCCESS
) {
691 t_info("dns_name_concatenate failed %s\n",
692 dns_result_totext(dns_result
));
697 t_info("comparing\t<%s>\n",
698 fixedname_totext(&fullname1
));
699 t_info("\twith\t<%s>\n", fixedname_totext(&fullname2
));
701 (void)dns_name_fullcompare(
702 dns_fixedname_name(&fullname1
),
703 dns_fixedname_name(&fullname2
),
707 t_info("unexpected order %s %s %s\n",
708 dnsname_totext(dns_fixedname_name(&fullname1
)),
709 order
== -1 ? "<" : (order
== 0 ? "==" : ">"),
710 dnsname_totext(dns_fixedname_name(&fullname2
)));
722 * Test by exercising the first|last|next|prev funcs in useful ways.
726 t_namechk(isc_result_t dns_result
, dns_fixedname_t
*dns_name
, char *exp_name
,
727 dns_fixedname_t
*dns_origin
, char *exp_origin
,
728 isc_result_t exp_result
)
734 if (fixedname_cmp(dns_name
, exp_name
)) {
735 t_info("\texpected name of %s, got %s\n",
736 exp_name
, fixedname_totext(dns_name
));
739 if (exp_origin
!= NULL
) {
740 t_info("checking for DNS_R_NEWORIGIN\n");
741 if (dns_result
== exp_result
) {
742 if (fixedname_cmp(dns_origin
, exp_origin
)) {
743 t_info("\torigin %s, expected %s\n",
744 fixedname_totext(dns_origin
),
749 t_info("\tgot %s\n", dns_result_totext(dns_result
));
757 t_dns_rbtnodechain_init(char *dbfile
, char *findname
,
758 char *nextname
, char *nextorigin
,
759 char *prevname
, char *prevorigin
,
760 char *firstname
, char *firstorigin
,
761 char *lastname
, char *lastorigin
)
768 dns_rbtnodechain_t chain
;
771 isc_result_t isc_result
;
772 isc_result_t dns_result
;
773 dns_fixedname_t dns_findname
;
774 dns_fixedname_t dns_foundname
;
775 dns_fixedname_t dns_firstname
;
776 dns_fixedname_t dns_lastname
;
777 dns_fixedname_t dns_prevname
;
778 dns_fixedname_t dns_nextname
;
779 dns_fixedname_t dns_origin
;
780 isc_buffer_t isc_buffer
;
782 result
= T_UNRESOLVED
;
788 isc_result
= isc_mem_create(0, 0, &mctx
);
789 if (isc_result
!= ISC_R_SUCCESS
) {
790 t_info("isc_mem_create failed %s\n",
791 isc_result_totext(isc_result
));
795 isc_result
= isc_entropy_create(mctx
, &ectx
);
796 if (isc_result
!= ISC_R_SUCCESS
) {
797 t_info("isc_entropy_create: %s: exiting\n",
798 dns_result_totext(isc_result
));
799 isc_mem_destroy(&mctx
);
800 return(T_UNRESOLVED
);
803 isc_result
= isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
);
804 if (isc_result
!= ISC_R_SUCCESS
) {
805 t_info("isc_hash_create: %s: exiting\n",
806 dns_result_totext(isc_result
));
807 isc_entropy_detach(&ectx
);
808 isc_mem_destroy(&mctx
);
809 return(T_UNRESOLVED
);
812 dns_rbtnodechain_init(&chain
, mctx
);
815 if (rbt_init(dbfile
, &rbt
, mctx
)) {
816 t_info("rbt_init %s failed\n", dbfile
);
818 isc_entropy_detach(&ectx
);
819 isc_mem_destroy(&mctx
);
823 len
= strlen(findname
);
824 isc_buffer_init(&isc_buffer
, findname
, len
);
825 isc_buffer_add(&isc_buffer
, len
);
827 dns_fixedname_init(&dns_foundname
);
828 dns_fixedname_init(&dns_findname
);
829 dns_fixedname_init(&dns_firstname
);
830 dns_fixedname_init(&dns_origin
);
831 dns_fixedname_init(&dns_lastname
);
832 dns_fixedname_init(&dns_prevname
);
833 dns_fixedname_init(&dns_nextname
);
835 dns_result
= dns_name_fromtext(dns_fixedname_name(&dns_findname
),
836 &isc_buffer
, NULL
, 0, NULL
);
838 if (dns_result
!= ISC_R_SUCCESS
) {
839 t_info("dns_name_fromtext failed %s\n",
840 dns_result_totext(dns_result
));
845 * Set the starting node.
848 dns_result
= dns_rbt_findnode(rbt
, dns_fixedname_name(&dns_findname
),
849 dns_fixedname_name(&dns_foundname
),
850 &node
, &chain
, DNS_RBTFIND_EMPTYDATA
,
853 if (dns_result
!= ISC_R_SUCCESS
) {
854 t_info("dns_rbt_findnode failed %s\n",
855 dns_result_totext(dns_result
));
862 t_info("checking for next name of %s and new origin of %s\n",
863 nextname
, nextorigin
);
864 dns_result
= dns_rbtnodechain_next(&chain
,
865 dns_fixedname_name(&dns_nextname
),
866 dns_fixedname_name(&dns_origin
));
868 if ((dns_result
!= ISC_R_SUCCESS
) &&
869 (dns_result
!= DNS_R_NEWORIGIN
)) {
870 t_info("dns_rbtnodechain_next unexpectedly returned %s\n",
871 dns_result_totext(dns_result
));
874 nfails
+= t_namechk(dns_result
, &dns_nextname
, nextname
, &dns_origin
,
875 nextorigin
, DNS_R_NEWORIGIN
);
878 * Set the starting node again.
881 dns_fixedname_init(&dns_foundname
);
882 dns_result
= dns_rbt_findnode(rbt
, dns_fixedname_name(&dns_findname
),
883 dns_fixedname_name(&dns_foundname
),
884 &node
, &chain
, DNS_RBTFIND_EMPTYDATA
,
887 if (dns_result
!= ISC_R_SUCCESS
) {
888 t_info("\tdns_rbt_findnode failed %s\n",
889 dns_result_totext(dns_result
));
896 t_info("checking for previous name of %s and new origin of %s\n",
897 prevname
, prevorigin
);
898 dns_fixedname_init(&dns_origin
);
899 dns_result
= dns_rbtnodechain_prev(&chain
,
900 dns_fixedname_name(&dns_prevname
),
901 dns_fixedname_name(&dns_origin
));
903 if ((dns_result
!= ISC_R_SUCCESS
) &&
904 (dns_result
!= DNS_R_NEWORIGIN
)) {
905 t_info("dns_rbtnodechain_prev unexpectedly returned %s\n",
906 dns_result_totext(dns_result
));
908 nfails
+= t_namechk(dns_result
, &dns_prevname
, prevname
, &dns_origin
,
909 prevorigin
, DNS_R_NEWORIGIN
);
914 t_info("checking for first name of %s and new origin of %s\n",
915 firstname
, firstorigin
);
916 dns_result
= dns_rbtnodechain_first(&chain
, rbt
,
917 dns_fixedname_name(&dns_firstname
),
918 dns_fixedname_name(&dns_origin
));
920 if (dns_result
!= DNS_R_NEWORIGIN
) {
921 t_info("dns_rbtnodechain_first unexpectedly returned %s\n",
922 dns_result_totext(dns_result
));
924 nfails
+= t_namechk(dns_result
, &dns_firstname
, firstname
,
925 &dns_origin
, firstorigin
, DNS_R_NEWORIGIN
);
930 t_info("checking for last name of %s\n", lastname
);
931 dns_result
= dns_rbtnodechain_last(&chain
, rbt
,
932 dns_fixedname_name(&dns_lastname
),
933 dns_fixedname_name(&dns_origin
));
935 if (dns_result
!= DNS_R_NEWORIGIN
) {
936 t_info("dns_rbtnodechain_last unexpectedly returned %s\n",
937 dns_result_totext(dns_result
));
939 nfails
+= t_namechk(dns_result
, &dns_lastname
, lastname
, &dns_origin
,
940 lastorigin
, DNS_R_NEWORIGIN
);
943 * Check node ordering.
945 t_info("checking node ordering\n");
946 nfails
+= t9_walkchain(&chain
, rbt
);
953 dns_rbtnodechain_invalidate(&chain
);
954 dns_rbt_destroy(&rbt
);
957 isc_entropy_detach(&ectx
);
958 isc_mem_destroy(&mctx
);
964 test_dns_rbtnodechain_init(const char *filename
) {
976 fp
= fopen(filename
, "r");
979 while ((p
= t_fgetbs(fp
)) != NULL
) {
984 * Skip comment lines.
986 if ((isspace((unsigned char)*p
)) || (*p
== '#')) {
991 cnt
= t_bustline(p
, Tokens
);
993 result
= t_dns_rbtnodechain_init(
994 Tokens
[0], /* dbfile */
995 Tokens
[1], /* startname */
996 Tokens
[2], /* nextname */
997 Tokens
[3], /* nextorigin */
998 Tokens
[4], /* prevname */
999 Tokens
[5], /* prevorigin */
1000 Tokens
[6], /* firstname */
1001 Tokens
[7], /* firstorigin */
1002 Tokens
[8], /* lastname */
1003 Tokens
[9]); /* lastorigin */
1004 if (result
!= T_PASS
) {
1005 if (result
== T_FAIL
)
1011 t_info("bad format in %s at line %d\n",
1020 t_info("Missing datafile %s\n", filename
);
1024 result
= T_UNRESOLVED
;
1026 if ((nfails
== 0) && (nprobs
== 0))
1038 t_assert("dns_rbtnodechain_init", 9, T_REQUIRED
, "%s", a9
);
1039 result
= test_dns_rbtnodechain_init("dns_rbtnodechain_init_data");
1044 t_dns_rbtnodechain_first(char *dbfile
, char *expected_firstname
,
1045 char *expected_firstorigin
,
1046 char *expected_nextname
,
1047 char *expected_nextorigin
)
1052 dns_rbtnodechain_t chain
;
1054 isc_entropy_t
*ectx
;
1055 isc_result_t isc_result
;
1056 isc_result_t dns_result
;
1057 dns_fixedname_t dns_name
;
1058 dns_fixedname_t dns_origin
;
1059 isc_result_t expected_result
;
1061 REQUIRE(dbfile
!= NULL
);
1062 REQUIRE(expected_firstname
!= NULL
);
1063 REQUIRE(expected_firstorigin
!= NULL
);
1064 REQUIRE(expected_nextname
!= NULL
);
1065 REQUIRE(expected_nextorigin
!= NULL
);
1067 result
= T_UNRESOLVED
;
1073 dns_fixedname_init(&dns_name
);
1074 dns_fixedname_init(&dns_origin
);
1076 isc_result
= isc_mem_create(0, 0, &mctx
);
1077 if (isc_result
!= ISC_R_SUCCESS
) {
1078 t_info("isc_mem_create failed %s\n",
1079 isc_result_totext(isc_result
));
1083 isc_result
= isc_entropy_create(mctx
, &ectx
);
1084 if (isc_result
!= ISC_R_SUCCESS
) {
1085 t_info("isc_entropy_create: %s: exiting\n",
1086 dns_result_totext(isc_result
));
1087 isc_mem_destroy(&mctx
);
1088 return(T_UNRESOLVED
);
1091 isc_result
= isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
);
1092 if (isc_result
!= ISC_R_SUCCESS
) {
1093 t_info("isc_hash_create: %s: exiting\n",
1094 dns_result_totext(isc_result
));
1095 isc_entropy_detach(&ectx
);
1096 isc_mem_destroy(&mctx
);
1097 return(T_UNRESOLVED
);
1100 dns_rbtnodechain_init(&chain
, mctx
);
1103 if (rbt_init(dbfile
, &rbt
, mctx
)) {
1104 t_info("rbt_init %s failed\n", dbfile
);
1106 isc_entropy_detach(&ectx
);
1107 isc_mem_destroy(&mctx
);
1111 t_info("testing for first name of %s, origin of %s\n",
1112 expected_firstname
, expected_firstorigin
);
1114 dns_result
= dns_rbtnodechain_first(&chain
, rbt
,
1115 dns_fixedname_name(&dns_name
),
1116 dns_fixedname_name(&dns_origin
));
1118 if (dns_result
!= DNS_R_NEWORIGIN
)
1119 t_info("dns_rbtnodechain_first unexpectedly returned %s\n",
1120 dns_result_totext(dns_result
));
1122 nfails
+= t_namechk(dns_result
, &dns_name
, expected_firstname
,
1123 &dns_origin
, expected_firstorigin
, DNS_R_NEWORIGIN
);
1125 dns_fixedname_init(&dns_name
);
1126 dns_result
= dns_rbtnodechain_next(&chain
,
1127 dns_fixedname_name(&dns_name
),
1128 dns_fixedname_name(&dns_origin
));
1130 t_info("testing for next name of %s, origin of %s\n",
1131 expected_nextname
, expected_nextorigin
);
1133 if ((dns_result
!= ISC_R_SUCCESS
) && (dns_result
!= DNS_R_NEWORIGIN
))
1134 t_info("dns_rbtnodechain_next unexpectedly returned %s\n",
1135 dns_result_totext(dns_result
));
1137 if (strcasecmp(expected_firstorigin
, expected_nextorigin
) == 0)
1138 expected_result
= ISC_R_SUCCESS
;
1140 expected_result
= DNS_R_NEWORIGIN
;
1141 nfails
+= t_namechk(dns_result
, &dns_name
, expected_nextname
,
1142 &dns_origin
, expected_nextorigin
, expected_result
);
1149 dns_rbtnodechain_invalidate(&chain
);
1151 dns_rbt_destroy(&rbt
);
1153 isc_entropy_detach(&ectx
);
1154 isc_mem_destroy(&mctx
);
1159 test_dns_rbtnodechain_first(const char *filename
) {
1171 fp
= fopen(filename
, "r");
1174 while ((p
= t_fgetbs(fp
)) != NULL
) {
1179 * Skip comment lines.
1181 if ((isspace((unsigned char)*p
)) || (*p
== '#')) {
1186 cnt
= t_bustline(p
, Tokens
);
1188 result
= t_dns_rbtnodechain_first(
1189 Tokens
[0], /* dbfile */
1190 Tokens
[1], /* firstname */
1191 Tokens
[2], /* firstorigin */
1192 Tokens
[3], /* nextname */
1193 Tokens
[4]); /* nextorigin */
1194 if (result
!= T_PASS
) {
1195 if (result
== T_FAIL
)
1201 t_info("bad format in %s at line %d\n",
1210 t_info("Missing datafile %s\n", filename
);
1214 result
= T_UNRESOLVED
;
1216 if ((nfails
== 0) && (nprobs
== 0))
1224 static const char *a10
= "a call to "
1225 "dns_rbtnodechain_first(chain, rbt, name, origin) "
1226 "sets name to point to the root of the tree, "
1227 "origin to point to the origin, "
1228 "and returns DNS_R_NEWORIGIN";
1234 t_assert("dns_rbtnodechain_first", 10, T_REQUIRED
, "%s", a10
);
1235 result
= test_dns_rbtnodechain_first("dns_rbtnodechain_first_data");
1240 t_dns_rbtnodechain_last(char *dbfile
, char *expected_lastname
,
1241 char *expected_lastorigin
,
1242 char *expected_prevname
,
1243 char *expected_prevorigin
)
1249 dns_rbtnodechain_t chain
;
1251 isc_entropy_t
*ectx
;
1252 isc_result_t isc_result
;
1253 isc_result_t dns_result
;
1254 dns_fixedname_t dns_name
;
1255 dns_fixedname_t dns_origin
;
1256 isc_result_t expected_result
;
1258 REQUIRE(dbfile
!= NULL
);
1259 REQUIRE(expected_lastname
!= NULL
);
1260 REQUIRE(expected_lastorigin
!= NULL
);
1261 REQUIRE(expected_prevname
!= NULL
);
1262 REQUIRE(expected_prevorigin
!= NULL
);
1264 result
= T_UNRESOLVED
;
1270 dns_fixedname_init(&dns_name
);
1271 dns_fixedname_init(&dns_origin
);
1273 isc_result
= isc_mem_create(0, 0, &mctx
);
1274 if (isc_result
!= ISC_R_SUCCESS
) {
1275 t_info("isc_mem_create failed %s\n",
1276 isc_result_totext(isc_result
));
1280 isc_result
= isc_entropy_create(mctx
, &ectx
);
1281 if (isc_result
!= ISC_R_SUCCESS
) {
1282 t_info("isc_entropy_create: %s: exiting\n",
1283 dns_result_totext(isc_result
));
1284 isc_mem_destroy(&mctx
);
1285 return(T_UNRESOLVED
);
1288 isc_result
= isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
);
1289 if (isc_result
!= ISC_R_SUCCESS
) {
1290 t_info("isc_hash_create: %s: exiting\n",
1291 dns_result_totext(isc_result
));
1292 isc_entropy_detach(&ectx
);
1293 isc_mem_destroy(&mctx
);
1294 return(T_UNRESOLVED
);
1297 dns_rbtnodechain_init(&chain
, mctx
);
1300 if (rbt_init(dbfile
, &rbt
, mctx
)) {
1301 t_info("rbt_init %s failed\n", dbfile
);
1303 isc_entropy_detach(&ectx
);
1304 isc_mem_destroy(&mctx
);
1308 t_info("testing for last name of %s, origin of %s\n",
1309 expected_lastname
, expected_lastorigin
);
1311 dns_result
= dns_rbtnodechain_last(&chain
, rbt
,
1312 dns_fixedname_name(&dns_name
),
1313 dns_fixedname_name(&dns_origin
));
1315 if (dns_result
!= DNS_R_NEWORIGIN
) {
1316 t_info("dns_rbtnodechain_last unexpectedly returned %s\n",
1317 dns_result_totext(dns_result
));
1319 nfails
+= t_namechk(dns_result
, &dns_name
, expected_lastname
,
1320 &dns_origin
, expected_lastorigin
, DNS_R_NEWORIGIN
);
1322 t_info("testing for previous name of %s, origin of %s\n",
1323 expected_prevname
, expected_prevorigin
);
1325 dns_fixedname_init(&dns_name
);
1326 dns_result
= dns_rbtnodechain_prev(&chain
,
1327 dns_fixedname_name(&dns_name
),
1328 dns_fixedname_name(&dns_origin
));
1330 if ((dns_result
!= ISC_R_SUCCESS
) &&
1331 (dns_result
!= DNS_R_NEWORIGIN
)) {
1332 t_info("dns_rbtnodechain_prev unexpectedly returned %s\n",
1333 dns_result_totext(dns_result
));
1335 if (strcasecmp(expected_lastorigin
, expected_prevorigin
) == 0)
1336 expected_result
= ISC_R_SUCCESS
;
1338 expected_result
= DNS_R_NEWORIGIN
;
1339 nfails
+= t_namechk(dns_result
, &dns_name
, expected_prevname
,
1340 &dns_origin
, expected_prevorigin
, expected_result
);
1347 dns_rbtnodechain_invalidate(&chain
);
1348 dns_rbt_destroy(&rbt
);
1351 isc_entropy_detach(&ectx
);
1352 isc_mem_destroy(&mctx
);
1358 test_dns_rbtnodechain_last(const char *filename
) {
1370 fp
= fopen(filename
, "r");
1373 while ((p
= t_fgetbs(fp
)) != NULL
) {
1378 * Skip comment lines.
1380 if ((isspace((unsigned char)*p
)) || (*p
== '#')) {
1385 cnt
= t_bustline(p
, Tokens
);
1387 result
= t_dns_rbtnodechain_last(
1388 Tokens
[0], /* dbfile */
1389 Tokens
[1], /* lastname */
1390 Tokens
[2], /* lastorigin */
1391 Tokens
[3], /* prevname */
1392 Tokens
[4]); /* prevorigin */
1393 if (result
!= T_PASS
) {
1394 if (result
== T_FAIL
)
1400 t_info("bad format in %s at line %d\n",
1409 t_info("Missing datafile %s\n", filename
);
1413 result
= T_UNRESOLVED
;
1415 if ((nfails
== 0) && (nprobs
== 0))
1423 static const char *a11
= "a call to "
1424 "dns_rbtnodechain_last(chain, rbt, name, origin) "
1425 "sets name to point to the last node of the megatree, "
1426 "origin to the name of the level above it, "
1427 "and returns DNS_R_NEWORIGIN";
1433 t_assert("dns_rbtnodechain_last", 11, T_REQUIRED
, "%s", a11
);
1434 result
= test_dns_rbtnodechain_last("dns_rbtnodechain_last_data");
1439 t_dns_rbtnodechain_next(char *dbfile
, char *findname
,
1440 char *nextname
, char *nextorigin
)
1447 dns_rbtnode_t
*node
;
1448 dns_rbtnodechain_t chain
;
1450 isc_entropy_t
*ectx
;
1451 isc_result_t isc_result
;
1452 isc_result_t dns_result
;
1453 dns_fixedname_t dns_findname
;
1454 dns_fixedname_t dns_foundname
;
1455 dns_fixedname_t dns_nextname
;
1456 dns_fixedname_t dns_origin
;
1457 isc_buffer_t isc_buffer
;
1459 result
= T_UNRESOLVED
;
1465 isc_result
= isc_mem_create(0, 0, &mctx
);
1466 if (isc_result
!= ISC_R_SUCCESS
) {
1467 t_info("isc_mem_create failed %s\n",
1468 isc_result_totext(isc_result
));
1472 isc_result
= isc_entropy_create(mctx
, &ectx
);
1473 if (isc_result
!= ISC_R_SUCCESS
) {
1474 t_info("isc_entropy_create: %s: exiting\n",
1475 dns_result_totext(isc_result
));
1476 isc_mem_destroy(&mctx
);
1477 return(T_UNRESOLVED
);
1480 isc_result
= isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
);
1481 if (isc_result
!= ISC_R_SUCCESS
) {
1482 t_info("isc_hash_create: %s: exiting\n",
1483 dns_result_totext(isc_result
));
1484 isc_entropy_detach(&ectx
);
1485 isc_mem_destroy(&mctx
);
1486 return(T_UNRESOLVED
);
1489 dns_rbtnodechain_init(&chain
, mctx
);
1492 if (rbt_init(dbfile
, &rbt
, mctx
)) {
1493 t_info("rbt_init %s failed\n", dbfile
);
1495 isc_entropy_detach(&ectx
);
1496 isc_mem_destroy(&mctx
);
1500 len
= strlen(findname
);
1501 isc_buffer_init(&isc_buffer
, findname
, len
);
1502 isc_buffer_add(&isc_buffer
, len
);
1504 dns_fixedname_init(&dns_foundname
);
1505 dns_fixedname_init(&dns_findname
);
1506 dns_fixedname_init(&dns_nextname
);
1507 dns_fixedname_init(&dns_origin
);
1509 dns_result
= dns_name_fromtext(dns_fixedname_name(&dns_findname
),
1510 &isc_buffer
, NULL
, 0, NULL
);
1512 if (dns_result
!= ISC_R_SUCCESS
) {
1513 t_info("dns_name_fromtext failed %s\n",
1514 dns_result_totext(dns_result
));
1519 * Set the starting node.
1522 dns_result
= dns_rbt_findnode(rbt
, dns_fixedname_name(&dns_findname
),
1523 dns_fixedname_name(&dns_foundname
),
1524 &node
, &chain
, DNS_RBTFIND_EMPTYDATA
,
1527 if (dns_result
!= ISC_R_SUCCESS
) {
1528 t_info("dns_rbt_findnode failed %s\n",
1529 dns_result_totext(dns_result
));
1536 t_info("checking for next name of %s and new origin of %s\n",
1537 nextname
, nextorigin
);
1538 dns_result
= dns_rbtnodechain_next(&chain
,
1539 dns_fixedname_name(&dns_nextname
),
1540 dns_fixedname_name(&dns_origin
));
1542 if ((dns_result
!= ISC_R_SUCCESS
) && (dns_result
!= DNS_R_NEWORIGIN
)) {
1543 t_info("dns_rbtnodechain_next unexpectedly returned %s\n",
1544 dns_result_totext(dns_result
));
1547 nfails
+= t_namechk(dns_result
, &dns_nextname
, nextname
, &dns_origin
,
1548 nextorigin
, DNS_R_NEWORIGIN
);
1555 dns_rbtnodechain_invalidate(&chain
);
1556 dns_rbt_destroy(&rbt
);
1559 isc_entropy_detach(&ectx
);
1560 isc_mem_destroy(&mctx
);
1566 test_dns_rbtnodechain_next(const char *filename
) {
1578 fp
= fopen(filename
, "r");
1581 while ((p
= t_fgetbs(fp
)) != NULL
) {
1586 * Skip comment lines.
1588 if ((isspace((unsigned char)*p
)) || (*p
== '#')) {
1593 cnt
= t_bustline(p
, Tokens
);
1595 result
= t_dns_rbtnodechain_next(
1596 Tokens
[0], /* dbfile */
1597 Tokens
[1], /* findname */
1598 Tokens
[2], /* nextname */
1599 Tokens
[3]); /* nextorigin */
1600 if (result
!= T_PASS
) {
1601 if (result
== T_FAIL
)
1607 t_info("bad format in %s at line %d\n",
1616 t_info("Missing datafile %s\n", filename
);
1620 result
= T_UNRESOLVED
;
1622 if ((nfails
== 0) && (nprobs
== 0))
1630 static const char *a12
= "a call to "
1631 "dns_rbtnodechain_next(chain, name, origin) "
1632 "sets name to point to the next node of the tree "
1633 "and returns ISC_R_SUCCESS or "
1634 "DNS_R_NEWORIGIN on success";
1641 t_assert("dns_rbtnodechain_next", 12, T_REQUIRED
, "%s", a12
);
1642 result
= test_dns_rbtnodechain_next("dns_rbtnodechain_next_data");
1647 t_dns_rbtnodechain_prev(char *dbfile
, char *findname
, char *prevname
,
1654 dns_rbtnode_t
*node
;
1655 dns_rbtnodechain_t chain
;
1657 isc_entropy_t
*ectx
= NULL
;
1658 isc_result_t isc_result
;
1659 isc_result_t dns_result
;
1660 dns_fixedname_t dns_findname
;
1661 dns_fixedname_t dns_foundname
;
1662 dns_fixedname_t dns_prevname
;
1663 dns_fixedname_t dns_origin
;
1664 isc_buffer_t isc_buffer
;
1666 result
= T_UNRESOLVED
;
1672 isc_result
= isc_mem_create(0, 0, &mctx
);
1673 if (isc_result
!= ISC_R_SUCCESS
) {
1674 t_info("isc_mem_create failed %s\n",
1675 isc_result_totext(isc_result
));
1679 isc_result
= isc_entropy_create(mctx
, &ectx
);
1680 if (isc_result
!= ISC_R_SUCCESS
) {
1681 t_info("isc_entropy_create: %s: exiting\n",
1682 dns_result_totext(isc_result
));
1683 isc_mem_destroy(&mctx
);
1684 return(T_UNRESOLVED
);
1687 isc_result
= isc_hash_create(mctx
, ectx
, DNS_NAME_MAXWIRE
);
1688 if (isc_result
!= ISC_R_SUCCESS
) {
1689 t_info("isc_hash_create: %s: exiting\n",
1690 dns_result_totext(isc_result
));
1691 isc_entropy_detach(&ectx
);
1692 isc_mem_destroy(&mctx
);
1693 return(T_UNRESOLVED
);
1696 dns_rbtnodechain_init(&chain
, mctx
);
1699 if (rbt_init(dbfile
, &rbt
, mctx
)) {
1700 t_info("rbt_init %s failed\n", dbfile
);
1702 isc_entropy_detach(&ectx
);
1703 isc_mem_destroy(&mctx
);
1707 len
= strlen(findname
);
1708 isc_buffer_init(&isc_buffer
, findname
, len
);
1709 isc_buffer_add(&isc_buffer
, len
);
1711 dns_fixedname_init(&dns_foundname
);
1712 dns_fixedname_init(&dns_findname
);
1713 dns_fixedname_init(&dns_prevname
);
1714 dns_fixedname_init(&dns_origin
);
1716 dns_result
= dns_name_fromtext(dns_fixedname_name(&dns_findname
),
1717 &isc_buffer
, NULL
, 0, NULL
);
1719 if (dns_result
!= ISC_R_SUCCESS
) {
1720 t_info("dns_name_fromtext failed %s\n",
1721 dns_result_totext(dns_result
));
1726 * Set the starting node.
1729 dns_result
= dns_rbt_findnode(rbt
, dns_fixedname_name(&dns_findname
),
1730 dns_fixedname_name(&dns_foundname
),
1731 &node
, &chain
, DNS_RBTFIND_EMPTYDATA
,
1734 if (dns_result
!= ISC_R_SUCCESS
) {
1735 t_info("dns_rbt_findnode failed %s\n",
1736 dns_result_totext(dns_result
));
1743 t_info("checking for next name of %s and new origin of %s\n",
1744 prevname
, prevorigin
);
1745 dns_result
= dns_rbtnodechain_prev(&chain
,
1746 dns_fixedname_name(&dns_prevname
),
1747 dns_fixedname_name(&dns_origin
));
1749 if ((dns_result
!= ISC_R_SUCCESS
) && (dns_result
!= DNS_R_NEWORIGIN
)) {
1750 t_info("dns_rbtnodechain_prev unexpectedly returned %s\n",
1751 dns_result_totext(dns_result
));
1754 nfails
+= t_namechk(dns_result
, &dns_prevname
, prevname
, &dns_origin
,
1755 prevorigin
, DNS_R_NEWORIGIN
);
1762 dns_rbtnodechain_invalidate(&chain
);
1763 dns_rbt_destroy(&rbt
);
1766 isc_entropy_detach(&ectx
);
1767 isc_mem_destroy(&mctx
);
1773 test_dns_rbtnodechain_prev(const char *filename
) {
1785 fp
= fopen(filename
, "r");
1788 while ((p
= t_fgetbs(fp
)) != NULL
) {
1793 * Skip comment lines.
1795 if ((isspace((unsigned char)*p
)) || (*p
== '#')) {
1800 cnt
= t_bustline(p
, Tokens
);
1802 result
= t_dns_rbtnodechain_prev(
1803 Tokens
[0], /* dbfile */
1804 Tokens
[1], /* findname */
1805 Tokens
[2], /* prevname */
1806 Tokens
[3]); /* prevorigin */
1807 if (result
!= T_PASS
) {
1808 if (result
== T_FAIL
)
1814 t_info("bad format in %s at line %d\n",
1823 t_info("Missing datafile %s\n", filename
);
1827 result
= T_UNRESOLVED
;
1829 if ((nfails
== 0) && (nprobs
== 0))
1837 static const char *a13
= "a call to "
1838 "dns_rbtnodechain_prev(chain, name, origin) "
1839 "sets name to point to the previous node of the tree "
1840 "and returns ISC_R_SUCCESS or "
1841 "DNS_R_NEWORIGIN on success";
1847 t_assert("dns_rbtnodechain_prev", 13, T_REQUIRED
, "%s", a13
);
1848 result
= test_dns_rbtnodechain_prev("dns_rbtnodechain_prev_data");
1852 testspec_t T_testlist
[] = {
1853 { (PFV
) t1
, "dns_rbt_create" },
1854 { (PFV
) t2
, "dns_rbt_addname 1" },
1855 { (PFV
) t3
, "dns_rbt_addname 2" },
1856 { (PFV
) t4
, "dns_rbt_deletename 1" },
1857 { (PFV
) t5
, "dns_rbt_deletename 2" },
1858 { (PFV
) t6
, "dns_rbt_findname 1" },
1859 { (PFV
) t7
, "dns_rbt_findname 2" },
1860 { (PFV
) t8
, "dns_rbt_findname 3" },
1861 { (PFV
) t9
, "dns_rbtnodechain_init" },
1862 { (PFV
) t10
, "dns_rbtnodechain_first" },
1863 { (PFV
) t11
, "dns_rbtnodechain_last" },
1864 { (PFV
) t12
, "dns_rbtnodechain_next" },
1865 { (PFV
) t13
, "dns_rbtnodechain_prev" },
1871 main(int argc
, char **argv
) {
1872 t_settests(T_testlist
);
1873 return (t_main(argc
, argv
));