summaryrefslogtreecommitdiffstats
path: root/bin/tests/rbt/t_rbt.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/tests/rbt/t_rbt.c')
-rw-r--r--bin/tests/rbt/t_rbt.c1857
1 files changed, 1857 insertions, 0 deletions
diff --git a/bin/tests/rbt/t_rbt.c b/bin/tests/rbt/t_rbt.c
new file mode 100644
index 0000000..171e633
--- /dev/null
+++ b/bin/tests/rbt/t_rbt.c
@@ -0,0 +1,1857 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 1998-2001, 2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: t_rbt.c,v 1.30 2007/06/19 23:47:00 tbox Exp $ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <isc/entropy.h>
+#include <isc/mem.h>
+#include <isc/util.h>
+#include <isc/hash.h>
+#include <isc/string.h>
+
+#include <dns/fixedname.h>
+#include <dns/rbt.h>
+#include <dns/result.h>
+
+#include <tests/t_api.h>
+
+#define BUFLEN 1024
+#define DNSNAMELEN 255
+
+char *progname;
+char *Tokens[T_MAXTOKS];
+
+static int
+t_dns_rbtnodechain_init(char *dbfile, char *findname,
+ char *firstname, char *firstorigin,
+ char *nextname, char *nextorigin,
+ char *prevname, char *prevorigin,
+ char *lastname, char *lastorigin);
+static char *
+fixedname_totext(dns_fixedname_t *name);
+
+static int
+fixedname_cmp(dns_fixedname_t *dns_name, char *txtname);
+
+static char *
+dnsname_totext(dns_name_t *name);
+
+static int
+t_namechk(isc_result_t dns_result, dns_fixedname_t *dns_name, char *exp_name,
+ dns_fixedname_t *dns_origin, char *exp_origin,
+ isc_result_t exp_result);
+
+/*
+ * Parts adapted from the original rbt_test.c.
+ */
+static int
+fixedname_cmp(dns_fixedname_t *dns_name, char *txtname) {
+ char *name;
+
+ name = dnsname_totext(dns_fixedname_name(dns_name));
+ if (strcmp(txtname, "NULL") == 0) {
+ if ((name == NULL) || (*name == '\0'))
+ return(0);
+ return(1);
+ } else {
+ return(strcmp(name, txtname));
+ }
+}
+
+static char *
+dnsname_totext(dns_name_t *name) {
+ static char buf[BUFLEN];
+ isc_buffer_t target;
+
+ isc_buffer_init(&target, buf, BUFLEN);
+ dns_name_totext(name, ISC_FALSE, &target);
+ *((char *)(target.base) + target.used) = '\0';
+ return(target.base);
+}
+
+static char *
+fixedname_totext(dns_fixedname_t *name) {
+ static char buf[BUFLEN];
+ isc_buffer_t target;
+
+ memset(buf, 0, BUFLEN);
+ isc_buffer_init(&target, buf, BUFLEN);
+ dns_name_totext(dns_fixedname_name(name), ISC_FALSE, &target);
+ *((char *)(target.base) + target.used) = '\0';
+ return(target.base);
+}
+
+#ifdef NEED_PRINT_DATA
+
+static isc_result_t
+print_data(void *data) {
+ isc_result_t dns_result;
+ isc_buffer_t target;
+ char *buffer[DNSNAMELEN];
+
+ isc_buffer_init(&target, buffer, sizeof(buffer));
+
+ dns_result = dns_name_totext(data, ISC_FALSE, &target);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_totext failed %s\n",
+ dns_result_totext(dns_result));
+ }
+ return(dns_result);
+}
+
+#endif /* NEED_PRINT_DATA */
+
+static int
+create_name(char *s, isc_mem_t *mctx, dns_name_t **dns_name) {
+ int nfails;
+ int length;
+ isc_result_t result;
+ isc_buffer_t source;
+ isc_buffer_t target;
+ dns_name_t *name;
+
+ nfails = 0;
+
+ if (s && *s) {
+
+ length = strlen(s);
+
+ isc_buffer_init(&source, s, length);
+ isc_buffer_add(&source, length);
+
+ /*
+ * The buffer for the actual name will immediately follow the
+ * name structure.
+ */
+ name = isc_mem_get(mctx, sizeof(*name) + DNSNAMELEN);
+ if (name == NULL) {
+ t_info("isc_mem_get failed\n");
+ ++nfails;
+ } else {
+
+ dns_name_init(name, NULL);
+ isc_buffer_init(&target, name + 1, DNSNAMELEN);
+
+ result = dns_name_fromtext(name, &source, dns_rootname,
+ ISC_FALSE, &target);
+
+ if (result != ISC_R_SUCCESS) {
+ ++nfails;
+ t_info("dns_name_fromtext(%s) failed %s\n",
+ s, dns_result_totext(result));
+ isc_mem_put(mctx, name,
+ sizeof(*name) + DNSNAMELEN);
+ } else
+ *dns_name = name;
+ }
+ } else {
+ ++nfails;
+ t_info("create_name: empty name\n");
+ }
+
+ return(nfails);
+}
+
+static void
+delete_name(void *data, void *arg) {
+ isc_mem_put((isc_mem_t *)arg, data, sizeof(dns_name_t) + DNSNAMELEN);
+}
+
+
+/*
+ * Adapted from the original rbt_test.c.
+ */
+static int
+t1_add(char *name, dns_rbt_t *rbt, isc_mem_t *mctx, isc_result_t *dns_result) {
+ int nprobs;
+ dns_name_t *dns_name;
+
+ nprobs = 0;
+ if (name && dns_result) {
+ if (create_name(name, mctx, &dns_name) == 0) {
+ if (T_debug)
+ t_info("dns_rbt_addname succeeded\n");
+ *dns_result = dns_rbt_addname(rbt, dns_name, dns_name);
+ if (*dns_result != ISC_R_SUCCESS) {
+ delete_name(dns_name, mctx);
+ t_info("dns_rbt_addname failed %s\n",
+ dns_result_totext(*dns_result));
+ ++nprobs;
+ }
+ } else {
+ ++nprobs;
+ }
+ } else {
+ ++nprobs;
+ }
+ return(nprobs);
+}
+
+static int
+t1_delete(char *name, dns_rbt_t *rbt, isc_mem_t *mctx,
+ isc_result_t *dns_result)
+{
+ int nprobs;
+ dns_name_t *dns_name;
+
+ nprobs = 0;
+ if (name && dns_result) {
+ if (create_name(name, mctx, &dns_name) == 0) {
+ *dns_result = dns_rbt_deletename(rbt, dns_name,
+ ISC_FALSE);
+ delete_name(dns_name, mctx);
+ } else {
+ ++nprobs;
+ }
+ } else {
+ ++nprobs;
+ }
+ return(nprobs);
+}
+
+static int
+t1_search(char *name, dns_rbt_t *rbt, isc_mem_t *mctx,
+ isc_result_t *dns_result)
+{
+ int nprobs;
+ dns_name_t *dns_searchname;
+ dns_name_t *dns_foundname;
+ dns_fixedname_t dns_fixedname;
+ void *data;
+
+ nprobs = 0;
+ if (name && dns_result) {
+ if (create_name(name, mctx, &dns_searchname) == 0) {
+ dns_fixedname_init(&dns_fixedname);
+ dns_foundname = dns_fixedname_name(&dns_fixedname);
+ data = NULL;
+ *dns_result = dns_rbt_findname(rbt, dns_searchname, 0,
+ dns_foundname, &data);
+ delete_name(dns_searchname, mctx);
+ } else {
+ ++nprobs;
+ }
+ } else {
+ ++nprobs;
+ }
+ return(nprobs);
+}
+
+/*
+ * Initialize a database from filename.
+ */
+static int
+rbt_init(char *filename, dns_rbt_t **rbt, isc_mem_t *mctx) {
+ int rval;
+ isc_result_t dns_result;
+ char *p;
+ FILE *fp;
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ t_info("No such file %s\n", filename);
+ return(1);
+ }
+
+ dns_result = dns_rbt_create(mctx, delete_name, mctx, rbt);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rbt_create failed %s\n",
+ dns_result_totext(dns_result));
+ fclose(fp);
+ return(1);
+ }
+
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ /*
+ * Skip any comment lines.
+ */
+ if ((*p == '#') || (*p == '\0') || (*p == ' ')) {
+ (void)free(p);
+ continue;
+ }
+
+ if (T_debug)
+ t_info("adding name %s to the rbt\n", p);
+
+ rval = t1_add(p, *rbt, mctx, &dns_result);
+ if ((rval != 0) || (dns_result != ISC_R_SUCCESS)) {
+ t_info("add of %s failed\n", p);
+ dns_rbt_destroy(rbt);
+ fclose(fp);
+ return(1);
+ }
+ (void) free(p);
+ }
+ fclose(fp);
+ return(0);
+}
+
+static int
+test_rbt_gen(char *filename, char *command, char *testname,
+ isc_result_t exp_result)
+{
+ int rval;
+ int result;
+ dns_rbt_t *rbt;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ dns_name_t *dns_name;
+
+ result = T_UNRESOLVED;
+
+ if (strcmp(command, "create") != 0)
+ t_info("testing using name %s\n", testname);
+
+ mctx = NULL;
+ ectx = NULL;
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ rbt = NULL;
+ if (rbt_init(filename, &rbt, mctx) != 0) {
+ if (strcmp(command, "create") == 0)
+ result = T_FAIL;
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ /*
+ * Now try the database command.
+ */
+ if (strcmp(command, "create") == 0) {
+ result = T_PASS;
+ } else if (strcmp(command, "add") == 0) {
+ if (create_name(testname, mctx, &dns_name) == 0) {
+ dns_result = dns_rbt_addname(rbt, dns_name, dns_name);
+
+ if (dns_result != ISC_R_SUCCESS)
+ delete_name(dns_name, mctx);
+
+ if (dns_result == exp_result) {
+ if (dns_result == ISC_R_SUCCESS) {
+ rval = t1_search(testname, rbt, mctx,
+ &dns_result);
+ if (rval == 0) {
+ if (dns_result == ISC_R_SUCCESS) {
+ result = T_PASS;
+ } else {
+ result = T_FAIL;
+ }
+ } else {
+ t_info("t1_search failed\n");
+ result = T_UNRESOLVED;
+ }
+ } else {
+ result = T_PASS;
+ }
+ } else {
+ t_info("dns_rbt_addname returned %s, "
+ "expected %s\n",
+ dns_result_totext(dns_result),
+ dns_result_totext(exp_result));
+ result = T_FAIL;
+ }
+ } else {
+ t_info("create_name failed %s\n",
+ dns_result_totext(dns_result));
+ result = T_UNRESOLVED;
+ }
+ } else if ((strcmp(command, "delete") == 0) ||
+ (strcmp(command, "nuke") == 0)) {
+ rval = t1_delete(testname, rbt, mctx, &dns_result);
+ if (rval == 0) {
+ if (dns_result == exp_result) {
+ rval = t1_search(testname, rbt, mctx,
+ &dns_result);
+ if (rval == 0) {
+ if (dns_result == ISC_R_SUCCESS) {
+ t_info("dns_rbt_deletename "
+ "didn't delete "
+ "the name");
+ result = T_FAIL;
+ } else {
+ result = T_PASS;
+ }
+ }
+ } else {
+ t_info("delete returned %s, expected %s\n",
+ dns_result_totext(dns_result),
+ dns_result_totext(exp_result));
+ result = T_FAIL;
+ }
+ }
+ } else if (strcmp(command, "search") == 0) {
+ rval = t1_search(testname, rbt, mctx, &dns_result);
+ if (rval == 0) {
+ if (dns_result == exp_result) {
+ result = T_PASS;
+ } else {
+ t_info("find returned %s, expected %s\n",
+ dns_result_totext(dns_result),
+ dns_result_totext(exp_result));
+ result = T_FAIL;
+ }
+ }
+ }
+
+ dns_rbt_destroy(&rbt);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+}
+
+static int
+test_dns_rbt_x(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ /*
+ * Name of db file, command, testname,
+ * expected result.
+ */
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 4) {
+ result = test_rbt_gen(Tokens[0], Tokens[1],
+ Tokens[2],
+ t_dns_result_fromtext(Tokens[3]));
+ if (result != T_PASS)
+ ++nfails;
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+
+static const char *a1 = "dns_rbt_create creates a rbt and returns "
+ "ISC_R_SUCCESS on success";
+
+static void
+t1() {
+ int result;
+
+ t_assert("dns_rbt_create", 1, T_REQUIRED, a1);
+ result = test_dns_rbt_x("dns_rbt_create_1_data");
+ t_result(result);
+}
+
+static const char *a2 = "dns_rbt_addname adds a name to a database and "
+ "returns ISC_R_SUCCESS on success";
+
+static void
+t2() {
+ int result;
+
+ t_assert("dns_rbt_addname", 2, T_REQUIRED, a2);
+ result = test_dns_rbt_x("dns_rbt_addname_1_data");
+ t_result(result);
+}
+
+static const char *a3 = "when name already exists, dns_rbt_addname() "
+ "returns ISC_R_EXISTS";
+
+static void
+t3() {
+ int result;
+
+ t_assert("dns_rbt_addname", 3, T_REQUIRED, a3);
+ result = test_dns_rbt_x("dns_rbt_addname_2_data");
+ t_result(result);
+}
+
+static const char *a4 = "when name exists, dns_rbt_deletename() returns "
+ "ISC_R_SUCCESS";
+
+static void
+t4() {
+ int result;
+
+ t_assert("dns_rbt_deletename", 4, T_REQUIRED, a4);
+ result = test_dns_rbt_x("dns_rbt_deletename_1_data");
+ t_result(result);
+}
+
+static const char *a5 = "when name does not exist, dns_rbt_deletename() "
+ "returns ISC_R_NOTFOUND";
+static void
+t5() {
+ int result;
+
+ t_assert("dns_rbt_deletename", 5, T_REQUIRED, a5);
+ result = test_dns_rbt_x("dns_rbt_deletename_2_data");
+ t_result(result);
+}
+
+static const char *a6 = "when name exists and exactly matches the "
+ "search name dns_rbt_findname() returns ISC_R_SUCCESS";
+
+static void
+t6() {
+ int result;
+
+ t_assert("dns_rbt_findname", 6, T_REQUIRED, a6);
+ result = test_dns_rbt_x("dns_rbt_findname_1_data");
+ t_result(result);
+}
+
+static const char *a7 = "when a name does not exist, "
+ "dns_rbt_findname returns ISC_R_NOTFOUND";
+
+static void
+t7() {
+ int result;
+
+ t_assert("dns_rbt_findname", 7, T_REQUIRED, a7);
+ result = test_dns_rbt_x("dns_rbt_findname_2_data");
+ t_result(result);
+}
+
+static const char *a8 = "when a superdomain is found with data matching name, "
+ "dns_rbt_findname returns DNS_R_PARTIALMATCH";
+
+static void
+t8() {
+ int result;
+
+ t_assert("dns_rbt_findname", 8, T_REQUIRED, a8);
+ result = test_dns_rbt_x("dns_rbt_findname_3_data");
+ t_result(result);
+}
+
+
+static const char *a9 = "a call to dns_rbtnodechain_init(chain, mctx) "
+ "initializes chain";
+
+static int
+t9_walkchain(dns_rbtnodechain_t *chain, dns_rbt_t *rbt) {
+ int cnt;
+ int order;
+ unsigned int nlabels;
+ int nprobs;
+ isc_result_t dns_result;
+
+ dns_fixedname_t name;
+ dns_fixedname_t origin;
+ dns_fixedname_t fullname1;
+ dns_fixedname_t fullname2;
+
+ cnt = 0;
+ nprobs = 0;
+
+ do {
+
+ if (cnt == 0) {
+ dns_fixedname_init(&name);
+ dns_fixedname_init(&origin);
+ dns_result = dns_rbtnodechain_first(chain, rbt,
+ dns_fixedname_name(&name),
+ dns_fixedname_name(&origin));
+ if (dns_result != DNS_R_NEWORIGIN) {
+ t_info("dns_rbtnodechain_first returned %s, "
+ "expecting DNS_R_NEWORIGIN\n",
+ dns_result_totext(dns_result));
+ ++nprobs;
+ break;
+ }
+ t_info("first name:\t<%s>\n", fixedname_totext(&name));
+ t_info("first origin:\t<%s>\n",
+ fixedname_totext(&origin));
+ } else {
+ dns_fixedname_init(&fullname1);
+ dns_result = dns_name_concatenate(
+ dns_fixedname_name(&name),
+ dns_name_isabsolute(dns_fixedname_name(&name)) ?
+ NULL : dns_fixedname_name(&origin),
+ dns_fixedname_name(&fullname1), NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_concatenate failed %s\n",
+ dns_result_totext(dns_result));
+ ++nprobs;
+ break;
+ }
+
+ /*
+ * Expecting origin not to get touched if next
+ * doesn't return NEWORIGIN.
+ */
+ dns_fixedname_init(&name);
+ dns_result = dns_rbtnodechain_next(chain,
+ dns_fixedname_name(&name),
+ dns_fixedname_name(&origin));
+ if ((dns_result != ISC_R_SUCCESS) &&
+ (dns_result != DNS_R_NEWORIGIN)) {
+ if (dns_result != ISC_R_NOMORE) {
+ t_info("dns_rbtnodechain_next "
+ "failed %s\n",
+ dns_result_totext(dns_result));
+ ++nprobs;
+ }
+ break;
+ }
+
+ t_info("next name:\t<%s>\n", fixedname_totext(&name));
+ t_info("next origin:\t<%s>\n",
+ fixedname_totext(&origin));
+
+ dns_fixedname_init(&fullname2);
+ dns_result = dns_name_concatenate(
+ dns_fixedname_name(&name),
+ dns_name_isabsolute(dns_fixedname_name(&name)) ?
+ NULL : dns_fixedname_name(&origin),
+ dns_fixedname_name(&fullname2), NULL);
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_concatenate failed %s\n",
+ dns_result_totext(dns_result));
+ ++nprobs;
+ break;
+ }
+
+ t_info("comparing\t<%s>\n",
+ fixedname_totext(&fullname1));
+ t_info("\twith\t<%s>\n", fixedname_totext(&fullname2));
+
+ (void)dns_name_fullcompare(
+ dns_fixedname_name(&fullname1),
+ dns_fixedname_name(&fullname2),
+ &order, &nlabels);
+
+ if (order >= 0) {
+ t_info("unexpected order %s %s %s\n",
+ dnsname_totext(dns_fixedname_name(&fullname1)),
+ order == -1 ? "<" : (order == 0 ? "==" : ">"),
+ dnsname_totext(dns_fixedname_name(&fullname2)));
+ ++nprobs;
+ }
+ }
+
+ ++cnt;
+ } while (1);
+
+ return (nprobs);
+}
+
+/*
+ * Test by exercising the first|last|next|prev funcs in useful ways.
+ */
+
+static int
+t_namechk(isc_result_t dns_result, dns_fixedname_t *dns_name, char *exp_name,
+ dns_fixedname_t *dns_origin, char *exp_origin,
+ isc_result_t exp_result)
+{
+ int nfails;
+
+ nfails = 0;
+
+ if (fixedname_cmp(dns_name, exp_name)) {
+ t_info("\texpected name of %s, got %s\n",
+ exp_name, fixedname_totext(dns_name));
+ ++nfails;
+ }
+ if (exp_origin != NULL) {
+ t_info("checking for DNS_R_NEWORIGIN\n");
+ if (dns_result == exp_result) {
+ if (fixedname_cmp(dns_origin, exp_origin)) {
+ t_info("\torigin %s, expected %s\n",
+ fixedname_totext(dns_origin),
+ exp_origin);
+ ++nfails;
+ }
+ } else {
+ t_info("\tgot %s\n", dns_result_totext(dns_result));
+ ++nfails;
+ }
+ }
+ return(nfails);
+}
+
+static int
+t_dns_rbtnodechain_init(char *dbfile, char *findname,
+ char *nextname, char *nextorigin,
+ char *prevname, char *prevorigin,
+ char *firstname, char *firstorigin,
+ char *lastname, char *lastorigin)
+{
+ int result;
+ int len;
+ int nfails;
+ dns_rbt_t *rbt;
+ dns_rbtnode_t *node;
+ dns_rbtnodechain_t chain;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_fixedname_t dns_findname;
+ dns_fixedname_t dns_foundname;
+ dns_fixedname_t dns_firstname;
+ dns_fixedname_t dns_lastname;
+ dns_fixedname_t dns_prevname;
+ dns_fixedname_t dns_nextname;
+ dns_fixedname_t dns_origin;
+ isc_buffer_t isc_buffer;
+
+ result = T_UNRESOLVED;
+
+ nfails = 0;
+ mctx = NULL;
+ ectx = NULL;
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(result);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ rbt = NULL;
+ if (rbt_init(dbfile, &rbt, mctx)) {
+ t_info("rbt_init %s failed\n", dbfile);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ len = strlen(findname);
+ isc_buffer_init(&isc_buffer, findname, len);
+ isc_buffer_add(&isc_buffer, len);
+
+ dns_fixedname_init(&dns_foundname);
+ dns_fixedname_init(&dns_findname);
+ dns_fixedname_init(&dns_firstname);
+ dns_fixedname_init(&dns_origin);
+ dns_fixedname_init(&dns_lastname);
+ dns_fixedname_init(&dns_prevname);
+ dns_fixedname_init(&dns_nextname);
+
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname),
+ &isc_buffer, NULL, ISC_FALSE, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Set the starting node.
+ */
+ node = NULL;
+ dns_result = dns_rbt_findnode(rbt, dns_fixedname_name(&dns_findname),
+ dns_fixedname_name(&dns_foundname),
+ &node, &chain, DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rbt_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Check next.
+ */
+ t_info("checking for next name of %s and new origin of %s\n",
+ nextname, nextorigin);
+ dns_result = dns_rbtnodechain_next(&chain,
+ dns_fixedname_name(&dns_nextname),
+ dns_fixedname_name(&dns_origin));
+
+ if ((dns_result != ISC_R_SUCCESS) &&
+ (dns_result != DNS_R_NEWORIGIN)) {
+ t_info("dns_rbtnodechain_next unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+
+ nfails += t_namechk(dns_result, &dns_nextname, nextname, &dns_origin,
+ nextorigin, DNS_R_NEWORIGIN);
+
+ /*
+ * Set the starting node again.
+ */
+ node = NULL;
+ dns_fixedname_init(&dns_foundname);
+ dns_result = dns_rbt_findnode(rbt, dns_fixedname_name(&dns_findname),
+ dns_fixedname_name(&dns_foundname),
+ &node, &chain, DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("\tdns_rbt_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Check previous.
+ */
+ t_info("checking for previous name of %s and new origin of %s\n",
+ prevname, prevorigin);
+ dns_fixedname_init(&dns_origin);
+ dns_result = dns_rbtnodechain_prev(&chain,
+ dns_fixedname_name(&dns_prevname),
+ dns_fixedname_name(&dns_origin));
+
+ if ((dns_result != ISC_R_SUCCESS) &&
+ (dns_result != DNS_R_NEWORIGIN)) {
+ t_info("dns_rbtnodechain_prev unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+ nfails += t_namechk(dns_result, &dns_prevname, prevname, &dns_origin,
+ prevorigin, DNS_R_NEWORIGIN);
+
+ /*
+ * Check first.
+ */
+ t_info("checking for first name of %s and new origin of %s\n",
+ firstname, firstorigin);
+ dns_result = dns_rbtnodechain_first(&chain, rbt,
+ dns_fixedname_name(&dns_firstname),
+ dns_fixedname_name(&dns_origin));
+
+ if (dns_result != DNS_R_NEWORIGIN) {
+ t_info("dns_rbtnodechain_first unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+ nfails += t_namechk(dns_result, &dns_firstname, firstname,
+ &dns_origin, firstorigin, DNS_R_NEWORIGIN);
+
+ /*
+ * Check last.
+ */
+ t_info("checking for last name of %s\n", lastname);
+ dns_result = dns_rbtnodechain_last(&chain, rbt,
+ dns_fixedname_name(&dns_lastname),
+ dns_fixedname_name(&dns_origin));
+
+ if (dns_result != DNS_R_NEWORIGIN) {
+ t_info("dns_rbtnodechain_last unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+ nfails += t_namechk(dns_result, &dns_lastname, lastname, &dns_origin,
+ lastorigin, DNS_R_NEWORIGIN);
+
+ /*
+ * Check node ordering.
+ */
+ t_info("checking node ordering\n");
+ nfails += t9_walkchain(&chain, rbt);
+
+ if (nfails)
+ result = T_FAIL;
+ else
+ result = T_PASS;
+
+ dns_rbtnodechain_invalidate(&chain);
+ dns_rbt_destroy(&rbt);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static int
+test_dns_rbtnodechain_init(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 10) {
+ result = t_dns_rbtnodechain_init(
+ Tokens[0], /* dbfile */
+ Tokens[1], /* startname */
+ Tokens[2], /* nextname */
+ Tokens[3], /* nextorigin */
+ Tokens[4], /* prevname */
+ Tokens[5], /* prevorigin */
+ Tokens[6], /* firstname */
+ Tokens[7], /* firstorigin */
+ Tokens[8], /* lastname */
+ Tokens[9]); /* lastorigin */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static void
+t9() {
+ int result;
+
+ t_assert("dns_rbtnodechain_init", 9, T_REQUIRED, a9);
+ result = test_dns_rbtnodechain_init("dns_rbtnodechain_init_data");
+ t_result(result);
+}
+
+static int
+t_dns_rbtnodechain_first(char *dbfile, char *expected_firstname,
+ char *expected_firstorigin,
+ char *expected_nextname,
+ char *expected_nextorigin)
+{
+ int result;
+ int nfails;
+ dns_rbt_t *rbt;
+ dns_rbtnodechain_t chain;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_fixedname_t dns_name;
+ dns_fixedname_t dns_origin;
+ isc_result_t expected_result;
+
+ result = T_UNRESOLVED;
+
+ nfails = 0;
+ mctx = NULL;
+ ectx = NULL;
+
+ dns_fixedname_init(&dns_name);
+ dns_fixedname_init(&dns_origin);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(result);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ rbt = NULL;
+ if (rbt_init(dbfile, &rbt, mctx)) {
+ t_info("rbt_init %s failed\n", dbfile);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ t_info("testing for first name of %s, origin of %s\n",
+ expected_firstname, expected_firstorigin);
+
+ dns_result = dns_rbtnodechain_first(&chain, rbt,
+ dns_fixedname_name(&dns_name),
+ dns_fixedname_name(&dns_origin));
+
+ if (dns_result != DNS_R_NEWORIGIN)
+ t_info("dns_rbtnodechain_first unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+
+ nfails = t_namechk(dns_result, &dns_name, expected_firstname,
+ &dns_origin, expected_firstorigin, DNS_R_NEWORIGIN);
+
+ dns_fixedname_init(&dns_name);
+ dns_result = dns_rbtnodechain_next(&chain,
+ dns_fixedname_name(&dns_name),
+ dns_fixedname_name(&dns_origin));
+
+ t_info("testing for next name of %s, origin of %s\n",
+ expected_nextname, expected_nextorigin);
+
+ if ((dns_result != ISC_R_SUCCESS) && (dns_result != DNS_R_NEWORIGIN))
+ t_info("dns_rbtnodechain_next unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+
+ if (strcasecmp(expected_firstorigin, expected_nextorigin) == 0)
+ expected_result = ISC_R_SUCCESS;
+ else
+ expected_result = DNS_R_NEWORIGIN;
+ nfails += t_namechk(dns_result, &dns_name, expected_nextname,
+ &dns_origin, expected_nextorigin, expected_result);
+
+ if (nfails)
+ result = T_FAIL;
+ else
+ result = T_PASS;
+
+ dns_rbtnodechain_invalidate(&chain);
+
+ dns_rbt_destroy(&rbt);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+}
+
+static int
+test_dns_rbtnodechain_first(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 5) {
+ result = t_dns_rbtnodechain_first(
+ Tokens[0], /* dbfile */
+ Tokens[1], /* firstname */
+ Tokens[2], /* firstorigin */
+ Tokens[3], /* nextname */
+ Tokens[4]); /* nextorigin */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a10 = "a call to "
+ "dns_rbtnodechain_first(chain, rbt, name, origin) "
+ "sets name to point to the root of the tree, "
+ "origin to point to the origin, "
+ "and returns DNS_R_NEWORIGIN";
+
+static void
+t10() {
+ int result;
+
+ t_assert("dns_rbtnodechain_first", 10, T_REQUIRED, a10);
+ result = test_dns_rbtnodechain_first("dns_rbtnodechain_first_data");
+ t_result(result);
+}
+
+static int
+t_dns_rbtnodechain_last(char *dbfile, char *expected_lastname,
+ char *expected_lastorigin,
+ char *expected_prevname,
+ char *expected_prevorigin)
+{
+
+ int result;
+ int nfails;
+ dns_rbt_t *rbt;
+ dns_rbtnodechain_t chain;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_fixedname_t dns_name;
+ dns_fixedname_t dns_origin;
+ isc_result_t expected_result;
+
+ result = T_UNRESOLVED;
+
+ nfails = 0;
+ mctx = NULL;
+ ectx = NULL;
+
+ dns_fixedname_init(&dns_name);
+ dns_fixedname_init(&dns_origin);
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(result);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ rbt = NULL;
+ if (rbt_init(dbfile, &rbt, mctx)) {
+ t_info("rbt_init %s failed\n", dbfile);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ t_info("testing for last name of %s, origin of %s\n",
+ expected_lastname, expected_lastorigin);
+
+ dns_result = dns_rbtnodechain_last(&chain, rbt,
+ dns_fixedname_name(&dns_name),
+ dns_fixedname_name(&dns_origin));
+
+ if (dns_result != DNS_R_NEWORIGIN) {
+ t_info("dns_rbtnodechain_last unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+ nfails = t_namechk(dns_result, &dns_name, expected_lastname,
+ &dns_origin, expected_lastorigin, DNS_R_NEWORIGIN);
+
+ t_info("testing for previous name of %s, origin of %s\n",
+ expected_prevname, expected_prevorigin);
+
+ dns_fixedname_init(&dns_name);
+ dns_result = dns_rbtnodechain_prev(&chain,
+ dns_fixedname_name(&dns_name),
+ dns_fixedname_name(&dns_origin));
+
+ if ((dns_result != ISC_R_SUCCESS) &&
+ (dns_result != DNS_R_NEWORIGIN)) {
+ t_info("dns_rbtnodechain_prev unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+ if (strcasecmp(expected_lastorigin, expected_prevorigin) == 0)
+ expected_result = ISC_R_SUCCESS;
+ else
+ expected_result = DNS_R_NEWORIGIN;
+ nfails += t_namechk(dns_result, &dns_name, expected_prevname,
+ &dns_origin, expected_prevorigin, expected_result);
+
+ if (nfails)
+ result = T_FAIL;
+ else
+ result = T_PASS;
+
+ dns_rbtnodechain_invalidate(&chain);
+ dns_rbt_destroy(&rbt);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static int
+test_dns_rbtnodechain_last(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 5) {
+ result = t_dns_rbtnodechain_last(
+ Tokens[0], /* dbfile */
+ Tokens[1], /* lastname */
+ Tokens[2], /* lastorigin */
+ Tokens[3], /* prevname */
+ Tokens[4]); /* prevorigin */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a11 = "a call to "
+ "dns_rbtnodechain_last(chain, rbt, name, origin) "
+ "sets name to point to the last node of the megatree, "
+ "origin to the name of the level above it, "
+ "and returns DNS_R_NEWORIGIN";
+
+static void
+t11() {
+ int result;
+
+ t_assert("dns_rbtnodechain_last", 11, T_REQUIRED, a11);
+ result = test_dns_rbtnodechain_last("dns_rbtnodechain_last_data");
+ t_result(result);
+}
+
+static int
+t_dns_rbtnodechain_next(char *dbfile, char *findname,
+ char *nextname, char *nextorigin)
+{
+
+ int result;
+ int len;
+ int nfails;
+ dns_rbt_t *rbt;
+ dns_rbtnode_t *node;
+ dns_rbtnodechain_t chain;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_fixedname_t dns_findname;
+ dns_fixedname_t dns_foundname;
+ dns_fixedname_t dns_nextname;
+ dns_fixedname_t dns_origin;
+ isc_buffer_t isc_buffer;
+
+ result = T_UNRESOLVED;
+
+ nfails = 0;
+ mctx = NULL;
+ ectx = NULL;
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(result);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ rbt = NULL;
+ if (rbt_init(dbfile, &rbt, mctx)) {
+ t_info("rbt_init %s failed\n", dbfile);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ len = strlen(findname);
+ isc_buffer_init(&isc_buffer, findname, len);
+ isc_buffer_add(&isc_buffer, len);
+
+ dns_fixedname_init(&dns_foundname);
+ dns_fixedname_init(&dns_findname);
+ dns_fixedname_init(&dns_nextname);
+ dns_fixedname_init(&dns_origin);
+
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname),
+ &isc_buffer, NULL, ISC_FALSE, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Set the starting node.
+ */
+ node = NULL;
+ dns_result = dns_rbt_findnode(rbt, dns_fixedname_name(&dns_findname),
+ dns_fixedname_name(&dns_foundname),
+ &node, &chain, DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rbt_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Check next.
+ */
+ t_info("checking for next name of %s and new origin of %s\n",
+ nextname, nextorigin);
+ dns_result = dns_rbtnodechain_next(&chain,
+ dns_fixedname_name(&dns_nextname),
+ dns_fixedname_name(&dns_origin));
+
+ if ((dns_result != ISC_R_SUCCESS) && (dns_result != DNS_R_NEWORIGIN)) {
+ t_info("dns_rbtnodechain_next unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+
+ nfails += t_namechk(dns_result, &dns_nextname, nextname, &dns_origin,
+ nextorigin, DNS_R_NEWORIGIN);
+
+ if (nfails)
+ result = T_FAIL;
+ else
+ result = T_PASS;
+
+ dns_rbtnodechain_invalidate(&chain);
+ dns_rbt_destroy(&rbt);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static int
+test_dns_rbtnodechain_next(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 4) {
+ result = t_dns_rbtnodechain_next(
+ Tokens[0], /* dbfile */
+ Tokens[1], /* findname */
+ Tokens[2], /* nextname */
+ Tokens[3]); /* nextorigin */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a12 = "a call to "
+ "dns_rbtnodechain_next(chain, name, origin) "
+ "sets name to point to the next node of the tree "
+ "and returns ISC_R_SUCCESS or "
+ "DNS_R_NEWORIGIN on success";
+
+
+static void
+t12() {
+ int result;
+
+ t_assert("dns_rbtnodechain_next", 12, T_REQUIRED, a12);
+ result = test_dns_rbtnodechain_next("dns_rbtnodechain_next_data");
+ t_result(result);
+}
+
+static int
+t_dns_rbtnodechain_prev(char *dbfile, char *findname, char *prevname,
+ char *prevorigin)
+{
+ int result;
+ int len;
+ int nfails;
+ dns_rbt_t *rbt;
+ dns_rbtnode_t *node;
+ dns_rbtnodechain_t chain;
+ isc_mem_t *mctx;
+ isc_entropy_t *ectx = NULL;
+ isc_result_t isc_result;
+ isc_result_t dns_result;
+ dns_fixedname_t dns_findname;
+ dns_fixedname_t dns_foundname;
+ dns_fixedname_t dns_prevname;
+ dns_fixedname_t dns_origin;
+ isc_buffer_t isc_buffer;
+
+ result = T_UNRESOLVED;
+
+ nfails = 0;
+ mctx = NULL;
+ ectx = NULL;
+
+ isc_result = isc_mem_create(0, 0, &mctx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_mem_create failed %s\n",
+ isc_result_totext(isc_result));
+ return(result);
+ }
+
+ isc_result = isc_entropy_create(mctx, &ectx);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_entropy_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ isc_result = isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE);
+ if (isc_result != ISC_R_SUCCESS) {
+ t_info("isc_hash_create: %s: exiting\n",
+ dns_result_totext(isc_result));
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(T_UNRESOLVED);
+ }
+
+ dns_rbtnodechain_init(&chain, mctx);
+
+ rbt = NULL;
+ if (rbt_init(dbfile, &rbt, mctx)) {
+ t_info("rbt_init %s failed\n", dbfile);
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+ return(result);
+ }
+
+ len = strlen(findname);
+ isc_buffer_init(&isc_buffer, findname, len);
+ isc_buffer_add(&isc_buffer, len);
+
+ dns_fixedname_init(&dns_foundname);
+ dns_fixedname_init(&dns_findname);
+ dns_fixedname_init(&dns_prevname);
+ dns_fixedname_init(&dns_origin);
+
+ dns_result = dns_name_fromtext(dns_fixedname_name(&dns_findname),
+ &isc_buffer, NULL, ISC_FALSE, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_name_fromtext failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Set the starting node.
+ */
+ node = NULL;
+ dns_result = dns_rbt_findnode(rbt, dns_fixedname_name(&dns_findname),
+ dns_fixedname_name(&dns_foundname),
+ &node, &chain, DNS_RBTFIND_EMPTYDATA,
+ NULL, NULL);
+
+ if (dns_result != ISC_R_SUCCESS) {
+ t_info("dns_rbt_findnode failed %s\n",
+ dns_result_totext(dns_result));
+ return(result);
+ }
+
+ /*
+ * Check next.
+ */
+ t_info("checking for next name of %s and new origin of %s\n",
+ prevname, prevorigin);
+ dns_result = dns_rbtnodechain_prev(&chain,
+ dns_fixedname_name(&dns_prevname),
+ dns_fixedname_name(&dns_origin));
+
+ if ((dns_result != ISC_R_SUCCESS) && (dns_result != DNS_R_NEWORIGIN)) {
+ t_info("dns_rbtnodechain_prev unexpectedly returned %s\n",
+ dns_result_totext(dns_result));
+ }
+
+ nfails += t_namechk(dns_result, &dns_prevname, prevname, &dns_origin,
+ prevorigin, DNS_R_NEWORIGIN);
+
+ if (nfails)
+ result = T_FAIL;
+ else
+ result = T_PASS;
+
+ dns_rbtnodechain_invalidate(&chain);
+ dns_rbt_destroy(&rbt);
+
+ isc_hash_destroy();
+ isc_entropy_detach(&ectx);
+ isc_mem_destroy(&mctx);
+
+ return(result);
+}
+
+static int
+test_dns_rbtnodechain_prev(const char *filename) {
+ FILE *fp;
+ char *p;
+ int line;
+ int cnt;
+ int result;
+ int nfails;
+ int nprobs;
+
+ nfails = 0;
+ nprobs = 0;
+
+ fp = fopen(filename, "r");
+ if (fp != NULL) {
+ line = 0;
+ while ((p = t_fgetbs(fp)) != NULL) {
+
+ ++line;
+
+ /*
+ * Skip comment lines.
+ */
+ if ((isspace((unsigned char)*p)) || (*p == '#')) {
+ (void)free(p);
+ continue;
+ }
+
+ cnt = t_bustline(p, Tokens);
+ if (cnt == 4) {
+ result = t_dns_rbtnodechain_prev(
+ Tokens[0], /* dbfile */
+ Tokens[1], /* findname */
+ Tokens[2], /* prevname */
+ Tokens[3]); /* prevorigin */
+ if (result != T_PASS) {
+ if (result == T_FAIL)
+ ++nfails;
+ else
+ ++nprobs;
+ }
+ } else {
+ t_info("bad format in %s at line %d\n",
+ filename, line);
+ ++nprobs;
+ }
+
+ (void)free(p);
+ }
+ (void)fclose(fp);
+ } else {
+ t_info("Missing datafile %s\n", filename);
+ ++nprobs;
+ }
+
+ result = T_UNRESOLVED;
+
+ if ((nfails == 0) && (nprobs == 0))
+ result = T_PASS;
+ else if (nfails)
+ result = T_FAIL;
+
+ return(result);
+}
+
+static const char *a13 = "a call to "
+ "dns_rbtnodechain_prev(chain, name, origin) "
+ "sets name to point to the previous node of the tree "
+ "and returns ISC_R_SUCCESS or "
+ "DNS_R_NEWORIGIN on success";
+
+static void
+t13() {
+ int result;
+
+ t_assert("dns_rbtnodechain_prev", 13, T_REQUIRED, a13);
+ result = test_dns_rbtnodechain_prev("dns_rbtnodechain_prev_data");
+ t_result(result);
+}
+
+
+
+testspec_t T_testlist[] = {
+ { t1, "dns_rbt_create" },
+ { t2, "dns_rbt_addname 1" },
+ { t3, "dns_rbt_addname 2" },
+ { t4, "dns_rbt_deletename 1" },
+ { t5, "dns_rbt_deletename 2" },
+ { t6, "dns_rbt_findname 1" },
+ { t7, "dns_rbt_findname 2" },
+ { t8, "dns_rbt_findname 3" },
+ { t9, "dns_rbtnodechain_init" },
+ { t10, "dns_rbtnodechain_first" },
+ { t11, "dns_rbtnodechain_last" },
+ { t12, "dns_rbtnodechain_next" },
+ { t13, "dns_rbtnodechain_prev" },
+ { NULL, NULL }
+};
+