]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Update qp unit tests merging denial and zone data
authorMatthijs Mekking <matthijs@isc.org>
Tue, 13 May 2025 10:47:02 +0000 (11:47 +0100)
committerMatthijs Mekking <matthijs@isc.org>
Thu, 10 Jul 2025 13:52:59 +0000 (13:52 +0000)
If zone and denial data are going to be stored in the same qp storage,
the unit tests need to be updated to reflect this change. The code
changes mainly affect name to qpkey conversion, lookups, and
predecessors.

A note on predecessors: since the denial and zone data are now in the
same qp storage, the predecessor of the first name in the zone data will
consequently be the last name in the denial data.

tests/dns/qp_test.c

index 67f2cb94f7e776e5163afa137c33da826c4d5e25..53a20cfa97d41e9a794572c0805b03e4d965da13 100644 (file)
@@ -52,69 +52,69 @@ ISC_RUN_TEST_IMPL(qpkey_name) {
                {
                        .namestr = "",
                        .denial = DNS_DB_NSEC_NORMAL,
-                       .key = { 0x00, 0x02 },
+                       .key = { 0x07, 0x02 },
                        .len = 1,
                },
                {
                        .namestr = ".",
                        .denial = DNS_DB_NSEC_NORMAL,
-                       .key = { 0x00, 0x02, 0x02 },
+                       .key = { 0x07, 0x02, 0x02 },
                        .len = 2,
                },
                {
                        .namestr = "\\000",
                        .denial = DNS_DB_NSEC_NORMAL,
-                       .key = { 0x00, 0x03, 0x03, 0x02 },
+                       .key = { 0x07, 0x03, 0x03, 0x02 },
                        .len = 4,
                },
                {
                        .namestr = "\\000\\009",
                        .denial = DNS_DB_NSEC_NORMAL,
-                       .key = { 0x00, 0x03, 0x03, 0x03, 0x0c, 0x02 },
+                       .key = { 0x07, 0x03, 0x03, 0x03, 0x0c, 0x02 },
                        .len = 6,
                },
                {
                        .namestr = "com",
                        .denial = DNS_DB_NSEC_NORMAL,
-                       .key = { 0x00, 0x16, 0x22, 0x20, 0x02 },
+                       .key = { 0x07, 0x16, 0x22, 0x20, 0x02 },
                        .len = 5,
                },
                {
                        .namestr = "com.",
                        .denial = DNS_DB_NSEC_NSEC,
-                       .key = { 0x02, 0x02, 0x16, 0x22, 0x20, 0x02 },
+                       .key = { 0x09, 0x02, 0x16, 0x22, 0x20, 0x02 },
                        .len = 6,
                },
                {
                        .namestr = "com.",
                        .denial = DNS_DB_NSEC_NSEC3,
-                       .key = { 0x03, 0x02, 0x16, 0x22, 0x20, 0x02 },
+                       .key = { 0x0a, 0x02, 0x16, 0x22, 0x20, 0x02 },
                        .len = 6,
                },
                {
                        .namestr = "com.",
                        .denial = DNS_DB_NSEC_NORMAL,
-                       .key = { 0x00, 0x02, 0x16, 0x22, 0x20, 0x02 },
+                       .key = { 0x07, 0x02, 0x16, 0x22, 0x20, 0x02 },
                        .len = 6,
                },
                {
                        .namestr = "example.com.",
                        .denial = DNS_DB_NSEC_NORMAL,
-                       .key = { 0x00, 0x02, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b,
+                       .key = { 0x07, 0x02, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b,
                                 0x14, 0x20, 0x23, 0x1f, 0x18, 0x02 },
                        .len = 14,
                },
                {
                        .namestr = "example.com",
                        .denial = DNS_DB_NSEC_NORMAL,
-                       .key = { 0x00, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14,
+                       .key = { 0x07, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14,
                                 0x20, 0x23, 0x1f, 0x18, 0x02 },
                        .len = 13,
                },
                {
                        .namestr = "EXAMPLE.COM",
                        .denial = DNS_DB_NSEC_NORMAL,
-                       .key = { 0x00, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14,
+                       .key = { 0x07, 0x16, 0x22, 0x20, 0x02, 0x18, 0x2b, 0x14,
                                 0x20, 0x23, 0x1f, 0x18, 0x02 },
                        .len = 13,
                },
@@ -155,20 +155,25 @@ ISC_RUN_TEST_IMPL(qpkey_sort) {
                const char *namestr;
                dns_name_t *name;
                dns_fixedname_t fixed;
+               uint8_t denial;
                size_t len;
                dns_qpkey_t key;
        } testcases[] = {
-               { .namestr = "." },
-               { .namestr = "\\000." },
-               { .namestr = "\\000.\\000." },
-               { .namestr = "\\000\\009." },
-               { .namestr = "\\007." },
-               { .namestr = "example.com." },
-               { .namestr = "EXAMPLE.COM." },
-               { .namestr = "www.example.com." },
-               { .namestr = "exam.com." },
-               { .namestr = "exams.com." },
-               { .namestr = "exam\\000.com." },
+               { .namestr = ".", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "\\000.", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "\\000.\\000.", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "\\000\\009.", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "\\007.", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "example.com.", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "EXAMPLE.COM.", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "www.example.com.", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "exam.com.", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "exams.com.", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "exam\\000.com.", .denial = DNS_DB_NSEC_NORMAL },
+               { .namestr = "exam.com.", .denial = DNS_DB_NSEC_NSEC },
+               { .namestr = "exams.com.", .denial = DNS_DB_NSEC_NSEC },
+               { .namestr = "exam.com.", .denial = DNS_DB_NSEC_NSEC3 },
+               { .namestr = "exams.com.", .denial = DNS_DB_NSEC_NSEC3 },
        };
 
        for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) {
@@ -176,7 +181,8 @@ ISC_RUN_TEST_IMPL(qpkey_sort) {
                                        &testcases[i].fixed);
                testcases[i].name = dns_fixedname_name(&testcases[i].fixed);
                testcases[i].len = dns_qpkey_fromname(testcases[i].key,
-                                                     testcases[i].name, 0);
+                                                     testcases[i].name,
+                                                     testcases[i].denial);
        }
 
        for (size_t i = 0; i < ARRAY_SIZE(testcases); i++) {
@@ -188,9 +194,16 @@ ISC_RUN_TEST_IMPL(qpkey_sort) {
                        /* include extra terminating NOBYTE */
                        int keycmp = memcmp(testcases[i].key, testcases[j].key,
                                            len + 1);
-                       assert_true((namecmp < 0) == (keycmp < 0));
-                       assert_true((namecmp == 0) == (keycmp == 0));
-                       assert_true((namecmp > 0) == (keycmp > 0));
+                       if (testcases[i].denial == testcases[j].denial) {
+                               assert_true((namecmp < 0) == (keycmp < 0));
+                               assert_true((namecmp == 0) == (keycmp == 0));
+                               assert_true((namecmp > 0) == (keycmp > 0));
+                       } else {
+                               uint8_t di = testcases[i].denial;
+                               uint8_t dj = testcases[j].denial;
+                               assert_true((di < dj) == (keycmp < 0));
+                               assert_true((di > dj) == (keycmp > 0));
+                       }
                }
        }
 }
@@ -371,14 +384,11 @@ no_op(void *uctx, void *pval, uint32_t ival) {
 static size_t
 qpkey_fromstring(dns_qpkey_t key, void *uctx, void *pval, uint32_t ival) {
        dns_fixedname_t fixed;
+       uint8_t denial = ival;
 
        UNUSED(uctx);
-       UNUSED(ival);
-       if (*(char *)pval == '\0') {
-               return 0;
-       }
        dns_test_namefromstring(pval, &fixed);
-       return dns_qpkey_fromname(key, dns_fixedname_name(&fixed), 0);
+       return dns_qpkey_fromname(key, dns_fixedname_name(&fixed), denial);
 }
 
 const dns_qpmethods_t string_methods = {
@@ -395,7 +405,8 @@ struct check_partialmatch {
 };
 
 static void
-check_partialmatch(dns_qp_t *qp, struct check_partialmatch check[]) {
+check_partialmatch(dns_qp_t *qp, struct check_partialmatch check[],
+                  uint8_t denial) {
        for (int i = 0; check[i].query != NULL; i++) {
                isc_result_t result;
                dns_fixedname_t fn1, fn2;
@@ -404,12 +415,13 @@ check_partialmatch(dns_qp_t *qp, struct check_partialmatch check[]) {
                void *pval = NULL;
 
                dns_test_namefromstring(check[i].query, &fn1);
-               result = dns_qp_lookup(qp, name, foundname, NULL, NULL, &pval,
-                                      NULL);
+               result = dns_qp_lookup2(qp, name, denial, foundname, NULL, NULL,
+                                       &pval, NULL);
 
 #if 0
-               fprintf(stderr, "%s %s (expected %s) "
+               fprintf(stderr, "%s%s %s (expected %s) "
                        "value \"%s\" (expected \"%s\")\n",
+                       denial == DNS_DB_NSEC_NSEC3 ? "NSEC3:" : (denial == DNS_DB_NSEC_NSEC ? "NSEC:" : ""),
                        check[i].query,
                        isc_result_totext(result),
                        isc_result_totext(check[i].result), (char *)pval,
@@ -448,16 +460,24 @@ check_partialmatch(dns_qp_t *qp, struct check_partialmatch check[]) {
 }
 
 static void
-insert_str(dns_qp_t *qp, const char *str) {
+insert_name(dns_qp_t *qp, const char *str, uint8_t denial) {
        isc_result_t result;
        uintptr_t pval = (uintptr_t)str;
+       uint32_t ival = (uint32_t)denial;
        INSIST((pval & 3) == 0);
-       result = dns_qp_insert(qp, (void *)pval, 0);
+       result = dns_qp_insert(qp, (void *)pval, ival);
+       assert_int_equal(result, ISC_R_SUCCESS);
+}
+
+static void
+delete_rootkey(dns_qp_t *qp, uint8_t denial) {
+       uint8_t d = dns_qp_bits_for_byte[denial + 48];
+       dns_qpkey_t rootkey = { d, SHIFT_NOBYTE };
+       isc_result_t result = dns_qp_deletekey(qp, rootkey, 1, NULL, NULL);
        assert_int_equal(result, ISC_R_SUCCESS);
 }
 
 ISC_RUN_TEST_IMPL(partialmatch) {
-       isc_result_t result;
        dns_qp_t *qp = NULL;
        int i = 0;
 
@@ -476,7 +496,10 @@ ISC_RUN_TEST_IMPL(partialmatch) {
         * results when we want "not found".
         */
        while (insert[i][0] != '.') {
-               insert_str(qp, insert[i++]);
+               insert_name(qp, insert[i], DNS_DB_NSEC_NORMAL);
+               insert_name(qp, insert[i], DNS_DB_NSEC_NSEC);
+               insert_name(qp, insert[i], DNS_DB_NSEC_NSEC3);
+               i++;
        }
 
        static struct check_partialmatch check1[] = {
@@ -494,11 +517,16 @@ ISC_RUN_TEST_IMPL(partialmatch) {
                { "my.other.foo.bar.", DNS_R_PARTIALMATCH, "foo.bar." },
                { NULL, 0, NULL },
        };
-       check_partialmatch(qp, check1);
+       check_partialmatch(qp, check1, DNS_DB_NSEC_NORMAL);
+       check_partialmatch(qp, check1, DNS_DB_NSEC_NSEC);
+       check_partialmatch(qp, check1, DNS_DB_NSEC_NSEC3);
 
        /* what if the trie contains the root? */
        INSIST(insert[i][0] == '.');
-       insert_str(qp, insert[i++]);
+       insert_name(qp, insert[i], DNS_DB_NSEC_NORMAL);
+       insert_name(qp, insert[i], DNS_DB_NSEC_NSEC);
+       insert_name(qp, insert[i], DNS_DB_NSEC_NSEC3);
+       i++;
 
        static struct check_partialmatch check2[] = {
                { "b.c.", DNS_R_PARTIALMATCH, "." },
@@ -507,26 +535,33 @@ ISC_RUN_TEST_IMPL(partialmatch) {
                { "bar", ISC_R_NOTFOUND, NULL },
                { NULL, 0, NULL },
        };
-       check_partialmatch(qp, check2);
+       check_partialmatch(qp, check2, DNS_DB_NSEC_NORMAL);
+       check_partialmatch(qp, check2, DNS_DB_NSEC_NSEC);
+       check_partialmatch(qp, check2, DNS_DB_NSEC_NSEC3);
 
        /*
         * what if entries in the trie are relative to the zone apex
         * and there's no root node?
         */
-       dns_qpkey_t rootkey = { 0x00, SHIFT_NOBYTE };
-       result = dns_qp_deletekey(qp, rootkey, 1, NULL, NULL);
-       assert_int_equal(result, ISC_R_SUCCESS);
-       check_partialmatch(qp, (struct check_partialmatch[]){
-                                      { "bar", ISC_R_NOTFOUND, NULL },
-                                      { "bar.", ISC_R_NOTFOUND, NULL },
-                                      { NULL, 0, NULL },
-                              });
+       delete_rootkey(qp, DNS_DB_NSEC_NORMAL);
+       delete_rootkey(qp, DNS_DB_NSEC_NSEC);
+       delete_rootkey(qp, DNS_DB_NSEC_NSEC3);
+
+       static struct check_partialmatch check3[] = {
+               { "bar", ISC_R_NOTFOUND, NULL },
+               { "bar.", ISC_R_NOTFOUND, NULL },
+               { NULL, 0, NULL },
+       };
+       check_partialmatch(qp, check3, DNS_DB_NSEC_NORMAL);
+       check_partialmatch(qp, check3, DNS_DB_NSEC_NSEC);
+       check_partialmatch(qp, check3, DNS_DB_NSEC_NSEC3);
 
        dns_qp_destroy(&qp);
 }
 
 struct check_qpchain {
        const char *query;
+       uint8_t denial;
        isc_result_t result;
        unsigned int length;
        const char *names[10];
@@ -543,12 +578,13 @@ check_qpchainiter(dns_qp_t *qp, struct check_qpchain check[],
 
                dns_qpchain_init(qp, &chain);
                dns_test_namefromstring(check[i].query, &fn1);
-               result = dns_qp_lookup(qp, name, NULL, iter, &chain, NULL,
-                                      NULL);
+               result = dns_qp_lookup2(qp, name, check[i].denial, NULL, iter,
+                                       &chain, NULL, NULL);
 #if 0
-               fprintf(stderr, "%s %s (expected %s), "
-                       "len %d (expected %d)\n", check[i].query,
-                       isc_result_totext(result),
+               fprintf(stderr,
+                       "%s %s (expected %s), "
+                       "len %d (expected %d)\n",
+                       check[i].query, isc_result_totext(result),
                        isc_result_totext(check[i].result),
                        dns_qpchain_length(&chain), check[i].length);
 #endif
@@ -591,24 +627,102 @@ ISC_RUN_TEST_IMPL(qpchain) {
        dns_qp_create(mctx, &string_methods, NULL, &qp);
 
        while (insert[i][0] != '\0') {
-               insert_str(qp, insert[i++]);
+               insert_name(qp, insert[i], DNS_DB_NSEC_NORMAL);
+               insert_name(qp, insert[i], DNS_DB_NSEC_NSEC);
+               insert_name(qp, insert[i], DNS_DB_NSEC_NSEC3);
+               i++;
        }
 
        static struct check_qpchain check1[] = {
-               { "b.", ISC_R_SUCCESS, 2, { ".", "b." } },
-               { "b.a.", ISC_R_SUCCESS, 3, { ".", "a.", "b.a." } },
-               { "c.", DNS_R_PARTIALMATCH, 1, { "." } },
+               { "b.", DNS_DB_NSEC_NORMAL, ISC_R_SUCCESS, 2, { ".", "b." } },
+               { "b.", DNS_DB_NSEC_NSEC, ISC_R_SUCCESS, 2, { ".", "b." } },
+               { "b.", DNS_DB_NSEC_NSEC3, ISC_R_SUCCESS, 2, { ".", "b." } },
+
+               { "b.a.",
+                 DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS,
+                 3,
+                 { ".", "a.", "b.a." } },
+               { "b.a.",
+                 DNS_DB_NSEC_NSEC,
+                 ISC_R_SUCCESS,
+                 3,
+                 { ".", "a.", "b.a." } },
+               { "b.a.",
+                 DNS_DB_NSEC_NSEC3,
+                 ISC_R_SUCCESS,
+                 3,
+                 { ".", "a.", "b.a." } },
+
+               { "c.", DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 1, { "." } },
+               { "c.", DNS_DB_NSEC_NSEC, DNS_R_PARTIALMATCH, 1, { "." } },
+               { "c.", DNS_DB_NSEC_NSEC3, DNS_R_PARTIALMATCH, 1, { "." } },
+
+               { "e.d.c.b.a.",
+                 DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS,
+                 5,
+                 { ".", "a.", "b.a.", "c.b.a.", "e.d.c.b.a." } },
+               { "e.d.c.b.a.",
+                 DNS_DB_NSEC_NSEC,
+                 ISC_R_SUCCESS,
+                 5,
+                 { ".", "a.", "b.a.", "c.b.a.", "e.d.c.b.a." } },
                { "e.d.c.b.a.",
+                 DNS_DB_NSEC_NSEC3,
                  ISC_R_SUCCESS,
                  5,
                  { ".", "a.", "b.a.", "c.b.a.", "e.d.c.b.a." } },
-               { "a.b.c.d.", ISC_R_SUCCESS, 3, { ".", "c.d.", "a.b.c.d." } },
-               { "b.c.d.", DNS_R_PARTIALMATCH, 2, { ".", "c.d." } },
+
+               { "a.b.c.d.",
+                 DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS,
+                 3,
+                 { ".", "c.d.", "a.b.c.d." } },
+               { "a.b.c.d.",
+                 DNS_DB_NSEC_NSEC,
+                 ISC_R_SUCCESS,
+                 3,
+                 { ".", "c.d.", "a.b.c.d." } },
+               { "a.b.c.d.",
+                 DNS_DB_NSEC_NSEC3,
+                 ISC_R_SUCCESS,
+                 3,
+                 { ".", "c.d.", "a.b.c.d." } },
+
+               { "b.c.d.",
+                 DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH,
+                 2,
+                 { ".", "c.d." } },
+               { "b.c.d.",
+                 DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH,
+                 2,
+                 { ".", "c.d." } },
+               { "b.c.d.",
+                 DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH,
+                 2,
+                 { ".", "c.d." } },
+
+               { "z.x.k.c.d.",
+                 DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH,
+                 3,
+                 { ".", "c.d.", "x.k.c.d." } },
+               { "z.x.k.c.d.",
+                 DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH,
+                 3,
+                 { ".", "c.d.", "x.k.c.d." } },
                { "z.x.k.c.d.",
+                 DNS_DB_NSEC_NSEC3,
                  DNS_R_PARTIALMATCH,
                  3,
                  { ".", "c.d.", "x.k.c.d." } },
-               { NULL, 0, 0, { NULL } },
+
+               { NULL, 0, 0, 0, { NULL } },
        };
 
        check_qpchain(qp, check1);
@@ -621,12 +735,29 @@ ISC_RUN_TEST_IMPL(qpchain) {
        dns_qp_create(mctx, &string_methods, NULL, &qp);
 
        while (insert2[i][0] != '\0') {
-               insert_str(qp, insert2[i++]);
+               insert_name(qp, insert2[i], DNS_DB_NSEC_NORMAL);
+               insert_name(qp, insert2[i], DNS_DB_NSEC_NSEC);
+               insert_name(qp, insert2[i], DNS_DB_NSEC_NSEC3);
+               i++;
        }
 
        static struct check_qpchain check2[] = {
-               { "f.c.b.a.", DNS_R_PARTIALMATCH, 1, { "a." } },
-               { NULL, 0, 0, { NULL } },
+               { "f.c.b.a.",
+                 DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH,
+                 1,
+                 { "a." } },
+               { "f.c.b.a.",
+                 DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH,
+                 1,
+                 { "a." } },
+               { "f.c.b.a.",
+                 DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH,
+                 1,
+                 { "a." } },
+               { NULL, 0, 0, 0, { NULL } },
        };
 
        check_qpchain(qp, check2);
@@ -635,7 +766,9 @@ ISC_RUN_TEST_IMPL(qpchain) {
 
 struct check_predecessors {
        const char *query;
+       uint8_t denial;
        const char *predecessor;
+       uint8_t pdenial;
        isc_result_t result;
        int remaining;
 };
@@ -648,6 +781,7 @@ check_predecessors_withchain(dns_qp_t *qp, struct check_predecessors check[],
        dns_name_t *name = dns_fixedname_initname(&fn1);
        dns_name_t *pred = dns_fixedname_initname(&fn2);
        char *namestr = NULL;
+       uint32_t ival;
 
        for (int i = 0; check[i].query != NULL; i++) {
                dns_qpiter_t it;
@@ -666,9 +800,15 @@ check_predecessors_withchain(dns_qp_t *qp, struct check_predecessors check[],
                result = dns_name_tostring(expred, &predstr, mctx);
                assert_int_equal(result, ISC_R_SUCCESS);
 
-               result = dns_qp_lookup(qp, name, NULL, &it, chain, NULL, NULL);
+               result = dns_qp_lookup2(qp, name, check[i].denial, NULL, &it,
+                                       chain, NULL, NULL);
 #if 0
-               fprintf(stderr, "%s: expected %s got %s\n", check[i].query,
+               fprintf(stderr, "%s %s: expected %s got %s\n", check[i].query,
+                       check[i].denial == DNS_DB_NSEC_NSEC3
+                               ? "NSEC3"
+                               : (check[i].denial == DNS_DB_NSEC_NSEC
+                                          ? "NSEC"
+                                          : "NORMAL"),
                        isc_result_totext(check[i].result),
                        isc_result_totext(result));
 #endif
@@ -679,26 +819,28 @@ check_predecessors_withchain(dns_qp_t *qp, struct check_predecessors check[],
                         * we found an exact match; iterate to find
                         * the predecessor.
                         */
-                       result = dns_qpiter_prev(&it, pred, NULL, NULL);
+                       result = dns_qpiter_prev(&it, pred, NULL, &ival);
                        if (result == ISC_R_NOMORE) {
-                               result = dns_qpiter_prev(&it, pred, NULL, NULL);
+                               result = dns_qpiter_prev(&it, pred, NULL,
+                                                        &ival);
                        }
                } else {
                        /*
                         * we didn't find a match, so the iterator should
                         * already be pointed at the predecessor node.
                         */
-                       result = dns_qpiter_current(&it, pred, NULL, NULL);
+                       result = dns_qpiter_current(&it, pred, NULL, &ival);
                }
                assert_int_equal(result, ISC_R_SUCCESS);
 
                result = dns_name_tostring(pred, &namestr, mctx);
 #if 0
-               fprintf(stderr, "... expected predecessor %s got %s\n",
-                       predstr, namestr);
+               fprintf(stderr, "... expected predecessor %s %u got %s %u\n",
+                       predstr, check[i].pdenial, namestr, ival);
 #endif
                assert_int_equal(result, ISC_R_SUCCESS);
                assert_string_equal(namestr, predstr);
+               assert_int_equal(ival, check[i].pdenial);
 
 #if 0
                fprintf(stderr, "%d: remaining names after %s:\n", i, namestr);
@@ -717,10 +859,12 @@ check_predecessors_withchain(dns_qp_t *qp, struct check_predecessors check[],
 #endif
                        j++;
                }
+
 #if 0
-               fprintf(stderr, "\n...expected %d got %d\n",
-                       check[i].remaining, j);
+               fprintf(stderr, "\n...expected %d got %d\n", check[i].remaining,
+                       j);
 #endif
+
                assert_int_equal(j, check[i].remaining);
        }
 }
@@ -745,87 +889,490 @@ ISC_RUN_TEST_IMPL(predecessors) {
 
        dns_qp_create(mctx, &string_methods, NULL, &qp);
        while (insert[i][0] != '\0') {
-               insert_str(qp, insert[i++]);
+               insert_name(qp, insert[i], DNS_DB_NSEC_NORMAL);
+               insert_name(qp, insert[i], DNS_DB_NSEC_NSEC);
+               insert_name(qp, insert[i], DNS_DB_NSEC_NSEC3);
+               i++;
        }
 
        /* first check: no root label in the database */
        static struct check_predecessors check1[] = {
-               { ".", "moops.", ISC_R_NOTFOUND, 0 },
-               { "a.", "moops.", ISC_R_SUCCESS, 0 },
-               { "b.a.", "a.", ISC_R_SUCCESS, 14 },
-               { "b.", "e.d.c.b.a.", ISC_R_SUCCESS, 11 },
-               { "aaa.a.", "a.", DNS_R_PARTIALMATCH, 14 },
-               { "ddd.a.", "e.d.c.b.a.", DNS_R_PARTIALMATCH, 11 },
-               { "d.c.", "c.b.b.", ISC_R_NOTFOUND, 9 },
-               { "1.2.c.b.a.", "c.b.a.", DNS_R_PARTIALMATCH, 12 },
-               { "a.b.c.e.f.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 },
-               { "z.y.x.", "moops.", ISC_R_NOTFOUND, 0 },
-               { "w.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH, 6 },
-               { "z.z.z.z.k.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH, 6 },
-               { "w.k.c.d.", "a.b.c.d.", DNS_R_PARTIALMATCH, 7 },
-               { "d.a.", "e.d.c.b.a.", DNS_R_PARTIALMATCH, 11 },
-               { "0.b.c.d.e.", "x.k.c.d.", ISC_R_NOTFOUND, 6 },
-               { "b.d.", "c.b.b.", ISC_R_NOTFOUND, 9 },
-               { "mon.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 },
-               { "moor.", "moops.", ISC_R_NOTFOUND, 0 },
-               { "mopbop.", "moops.", ISC_R_NOTFOUND, 0 },
-               { "moppop.", "moops.", ISC_R_NOTFOUND, 0 },
-               { "mopps.", "moops.", ISC_R_NOTFOUND, 0 },
-               { "mopzop.", "moops.", ISC_R_NOTFOUND, 0 },
-               { "mop.", "moops.", ISC_R_NOTFOUND, 0 },
-               { "monbop.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 },
-               { "monpop.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 },
-               { "monps.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 },
-               { "monzop.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 },
-               { "mon.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 },
-               { "moop.", "moon.", ISC_R_NOTFOUND, 1 },
-               { "moopser.", "moops.", ISC_R_NOTFOUND, 0 },
-               { "monky.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 },
-               { "monkey.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 },
-               { "monker.", "a.b.c.d.e.", ISC_R_NOTFOUND, 5 },
-               { NULL, NULL, 0, 0 }
+               { ".", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+               { ".", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 30 },
+               { ".", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 15 },
+
+               { "a.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_SUCCESS, 0 },
+               { "a.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS, 30 },
+               { "a.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_SUCCESS, 15 },
+
+               { "b.a.", DNS_DB_NSEC_NORMAL, "a.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS, 44 },
+               { "b.a.", DNS_DB_NSEC_NSEC, "a.", DNS_DB_NSEC_NSEC,
+                 ISC_R_SUCCESS, 29 },
+               { "b.a.", DNS_DB_NSEC_NSEC3, "a.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_SUCCESS, 14 },
+
+               { "b.", DNS_DB_NSEC_NORMAL, "e.d.c.b.a.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS, 41 },
+               { "b.", DNS_DB_NSEC_NSEC, "e.d.c.b.a.", DNS_DB_NSEC_NSEC,
+                 ISC_R_SUCCESS, 26 },
+               { "b.", DNS_DB_NSEC_NSEC3, "e.d.c.b.a.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_SUCCESS, 11 },
+
+               { "aaa.a.", DNS_DB_NSEC_NORMAL, "a.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 44 },
+               { "aaa.a.", DNS_DB_NSEC_NSEC, "a.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 29 },
+               { "aaa.a.", DNS_DB_NSEC_NSEC3, "a.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 14 },
+
+               { "ddd.a.", DNS_DB_NSEC_NORMAL, "e.d.c.b.a.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 41 },
+               { "ddd.a.", DNS_DB_NSEC_NSEC, "e.d.c.b.a.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 26 },
+               { "ddd.a.", DNS_DB_NSEC_NSEC3, "e.d.c.b.a.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 11 },
+
+               { "d.c.", DNS_DB_NSEC_NORMAL, "c.b.b.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 39 },
+               { "d.c.", DNS_DB_NSEC_NSEC, "c.b.b.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 24 },
+               { "d.c.", DNS_DB_NSEC_NSEC3, "c.b.b.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 9 },
+
+               { "1.2.c.b.a.", DNS_DB_NSEC_NORMAL, "c.b.a.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 42 },
+               { "1.2.c.b.a.", DNS_DB_NSEC_NSEC, "c.b.a.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 27 },
+               { "1.2.c.b.a.", DNS_DB_NSEC_NSEC3, "c.b.a.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 12 },
+
+               { "a.b.c.e.f.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 35 },
+               { "a.b.c.e.f.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NSEC, ISC_R_NOTFOUND, 20 },
+               { "a.b.c.e.f.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NSEC3, ISC_R_NOTFOUND, 5 },
+
+               { "z.y.x.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 30 },
+               { "z.y.x.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 15 },
+               { "z.y.x.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+
+               { "w.c.d.", DNS_DB_NSEC_NORMAL, "x.k.c.d.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 36 },
+               { "w.c.d.", DNS_DB_NSEC_NSEC, "x.k.c.d.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 21 },
+               { "w.c.d.", DNS_DB_NSEC_NSEC3, "x.k.c.d.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 6 },
+
+               { "z.z.z.z.k.c.d.", DNS_DB_NSEC_NORMAL, "x.k.c.d.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 36 },
+               { "z.z.z.z.k.c.d.", DNS_DB_NSEC_NSEC, "x.k.c.d.",
+                 DNS_DB_NSEC_NSEC, DNS_R_PARTIALMATCH, 21 },
+               { "z.z.z.z.k.c.d.", DNS_DB_NSEC_NSEC3, "x.k.c.d.",
+                 DNS_DB_NSEC_NSEC3, DNS_R_PARTIALMATCH, 6 },
+
+               { "w.k.c.d.", DNS_DB_NSEC_NORMAL, "a.b.c.d.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 37 },
+               { "w.k.c.d.", DNS_DB_NSEC_NSEC, "a.b.c.d.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 22 },
+               { "w.k.c.d.", DNS_DB_NSEC_NSEC3, "a.b.c.d.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 7 },
+
+               { "d.a.", DNS_DB_NSEC_NORMAL, "e.d.c.b.a.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 41 },
+               { "d.a.", DNS_DB_NSEC_NSEC, "e.d.c.b.a.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 26 },
+               { "d.a.", DNS_DB_NSEC_NSEC3, "e.d.c.b.a.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 11 },
+
+               { "0.b.c.d.e.", DNS_DB_NSEC_NORMAL, "x.k.c.d.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 36 },
+               { "0.b.c.d.e.", DNS_DB_NSEC_NSEC, "x.k.c.d.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 21 },
+               { "0.b.c.d.e.", DNS_DB_NSEC_NSEC3, "x.k.c.d.",
+                 DNS_DB_NSEC_NSEC3, ISC_R_NOTFOUND, 6 },
+
+               { "b.d.", DNS_DB_NSEC_NORMAL, "c.b.b.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 39 },
+               { "b.d.", DNS_DB_NSEC_NSEC, "c.b.b.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 24 },
+               { "b.d.", DNS_DB_NSEC_NSEC3, "c.b.b.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 9 },
+
+               { "mon.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 35 },
+               { "mon.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 20 },
+               { "mon.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 5 },
+
+               { "moor.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 30 },
+               { "moor.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 15 },
+               { "moor.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+
+               { "mopbop.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 30 },
+               { "mopbop.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 15 },
+               { "mopbop.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+
+               { "moppop.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 30 },
+               { "moppop.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 15 },
+               { "moppop.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+
+               { "mopps.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 30 },
+               { "mopps.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 15 },
+               { "mopps.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+
+               { "mopzop.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 30 },
+               { "mopzop.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 15 },
+               { "mopzop.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+
+               { "mop.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 30 },
+               { "mop.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 15 },
+               { "mop.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+
+               { "monbop.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 35 },
+               { "monbop.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 20 },
+               { "monbop.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 5 },
+
+               { "monpop.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 35 },
+               { "monpop.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 20 },
+               { "monpop.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 5 },
+
+               { "monps.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 35 },
+               { "monps.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 20 },
+               { "monps.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 5 },
+
+               { "monzop.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 35 },
+               { "monzop.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 20 },
+               { "monzop.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 5 },
+
+               { "mon.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 35 },
+               { "mon.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 20 },
+               { "mon.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 5 },
+
+               { "moop.", DNS_DB_NSEC_NORMAL, "moon.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 31 },
+               { "moop.", DNS_DB_NSEC_NSEC, "moon.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 16 },
+               { "moop.", DNS_DB_NSEC_NSEC3, "moon.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 1 },
+
+               { "moopser.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 30 },
+               { "moopser.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 15 },
+               { "moopser.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+
+               { "monky.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 35 },
+               { "monky.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 20 },
+               { "monky.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 5 },
+
+               { "monkey.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 35 },
+               { "monkey.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 20 },
+               { "monkey.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 5 },
+
+               { "monker.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 35 },
+               { "monker.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 20 },
+               { "monker.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 5 },
+
+               { NULL, 0, NULL, 0, 0, 0 }
        };
 
        check_predecessors(qp, check1);
 
        /* second check: add a root label and try again */
        const char root[16] = ".";
-       insert_str(qp, root);
+       insert_name(qp, root, DNS_DB_NSEC_NORMAL);
+       insert_name(qp, root, DNS_DB_NSEC_NSEC);
+       insert_name(qp, root, DNS_DB_NSEC_NSEC3);
+       i++;
 
        static struct check_predecessors check2[] = {
-               { ".", "moops.", ISC_R_SUCCESS, 0 },
-               { "a.", ".", ISC_R_SUCCESS, 15 },
-               { "b.a.", "a.", ISC_R_SUCCESS, 14 },
-               { "b.", "e.d.c.b.a.", ISC_R_SUCCESS, 11 },
-               { "aaa.a.", "a.", DNS_R_PARTIALMATCH, 14 },
-               { "ddd.a.", "e.d.c.b.a.", DNS_R_PARTIALMATCH, 11 },
-               { "d.c.", "c.b.b.", DNS_R_PARTIALMATCH, 9 },
-               { "1.2.c.b.a.", "c.b.a.", DNS_R_PARTIALMATCH, 12 },
-               { "a.b.c.e.f.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 },
-               { "z.y.x.", "moops.", DNS_R_PARTIALMATCH, 0 },
-               { "w.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH, 6 },
-               { "z.z.z.z.k.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH, 6 },
-               { "w.k.c.d.", "a.b.c.d.", DNS_R_PARTIALMATCH, 7 },
-               { "d.a.", "e.d.c.b.a.", DNS_R_PARTIALMATCH, 11 },
-               { "0.b.c.d.e.", "x.k.c.d.", DNS_R_PARTIALMATCH, 6 },
-               { "mon.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 },
-               { "moor.", "moops.", DNS_R_PARTIALMATCH, 0 },
-               { "mopbop.", "moops.", DNS_R_PARTIALMATCH, 0 },
-               { "moppop.", "moops.", DNS_R_PARTIALMATCH, 0 },
-               { "mopps.", "moops.", DNS_R_PARTIALMATCH, 0 },
-               { "mopzop.", "moops.", DNS_R_PARTIALMATCH, 0 },
-               { "mop.", "moops.", DNS_R_PARTIALMATCH, 0 },
-               { "monbop.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 },
-               { "monpop.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 },
-               { "monps.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 },
-               { "monzop.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 },
-               { "mon.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 },
-               { "moop.", "moon.", DNS_R_PARTIALMATCH, 1 },
-               { "moopser.", "moops.", DNS_R_PARTIALMATCH, 0 },
-               { "monky.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 },
-               { "monkey.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 },
-               { "monker.", "a.b.c.d.e.", DNS_R_PARTIALMATCH, 5 },
-               { NULL, NULL, 0, 0 }
+               { ".", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_SUCCESS, 0 },
+               { ".", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS, 32 },
+               { ".", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC,
+                 ISC_R_SUCCESS, 16 },
+
+               { "a.", DNS_DB_NSEC_NORMAL, ".", DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS, 47 },
+               { "a.", DNS_DB_NSEC_NSEC, ".", DNS_DB_NSEC_NSEC, ISC_R_SUCCESS,
+                 31 },
+               { "a.", DNS_DB_NSEC_NSEC3, ".", DNS_DB_NSEC_NSEC3,
+                 ISC_R_SUCCESS, 15 },
+
+               { "b.a.", DNS_DB_NSEC_NORMAL, "a.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS, 46 },
+               { "b.a.", DNS_DB_NSEC_NSEC, "a.", DNS_DB_NSEC_NSEC,
+                 ISC_R_SUCCESS, 30 },
+               { "b.a.", DNS_DB_NSEC_NSEC3, "a.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_SUCCESS, 14 },
+
+               { "b.", DNS_DB_NSEC_NORMAL, "e.d.c.b.a.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS, 43 },
+               { "b.", DNS_DB_NSEC_NSEC, "e.d.c.b.a.", DNS_DB_NSEC_NSEC,
+                 ISC_R_SUCCESS, 27 },
+               { "b.", DNS_DB_NSEC_NSEC3, "e.d.c.b.a.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_SUCCESS, 11 },
+
+               { "aaa.a.", DNS_DB_NSEC_NORMAL, "a.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 46 },
+               { "aaa.a.", DNS_DB_NSEC_NSEC, "a.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 30 },
+               { "aaa.a.", DNS_DB_NSEC_NSEC3, "a.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 14 },
+
+               { "ddd.a.", DNS_DB_NSEC_NORMAL, "e.d.c.b.a.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 43 },
+               { "ddd.a.", DNS_DB_NSEC_NSEC, "e.d.c.b.a.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 27 },
+               { "ddd.a.", DNS_DB_NSEC_NSEC3, "e.d.c.b.a.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 11 },
+
+               { "d.c.", DNS_DB_NSEC_NORMAL, "c.b.b.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 41 },
+               { "d.c.", DNS_DB_NSEC_NSEC, "c.b.b.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 25 },
+               { "d.c.", DNS_DB_NSEC_NSEC3, "c.b.b.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 9 },
+
+               { "1.2.c.b.a.", DNS_DB_NSEC_NORMAL, "c.b.a.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 44 },
+               { "1.2.c.b.a.", DNS_DB_NSEC_NSEC, "c.b.a.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 28 },
+               { "1.2.c.b.a.", DNS_DB_NSEC_NSEC3, "c.b.a.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 12 },
+
+               { "a.b.c.e.f.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 37 },
+               { "a.b.c.e.f.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NSEC, DNS_R_PARTIALMATCH, 21 },
+               { "a.b.c.e.f.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NSEC3, DNS_R_PARTIALMATCH, 5 },
+
+               { "z.y.x.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 32 },
+               { "z.y.x.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 16 },
+               { "z.y.x.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "w.c.d.", DNS_DB_NSEC_NORMAL, "x.k.c.d.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 38 },
+               { "w.c.d.", DNS_DB_NSEC_NSEC, "x.k.c.d.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 22 },
+               { "w.c.d.", DNS_DB_NSEC_NSEC3, "x.k.c.d.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 6 },
+
+               { "z.z.z.z.k.c.d.", DNS_DB_NSEC_NORMAL, "x.k.c.d.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 38 },
+               { "z.z.z.z.k.c.d.", DNS_DB_NSEC_NSEC, "x.k.c.d.",
+                 DNS_DB_NSEC_NSEC, DNS_R_PARTIALMATCH, 22 },
+               { "z.z.z.z.k.c.d.", DNS_DB_NSEC_NSEC3, "x.k.c.d.",
+                 DNS_DB_NSEC_NSEC3, DNS_R_PARTIALMATCH, 6 },
+
+               { "w.k.c.d.", DNS_DB_NSEC_NORMAL, "a.b.c.d.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 39 },
+               { "w.k.c.d.", DNS_DB_NSEC_NSEC, "a.b.c.d.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 23 },
+               { "w.k.c.d.", DNS_DB_NSEC_NSEC3, "a.b.c.d.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 7 },
+
+               { "d.a.", DNS_DB_NSEC_NORMAL, "e.d.c.b.a.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 43 },
+               { "d.a.", DNS_DB_NSEC_NSEC, "e.d.c.b.a.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 27 },
+               { "d.a.", DNS_DB_NSEC_NSEC3, "e.d.c.b.a.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 11 },
+
+               { "0.b.c.d.e.", DNS_DB_NSEC_NORMAL, "x.k.c.d.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 38 },
+               { "0.b.c.d.e.", DNS_DB_NSEC_NSEC, "x.k.c.d.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 22 },
+               { "0.b.c.d.e.", DNS_DB_NSEC_NSEC3, "x.k.c.d.",
+                 DNS_DB_NSEC_NSEC3, DNS_R_PARTIALMATCH, 6 },
+
+               { "b.d.", DNS_DB_NSEC_NORMAL, "c.b.b.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 41 },
+               { "b.d.", DNS_DB_NSEC_NSEC, "c.b.b.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 25 },
+               { "b.d.", DNS_DB_NSEC_NSEC3, "c.b.b.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 9 },
+
+               { "mon.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 37 },
+               { "mon.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 21 },
+               { "mon.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 5 },
+
+               { "moor.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 32 },
+               { "moor.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 16 },
+               { "moor.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "mopbop.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 32 },
+               { "mopbop.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 16 },
+               { "mopbop.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "moppop.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 32 },
+               { "moppop.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 16 },
+               { "moppop.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "mopps.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 32 },
+               { "mopps.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 16 },
+               { "mopps.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "mopzop.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 32 },
+               { "mopzop.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 16 },
+               { "mopzop.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "mop.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 32 },
+               { "mop.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 16 },
+               { "mop.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "monbop.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 37 },
+               { "monbop.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 21 },
+               { "monbop.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 5 },
+
+               { "monpop.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 37 },
+               { "monpop.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 21 },
+               { "monpop.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 5 },
+
+               { "monps.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 37 },
+               { "monps.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 21 },
+               { "monps.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 5 },
+
+               { "monzop.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 37 },
+               { "monzop.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 21 },
+               { "monzop.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 5 },
+
+               { "mon.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 37 },
+               { "mon.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 21 },
+               { "mon.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 5 },
+
+               { "moop.", DNS_DB_NSEC_NORMAL, "moon.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 33 },
+               { "moop.", DNS_DB_NSEC_NSEC, "moon.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 17 },
+               { "moop.", DNS_DB_NSEC_NSEC3, "moon.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 1 },
+
+               { "moopser.", DNS_DB_NSEC_NORMAL, "moops.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 32 },
+               { "moopser.", DNS_DB_NSEC_NSEC, "moops.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 16 },
+               { "moopser.", DNS_DB_NSEC_NSEC3, "moops.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "monky.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 37 },
+               { "monky.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 21 },
+               { "monky.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 5 },
+
+               { "monkey.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 37 },
+               { "monkey.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 21 },
+               { "monkey.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 5 },
+
+               { "monker.", DNS_DB_NSEC_NORMAL, "a.b.c.d.e.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 37 },
+               { "monker.", DNS_DB_NSEC_NSEC, "a.b.c.d.e.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 21 },
+               { "monker.", DNS_DB_NSEC_NSEC3, "a.b.c.d.e.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 5 },
+
+               { NULL, 0, NULL, 0, 0, 0 }
        };
 
        check_predecessors(qp, check2);
@@ -861,18 +1408,63 @@ ISC_RUN_TEST_IMPL(fixiterator) {
 
        dns_qp_create(mctx, &string_methods, NULL, &qp);
        while (insert1[i][0] != '\0') {
-               insert_str(qp, insert1[i++]);
+               insert_name(qp, insert1[i], DNS_DB_NSEC_NORMAL);
+               insert_name(qp, insert1[i], DNS_DB_NSEC_NSEC);
+               insert_name(qp, insert1[i], DNS_DB_NSEC_NSEC3);
+               i++;
        }
 
        static struct check_predecessors check1[] = {
-               { "newtext.dynamic.", "mx.dynamic.", DNS_R_PARTIALMATCH, 7 },
-               { "nsd.dynamic.", "ns.dynamic.", DNS_R_PARTIALMATCH, 6 },
-               { "nsf.dynamic.", "nsec.dynamic.", DNS_R_PARTIALMATCH, 5 },
-               { "d.", "trailing.", ISC_R_NOTFOUND, 0 },
-               { "absent.", "trailing.", ISC_R_NOTFOUND, 0 },
-               { "nonexistent.", "txt.dynamic.", ISC_R_NOTFOUND, 1 },
-               { "wayback.", "trailing.", ISC_R_NOTFOUND, 0 },
-               { NULL, NULL, 0, 0 }
+               { "newtext.dynamic.", DNS_DB_NSEC_NORMAL, "mx.dynamic.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 41 },
+               { "newtext.dynamic.", DNS_DB_NSEC_NSEC, "mx.dynamic.",
+                 DNS_DB_NSEC_NSEC, DNS_R_PARTIALMATCH, 24 },
+               { "newtext.dynamic.", DNS_DB_NSEC_NSEC3, "mx.dynamic.",
+                 DNS_DB_NSEC_NSEC3, DNS_R_PARTIALMATCH, 7 },
+
+               { "nsd.dynamic.", DNS_DB_NSEC_NORMAL, "ns.dynamic.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 40 },
+               { "nsd.dynamic.", DNS_DB_NSEC_NSEC, "ns.dynamic.",
+                 DNS_DB_NSEC_NSEC, DNS_R_PARTIALMATCH, 23 },
+               { "nsd.dynamic.", DNS_DB_NSEC_NSEC3, "ns.dynamic.",
+                 DNS_DB_NSEC_NSEC3, DNS_R_PARTIALMATCH, 6 },
+
+               { "nsf.dynamic.", DNS_DB_NSEC_NORMAL, "nsec.dynamic.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 39 },
+               { "nsf.dynamic.", DNS_DB_NSEC_NSEC, "nsec.dynamic.",
+                 DNS_DB_NSEC_NSEC, DNS_R_PARTIALMATCH, 22 },
+               { "nsf.dynamic.", DNS_DB_NSEC_NSEC3, "nsec.dynamic.",
+                 DNS_DB_NSEC_NSEC3, DNS_R_PARTIALMATCH, 5 },
+
+               { "d.", DNS_DB_NSEC_NORMAL, "trailing.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+               { "d.", DNS_DB_NSEC_NSEC, "trailing.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 34 },
+               { "d.", DNS_DB_NSEC_NSEC3, "trailing.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 17 },
+
+               { "absent.", DNS_DB_NSEC_NORMAL, "trailing.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+               { "absent.", DNS_DB_NSEC_NSEC, "trailing.", DNS_DB_NSEC_NORMAL,
+                 ISC_R_NOTFOUND, 34 },
+               { "absent.", DNS_DB_NSEC_NSEC3, "trailing.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 17 },
+
+               { "nonexistent.", DNS_DB_NSEC_NORMAL, "txt.dynamic.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 35 },
+               { "nonexistent.", DNS_DB_NSEC_NSEC, "txt.dynamic.",
+                 DNS_DB_NSEC_NSEC, ISC_R_NOTFOUND, 18 },
+               { "nonexistent.", DNS_DB_NSEC_NSEC3, "txt.dynamic.",
+                 DNS_DB_NSEC_NSEC3, ISC_R_NOTFOUND, 1 },
+
+               { "wayback.", DNS_DB_NSEC_NORMAL, "trailing.",
+                 DNS_DB_NSEC_NORMAL, ISC_R_NOTFOUND, 34 },
+               { "wayback.", DNS_DB_NSEC_NSEC, "trailing.", DNS_DB_NSEC_NSEC,
+                 ISC_R_NOTFOUND, 17 },
+               { "wayback.", DNS_DB_NSEC_NSEC3, "trailing.", DNS_DB_NSEC_NSEC3,
+                 ISC_R_NOTFOUND, 0 },
+
+               { NULL, 0, NULL, 0, 0, 0 }
        };
 
        check_predecessors(qp, check1);
@@ -883,15 +1475,42 @@ ISC_RUN_TEST_IMPL(fixiterator) {
 
        dns_qp_create(mctx, &string_methods, NULL, &qp);
        while (insert2[i][0] != '\0') {
-               insert_str(qp, insert2[i++]);
+               insert_name(qp, insert2[i], DNS_DB_NSEC_NORMAL);
+               insert_name(qp, insert2[i], DNS_DB_NSEC_NSEC);
+               insert_name(qp, insert2[i], DNS_DB_NSEC_NSEC3);
+               i++;
        }
 
        static struct check_predecessors check2[] = {
-               { "acb.", "abc.", DNS_R_PARTIALMATCH, 0 },
-               { "acc.", "abc.", DNS_R_PARTIALMATCH, 0 },
-               { "abbb.", "abb.", DNS_R_PARTIALMATCH, 1 },
-               { "aab.", ".", DNS_R_PARTIALMATCH, 2 },
-               { NULL, NULL, 0, 0 }
+               { "acb.", DNS_DB_NSEC_NORMAL, "abc.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 6 },
+               { "acb.", DNS_DB_NSEC_NSEC, "abc.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 3 },
+               { "acb.", DNS_DB_NSEC_NSEC3, "abc.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "acc.", DNS_DB_NSEC_NORMAL, "abc.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 6 },
+               { "acc.", DNS_DB_NSEC_NSEC, "abc.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 3 },
+               { "acc.", DNS_DB_NSEC_NSEC3, "abc.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "abbb.", DNS_DB_NSEC_NORMAL, "abb.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 7 },
+               { "abbb.", DNS_DB_NSEC_NSEC, "abb.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 4 },
+               { "abbb.", DNS_DB_NSEC_NSEC3, "abb.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 1 },
+
+               { "aab.", DNS_DB_NSEC_NORMAL, ".", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 8 },
+               { "aab.", DNS_DB_NSEC_NSEC, ".", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 5 },
+               { "aab.", DNS_DB_NSEC_NSEC3, ".", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 2 },
+
+               { NULL, 0, NULL, 0, 0, 0 }
        };
 
        check_predecessors(qp, check2);
@@ -907,13 +1526,24 @@ ISC_RUN_TEST_IMPL(fixiterator) {
 
        dns_qp_create(mctx, &string_methods, NULL, &qp);
        while (insert3[i][0] != '\0') {
-               insert_str(qp, insert3[i++]);
+               insert_name(qp, insert3[i], DNS_DB_NSEC_NORMAL);
+               insert_name(qp, insert3[i], DNS_DB_NSEC_NSEC);
+               insert_name(qp, insert3[i], DNS_DB_NSEC_NSEC3);
+               i++;
        }
 
-       static struct check_predecessors check3[] = { { "key-is-21556.example.",
-                                                       "key-is-14779.example.",
-                                                       DNS_R_PARTIALMATCH, 2 },
-                                                     { NULL, NULL, 0, 0 } };
+       static struct check_predecessors check3[] = {
+               { "key-is-21556.example.", DNS_DB_NSEC_NORMAL,
+                 "key-is-14779.example.", DNS_DB_NSEC_NORMAL,
+                 DNS_R_PARTIALMATCH, 12 },
+               { "key-is-21556.example.", DNS_DB_NSEC_NSEC,
+                 "key-is-14779.example.", DNS_DB_NSEC_NSEC, DNS_R_PARTIALMATCH,
+                 7 },
+               { "key-is-21556.example.", DNS_DB_NSEC_NSEC3,
+                 "key-is-14779.example.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 2 },
+               { NULL, 0, NULL, 0, 0, 0 }
+       };
 
        check_predecessors(qp, check3);
        dns_qp_destroy(&qp);
@@ -924,16 +1554,49 @@ ISC_RUN_TEST_IMPL(fixiterator) {
 
        dns_qp_create(mctx, &string_methods, NULL, &qp);
        while (insert4[i][0] != '\0') {
-               insert_str(qp, insert4[i++]);
+               insert_name(qp, insert4[i], DNS_DB_NSEC_NORMAL);
+               insert_name(qp, insert4[i], DNS_DB_NSEC_NSEC);
+               insert_name(qp, insert4[i], DNS_DB_NSEC_NSEC3);
+               i++;
        }
 
        static struct check_predecessors check4[] = {
-               { "\\007.", "\\000\\009.", DNS_R_PARTIALMATCH, 0 },
-               { "\\009.", "\\000\\009.", DNS_R_PARTIALMATCH, 0 },
-               { "\\045.", "\\000\\009.", DNS_R_PARTIALMATCH, 0 },
-               { "\\044.", "\\000\\009.", DNS_R_PARTIALMATCH, 0 },
-               { "\\000.", ".", ISC_R_SUCCESS, 3 },
-               { NULL, NULL, 0, 0 },
+               { "\\007.", DNS_DB_NSEC_NORMAL, "\\000\\009.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 8 },
+               { "\\007.", DNS_DB_NSEC_NSEC, "\\000\\009.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 4 },
+               { "\\007.", DNS_DB_NSEC_NSEC3, "\\000\\009.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "\\009.", DNS_DB_NSEC_NORMAL, "\\000\\009.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 8 },
+               { "\\009.", DNS_DB_NSEC_NSEC, "\\000\\009.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 4 },
+               { "\\009.", DNS_DB_NSEC_NSEC3, "\\000\\009.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "\\045.", DNS_DB_NSEC_NORMAL, "\\000\\009.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 8 },
+               { "\\045.", DNS_DB_NSEC_NSEC, "\\000\\009.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 4 },
+               { "\\045.", DNS_DB_NSEC_NSEC3, "\\000\\009.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "\\044.", DNS_DB_NSEC_NORMAL, "\\000\\009.",
+                 DNS_DB_NSEC_NORMAL, DNS_R_PARTIALMATCH, 8 },
+               { "\\044.", DNS_DB_NSEC_NSEC, "\\000\\009.", DNS_DB_NSEC_NSEC,
+                 DNS_R_PARTIALMATCH, 4 },
+               { "\\044.", DNS_DB_NSEC_NSEC3, "\\000\\009.", DNS_DB_NSEC_NSEC3,
+                 DNS_R_PARTIALMATCH, 0 },
+
+               { "\\000.", DNS_DB_NSEC_NORMAL, ".", DNS_DB_NSEC_NORMAL,
+                 ISC_R_SUCCESS, 11 },
+               { "\\000.", DNS_DB_NSEC_NSEC, ".", DNS_DB_NSEC_NSEC,
+                 ISC_R_SUCCESS, 7 },
+               { "\\000.", DNS_DB_NSEC_NSEC3, ".", DNS_DB_NSEC_NSEC3,
+                 ISC_R_SUCCESS, 3 },
+
+               { NULL, 0, NULL, 0, 0, 0 },
        };
 
        check_predecessors(qp, check4);