Compare commits
7 Commits
4702-qp-lo
...
each-qp-lo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74c4d1e8f8 | ||
|
|
3346164b96 | ||
|
|
6b4c329005 | ||
|
|
00ec7a2c25 | ||
|
|
5cd070fc54 | ||
|
|
dd39b16a8d | ||
|
|
6645ed2ba5 |
@@ -528,8 +528,8 @@ dns_qp_getname(dns_qpreadable_t qpr, const dns_name_t *name, void **pval_r,
|
||||
|
||||
isc_result_t
|
||||
dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
|
||||
dns_name_t *foundname, dns_name_t *predecessor,
|
||||
dns_qpchain_t *chain, void **pval_r, uint32_t *ival_r);
|
||||
dns_name_t *foundname, dns_qpiter_t *iter, dns_qpchain_t *chain,
|
||||
void **pval_r, uint32_t *ival_r);
|
||||
/*%<
|
||||
* Look up a leaf in a qp-trie that is equal to, or an ancestor domain of,
|
||||
* 'name'.
|
||||
@@ -547,9 +547,9 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
|
||||
* ISC_R_SUCCESS then it terminates at the name that was requested.
|
||||
* If the result is ISC_R_NOTFOUND, 'chain' will not be updated.
|
||||
*
|
||||
* If 'predecessor' is not NULL, it will be updated to contain the
|
||||
* closest predecessor of the searched-for name that exists in the
|
||||
* trie.
|
||||
* If 'iter' is not NULL, it will be updated to point to a QP iterator
|
||||
* which is pointed at the searched-for name if it exists in the trie,
|
||||
* or the closest predecessor if it doesn't.
|
||||
*
|
||||
* The leaf data for the node that was found will be assigned to
|
||||
* whichever of `*pval_r` and `*ival_r` are not NULL, unless the
|
||||
@@ -559,7 +559,7 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
|
||||
* \li `qpr` is a pointer to a readable qp-trie
|
||||
* \li `name` is a pointer to a valid `dns_name_t`
|
||||
* \li `foundname` is a pointer to a valid `dns_name_t` with
|
||||
* buffer and offset space available, or is NULL.
|
||||
* buffer and offset space available, or is NULL
|
||||
*
|
||||
* Returns:
|
||||
* \li ISC_R_SUCCESS if an exact match was found
|
||||
@@ -666,6 +666,24 @@ dns_qpiter_prev(dns_qpiter_t *qpi, dns_name_t *name, void **pval_r,
|
||||
* \li ISC_R_NOMORE otherwise
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_qpiter_current(dns_qpiter_t *qpi, dns_name_t *name, void **pval_r,
|
||||
uint32_t *ival_r);
|
||||
/*%<
|
||||
* Sets the values of `name`, `pval_r` and `ival_r` to those at the
|
||||
* node currently pointed to by `qpi`, but without moving the iterator
|
||||
* in either direction. If the iterator is not currently pointed at a
|
||||
* leaf node, ISC_R_FAILURE is returned.
|
||||
* Requires:
|
||||
*
|
||||
* \li `qpi` is a pointer to a valid qp iterator
|
||||
*
|
||||
* Returns:
|
||||
* \li ISC_R_SUCCESS if a leaf was found and pval_r and ival_r were set
|
||||
* \li ISC_R_FAILURE if the iterator is not initialized or not pointing
|
||||
* at a leaf node
|
||||
*/
|
||||
|
||||
void
|
||||
dns_qpchain_init(dns_qpreadable_t qpr, dns_qpchain_t *chain);
|
||||
/*%<
|
||||
@@ -673,7 +691,7 @@ dns_qpchain_init(dns_qpreadable_t qpr, dns_qpchain_t *chain);
|
||||
*
|
||||
* Requires:
|
||||
* \li `qpr` is a pointer to a valid qp-trie
|
||||
* \li `chain` is not NULL.
|
||||
* \li `chain` is not NULL
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
@@ -682,7 +700,7 @@ dns_qpchain_length(dns_qpchain_t *chain);
|
||||
* Returns the length of a QP chain.
|
||||
*
|
||||
* Requires:
|
||||
* \li `chain` is a pointer to an initialized QP chain object.
|
||||
* \li `chain` is a pointer to an initialized QP chain object
|
||||
*/
|
||||
|
||||
void
|
||||
@@ -695,8 +713,8 @@ dns_qpchain_node(dns_qpchain_t *chain, unsigned int level, dns_name_t *name,
|
||||
* are not null.
|
||||
*
|
||||
* Requires:
|
||||
* \li `chain` is a pointer to an initialized QP chain object.
|
||||
* \li `level` is less than `chain->len`.
|
||||
* \li `chain` is a pointer to an initialized QP chain object
|
||||
* \li `level` is less than `chain->len`
|
||||
*/
|
||||
|
||||
/***********************************************************************
|
||||
|
||||
280
lib/dns/qp.c
280
lib/dns/qp.c
@@ -1948,6 +1948,24 @@ dns_qpiter_prev(dns_qpiter_t *qpi, dns_name_t *name, void **pval_r,
|
||||
return (iterate(false, qpi, name, pval_r, ival_r));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_qpiter_current(dns_qpiter_t *qpi, dns_name_t *name, void **pval_r,
|
||||
uint32_t *ival_r) {
|
||||
dns_qpnode_t *node = NULL;
|
||||
|
||||
REQUIRE(QPITER_VALID(qpi));
|
||||
|
||||
node = qpi->stack[qpi->sp];
|
||||
if (node == NULL || is_branch(node)) {
|
||||
return (ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
SET_IF_NOT_NULL(pval_r, leaf_pval(node));
|
||||
SET_IF_NOT_NULL(ival_r, leaf_ival(node));
|
||||
maybe_set_name(qpi->qp, node, name);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* search
|
||||
@@ -2020,18 +2038,142 @@ prevleaf(dns_qpiter_t *it) {
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static inline dns_qpnode_t *
|
||||
greatest_leaf(dns_qpreadable_t qpr, dns_qpnode_t *n, dns_qpiter_t *iter) {
|
||||
while (is_branch(n)) {
|
||||
dns_qpref_t ref = branch_twigs_ref(n) + branch_twigs_size(n) -
|
||||
1;
|
||||
iter->stack[++iter->sp] = n;
|
||||
n = ref_ptr(qpr, ref);
|
||||
}
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've been passed an iterator, we want it to point at the matching name
|
||||
* in the case of an exact match, or at the predecessor name for a non-exact
|
||||
* match.
|
||||
*
|
||||
* If the search ended at a leaf, and it was not an exact match, then we're
|
||||
* now pointing at either some predecessor or some successor of the searched-for
|
||||
* name. First find the immediate predecessor or successor, then we can the
|
||||
* qpiter stack to step back one leaf to the predecessor (or if the iterator
|
||||
* already points to the predecessor, or it was an exact match, we don't need to
|
||||
* do anything).
|
||||
*
|
||||
* If the search ended on a branch, we also first have to find the immediate
|
||||
* predecessor or successor. If there are no more suitable twig candidates in
|
||||
* this branch we can again use the qpiter stack to step back one leaf to the
|
||||
* predecessor. Otherwise, we select the right twig from the branch and walk
|
||||
* down to the greatest leaf node.
|
||||
*/
|
||||
static dns_qpnode_t *
|
||||
qpgetpred(dns_qpreader_t *qp, dns_qpiter_t *iter, dns_qpnode_t *n,
|
||||
dns_qpkey_t search, size_t searchlen, dns_qpshift_t bit,
|
||||
size_t offset) {
|
||||
size_t to;
|
||||
dns_qpnode_t *least = n;
|
||||
dns_qpkey_t found;
|
||||
size_t foundlen;
|
||||
dns_qpnode_t *twigs = branch_twigs(qp, n);
|
||||
|
||||
/*
|
||||
* Go down to a leaf node so we can compare something with
|
||||
* the search key.
|
||||
*/
|
||||
while (is_branch(least)) {
|
||||
least = branch_twigs(qp, least);
|
||||
}
|
||||
|
||||
foundlen = leaf_qpkey(qp, least, found);
|
||||
to = qpkey_compare(search, searchlen, found, foundlen);
|
||||
if (to == QPKEY_EQUAL) {
|
||||
return (n);
|
||||
}
|
||||
|
||||
/*
|
||||
* As long as the branch offset point is after the point where the
|
||||
* search key differs, we need to branch up and find a better leaf
|
||||
* node.
|
||||
*/
|
||||
while (to < offset) {
|
||||
if (to <= searchlen && to <= foundlen && search[to] < found[to])
|
||||
{
|
||||
/*
|
||||
* Every leaf is greater than the one we wanted, so
|
||||
* go to the parent branch and iterate back to the
|
||||
* predecessor from that point.
|
||||
*/
|
||||
iter->sp--;
|
||||
prevleaf(iter);
|
||||
n = iter->stack[iter->sp];
|
||||
least = n;
|
||||
} else {
|
||||
if (is_branch(n)) {
|
||||
n = greatest_leaf(qp, n, iter);
|
||||
return (n);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
foundlen = leaf_qpkey(qp, least, found);
|
||||
to = qpkey_compare(search, searchlen, found, foundlen);
|
||||
}
|
||||
|
||||
if (is_branch(n)) {
|
||||
/*
|
||||
* We're on the right branch, so find the best match.
|
||||
*/
|
||||
dns_qpweight_t pos = branch_twig_pos(n, bit);
|
||||
if (pos == 0) {
|
||||
/*
|
||||
* Every leaf in the branch is greater than the one we
|
||||
* wanted; use the iterator to walk back to the
|
||||
* predecessor.
|
||||
*/
|
||||
prevleaf(iter);
|
||||
n = iter->stack[iter->sp--];
|
||||
} else {
|
||||
/*
|
||||
* The name we want would've been after some twig in
|
||||
* this branch. point n to that twig, then walk down
|
||||
* to the highest leaf in that subtree to get
|
||||
* the predecessor.
|
||||
*/
|
||||
n = greatest_leaf(qp, twigs + pos - 1, iter);
|
||||
}
|
||||
|
||||
} else {
|
||||
/*
|
||||
* We're on the right leaf, either the iterator already points
|
||||
* to the rightful predecessor, or it points to an immediate
|
||||
* successor. If the latter, we can now use the qpiter stack
|
||||
* we've constructed to step back to the predecessor. Otherwise,
|
||||
* we don't have to do anything anymore.
|
||||
*/
|
||||
if (to <= searchlen && to <= foundlen && search[to] < found[to])
|
||||
{
|
||||
prevleaf(iter);
|
||||
}
|
||||
}
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
|
||||
dns_name_t *foundname, dns_name_t *predecessor,
|
||||
dns_qpchain_t *chain, void **pval_r, uint32_t *ival_r) {
|
||||
dns_name_t *foundname, dns_qpiter_t *iter, dns_qpchain_t *chain,
|
||||
void **pval_r, uint32_t *ival_r) {
|
||||
dns_qpreader_t *qp = dns_qpreader(qpr);
|
||||
dns_qpkey_t search, found;
|
||||
size_t searchlen, foundlen;
|
||||
size_t offset;
|
||||
size_t offset = 0;
|
||||
dns_qpnode_t *n = NULL;
|
||||
dns_qpshift_t bit = SHIFT_NOBYTE;
|
||||
dns_qpchain_t oc;
|
||||
dns_qpiter_t it;
|
||||
bool matched = true;
|
||||
bool getpred = true;
|
||||
|
||||
REQUIRE(QP_VALID(qp));
|
||||
REQUIRE(foundname == NULL || ISC_MAGIC_VALID(name, DNS_NAME_MAGIC));
|
||||
@@ -2041,42 +2183,50 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
|
||||
if (chain == NULL) {
|
||||
chain = &oc;
|
||||
}
|
||||
if (iter == NULL) {
|
||||
iter = ⁢
|
||||
getpred = false;
|
||||
}
|
||||
dns_qpchain_init(qp, chain);
|
||||
dns_qpiter_init(qp, &it);
|
||||
dns_qpiter_init(qp, iter);
|
||||
|
||||
n = get_root(qp);
|
||||
if (n == NULL) {
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
it.stack[0] = n;
|
||||
iter->stack[0] = n;
|
||||
|
||||
/*
|
||||
* Like `dns_qp_insert()`, we must find a leaf. However, we don't make a
|
||||
* second pass: instead, we keep track of any leaves with shorter keys
|
||||
* that we discover along the way. (In general, qp-trie searches can be
|
||||
* one-pass, by recording their traversal, or two-pass, for less stack
|
||||
* memory usage.)
|
||||
* Like `dns_qp_insert()`, we must find a leaf. However,
|
||||
* we don't make a second pass: instead, we keep track
|
||||
* of any leaves with shorter keys that we discover
|
||||
* along the way. (In general, qp-trie searches can be
|
||||
* one-pass, by recording their traversal, or two-pass,
|
||||
* for less stack memory usage.)
|
||||
*/
|
||||
while (is_branch(n)) {
|
||||
prefetch_twigs(qp, n);
|
||||
|
||||
offset = branch_key_offset(n);
|
||||
dns_qpshift_t bit = qpkey_bit(search, searchlen, offset);
|
||||
bit = qpkey_bit(search, searchlen, offset);
|
||||
dns_qpnode_t *twigs = branch_twigs(qp, n);
|
||||
|
||||
/*
|
||||
* A shorter key that can be a parent domain always has a
|
||||
* leaf node at SHIFT_NOBYTE (indicating end of its key)
|
||||
* where our search key has a normal character immediately
|
||||
* after a label separator.
|
||||
* A shorter key that can be a parent domain
|
||||
* always has a leaf node at SHIFT_NOBYTE
|
||||
* (indicating end of its key) where our search
|
||||
* key has a normal character immediately after
|
||||
* a label separator.
|
||||
*
|
||||
* Note 1: It is OK if `off - 1` underflows: it will
|
||||
* become SIZE_MAX, which is greater than `searchlen`, so
|
||||
* `qpkey_bit()` will return SHIFT_NOBYTE, which is what we
|
||||
* want when `off == 0`.
|
||||
* Note 1: It is OK if `off - 1` underflows: it
|
||||
* will become SIZE_MAX, which is greater than
|
||||
* `searchlen`, so `qpkey_bit()` will return
|
||||
* SHIFT_NOBYTE, which is what we want when `off
|
||||
* == 0`.
|
||||
*
|
||||
* Note 2: If SHIFT_NOBYTE twig is present, it will always
|
||||
* be in position 0, the first localtion in 'twigs'.
|
||||
* Note 2: If SHIFT_NOBYTE twig is present, it
|
||||
* will always be in position 0, the first
|
||||
* localtion in 'twigs'.
|
||||
*/
|
||||
if (bit != SHIFT_NOBYTE && branch_has_twig(n, SHIFT_NOBYTE) &&
|
||||
qpkey_bit(search, searchlen, offset - 1) == SHIFT_NOBYTE &&
|
||||
@@ -2088,54 +2238,37 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
|
||||
matched = branch_has_twig(n, bit);
|
||||
if (matched) {
|
||||
/*
|
||||
* found a match: if it's a branch, we keep
|
||||
* searching, and if it's a leaf, we drop out of
|
||||
* the loop.
|
||||
* found a match: if it's a branch, we
|
||||
* keep searching, and if it's a leaf,
|
||||
* we drop out of the loop.
|
||||
*/
|
||||
n = branch_twig_ptr(qp, n, bit);
|
||||
} else if (predecessor != NULL) {
|
||||
} else if (getpred) {
|
||||
/*
|
||||
* this branch is a dead end, but the caller wants
|
||||
* the predecessor to the name we were searching
|
||||
* for, so let's go find that.
|
||||
* this branch is a dead end. however,
|
||||
* the caller passed us an iterator, so
|
||||
* we need to find the predecessor of
|
||||
* the searched-for-name. first step:
|
||||
* find out if we've overshot the search
|
||||
* key; we do that by finding an
|
||||
* arbitrary leaf to compare against.
|
||||
*/
|
||||
dns_qpweight_t pos = branch_twig_pos(n, bit);
|
||||
if (pos == 0) {
|
||||
/*
|
||||
* this entire branch is greater than
|
||||
* the key we wanted, so we step back to
|
||||
* the predecessor using the iterator.
|
||||
*/
|
||||
prevleaf(&it);
|
||||
n = it.stack[it.sp];
|
||||
} else {
|
||||
/*
|
||||
* the name we want would've been between
|
||||
* two twigs in this branch. point n to the
|
||||
* lesser of those, then walk down to the
|
||||
* highest leaf in that subtree to get the
|
||||
* predecessor.
|
||||
*/
|
||||
n = twigs + pos - 1;
|
||||
while (is_branch(n)) {
|
||||
prefetch_twigs(qp, n);
|
||||
it.stack[++it.sp] = n;
|
||||
pos = branch_twigs_size(n) - 1;
|
||||
n = ref_ptr(qp,
|
||||
branch_twigs_ref(n) + pos);
|
||||
}
|
||||
}
|
||||
n = qpgetpred(qp, iter, n, search, searchlen, bit,
|
||||
offset);
|
||||
} else {
|
||||
/*
|
||||
* this branch is a dead end, and the predecessor
|
||||
* doesn't matter. now we just need to find a leaf
|
||||
* to end on so qpkey_leaf() will work below.
|
||||
* this branch is a dead end, and the
|
||||
* predecessor doesn't matter. now we
|
||||
* just need to find a leaf to end on so
|
||||
* qpkey_leaf() will work below.
|
||||
*/
|
||||
if (chain->len > 0) {
|
||||
/* we saved an ancestor leaf: use that */
|
||||
/* we saved an ancestor leaf:
|
||||
* use that */
|
||||
n = chain->chain[chain->len - 1].node;
|
||||
} else {
|
||||
/* walk down to find the leftmost leaf */
|
||||
/* walk down to find the
|
||||
* leftmost leaf */
|
||||
while (is_branch(twigs)) {
|
||||
twigs = branch_twigs(qp, twigs);
|
||||
}
|
||||
@@ -2143,29 +2276,17 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
|
||||
}
|
||||
}
|
||||
|
||||
it.stack[++it.sp] = n;
|
||||
iter->stack[++iter->sp] = n;
|
||||
}
|
||||
|
||||
if (getpred && matched) {
|
||||
n = qpgetpred(qp, iter, n, search, searchlen, bit, offset);
|
||||
}
|
||||
|
||||
/* do the keys differ, and if so, where? */
|
||||
foundlen = leaf_qpkey(qp, n, found);
|
||||
offset = qpkey_compare(search, searchlen, found, foundlen);
|
||||
|
||||
/*
|
||||
* if we've been asked to return the predecessor name, we
|
||||
* work that out here.
|
||||
*
|
||||
* if 'matched' is true, the search ended at a leaf. it's either
|
||||
* an exact match or the immediate successor of the searched-for
|
||||
* name, and in either case, we can use the qpiter stack we've
|
||||
* constructed to step back to the predecessor. if 'matched' is
|
||||
* false, then the search failed at a branch node, and we would
|
||||
* have already found the predecessor.
|
||||
*/
|
||||
if (predecessor != NULL && matched) {
|
||||
prevleaf(&it);
|
||||
}
|
||||
maybe_set_name(qp, it.stack[it.sp], predecessor);
|
||||
|
||||
if (offset == QPKEY_EQUAL || offset == foundlen) {
|
||||
SET_IF_NOT_NULL(pval_r, leaf_pval(n));
|
||||
SET_IF_NOT_NULL(ival_r, leaf_ival(n));
|
||||
@@ -2192,9 +2313,10 @@ dns_qp_lookup(dns_qpreadable_t qpr, const dns_name_t *name,
|
||||
return (DNS_R_PARTIALMATCH);
|
||||
} else {
|
||||
/*
|
||||
* oops, during the search we found and added
|
||||
* a leaf that's longer than the requested
|
||||
* name; remove it from the chain.
|
||||
* oops, during the search we found and
|
||||
* added a leaf that's longer than the
|
||||
* requested name; remove it from the
|
||||
* chain.
|
||||
*/
|
||||
chain->len--;
|
||||
}
|
||||
|
||||
@@ -204,6 +204,7 @@ ISC_RUN_TEST_IMPL(qpiter) {
|
||||
int inserted, n;
|
||||
uint32_t ival;
|
||||
void *pval = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
dns_qp_create(mctx, &qpiter_methods, item, &qp);
|
||||
for (size_t tests = 0; tests < 1234; tests++) {
|
||||
@@ -253,15 +254,30 @@ ISC_RUN_TEST_IMPL(qpiter) {
|
||||
while (dns_qpiter_prev(&qpi, NULL, NULL, &ival) ==
|
||||
ISC_R_SUCCESS)
|
||||
{
|
||||
assert_int_equal(ival, order[--n]);
|
||||
--n;
|
||||
|
||||
assert_int_equal(ival, order[n]);
|
||||
|
||||
/* and check current iterator value as well */
|
||||
result = dns_qpiter_current(&qpi, NULL, NULL, &ival);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(ival, order[n]);
|
||||
}
|
||||
|
||||
assert_int_equal(n, 0);
|
||||
|
||||
/* ...and forward again */
|
||||
while (dns_qpiter_next(&qpi, NULL, NULL, &ival) ==
|
||||
ISC_R_SUCCESS)
|
||||
{
|
||||
assert_int_equal(ival, order[n++]);
|
||||
assert_int_equal(ival, order[n]);
|
||||
|
||||
/* and check current iterator value as well */
|
||||
result = dns_qpiter_current(&qpi, NULL, NULL, &ival);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_int_equal(ival, order[n]);
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
assert_int_equal(n, inserted);
|
||||
@@ -575,16 +591,36 @@ check_predecessors(dns_qp_t *qp, struct check_predecessors check[]) {
|
||||
dns_name_t *pred = dns_fixedname_initname(&fn2);
|
||||
|
||||
for (int i = 0; check[i].query != NULL; i++) {
|
||||
dns_qpiter_t it;
|
||||
char *predname = NULL;
|
||||
|
||||
dns_test_namefromstring(check[i].query, &fn1);
|
||||
result = dns_qp_lookup(qp, name, NULL, pred, NULL, NULL, NULL);
|
||||
result = dns_qp_lookup(qp, name, NULL, &it, NULL, NULL, NULL);
|
||||
#if 0
|
||||
fprintf(stderr, "%s: expected %s got %s\n", check[i].query,
|
||||
isc_result_totext(check[i].result),
|
||||
isc_result_totext(result));
|
||||
#endif
|
||||
assert_int_equal(result, check[i].result);
|
||||
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
/*
|
||||
* we found an exact match; iterate to find
|
||||
* the predecessor.
|
||||
*/
|
||||
result = dns_qpiter_prev(&it, pred, NULL, NULL);
|
||||
if (result == ISC_R_NOMORE) {
|
||||
result = dns_qpiter_prev(&it, pred, NULL, NULL);
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = dns_name_tostring(pred, &predname, mctx);
|
||||
#if 0
|
||||
fprintf(stderr, "... expected predecessor %s got %s\n",
|
||||
@@ -602,7 +638,8 @@ ISC_RUN_TEST_IMPL(predecessors) {
|
||||
const char insert[][16] = {
|
||||
"a.", "b.", "c.b.a.", "e.d.c.b.a.",
|
||||
"c.b.b.", "c.d.", "a.b.c.d.", "a.b.c.d.e.",
|
||||
"b.a.", "x.k.c.d.", ""
|
||||
"b.a.", "x.k.c.d.", "moog.", "mooker.",
|
||||
"mooko.", "moon.", "moops.", ""
|
||||
};
|
||||
int i = 0;
|
||||
|
||||
@@ -613,8 +650,8 @@ ISC_RUN_TEST_IMPL(predecessors) {
|
||||
|
||||
/* first check: no root label in the database */
|
||||
static struct check_predecessors check1[] = {
|
||||
{ ".", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ "a.", "a.b.c.d.e.", ISC_R_SUCCESS },
|
||||
{ ".", "moops.", ISC_R_NOTFOUND },
|
||||
{ "a.", "moops.", ISC_R_SUCCESS },
|
||||
{ "b.a.", "a.", ISC_R_SUCCESS },
|
||||
{ "b.", "e.d.c.b.a.", ISC_R_SUCCESS },
|
||||
{ "aaa.a.", "a.", DNS_R_PARTIALMATCH },
|
||||
@@ -622,13 +659,29 @@ ISC_RUN_TEST_IMPL(predecessors) {
|
||||
{ "d.c.", "c.b.b.", ISC_R_NOTFOUND },
|
||||
{ "1.2.c.b.a.", "c.b.a.", DNS_R_PARTIALMATCH },
|
||||
{ "a.b.c.e.f.", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ "z.y.x.", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ "z.y.x.", "moops.", ISC_R_NOTFOUND },
|
||||
{ "w.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH },
|
||||
{ "z.z.z.z.k.c.d.", "a.b.c.d.", DNS_R_PARTIALMATCH },
|
||||
{ "z.z.z.z.k.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH },
|
||||
{ "w.k.c.d.", "a.b.c.d.", DNS_R_PARTIALMATCH },
|
||||
{ "d.a.", "e.d.c.b.a.", DNS_R_PARTIALMATCH },
|
||||
{ "0.b.c.d.e.", "x.k.c.d.", ISC_R_NOTFOUND },
|
||||
{ "b.d.", "c.b.b.", ISC_R_NOTFOUND },
|
||||
{ "moor.", "moops.", ISC_R_NOTFOUND },
|
||||
{ "mopbop.", "moops.", ISC_R_NOTFOUND },
|
||||
{ "moppop.", "moops.", ISC_R_NOTFOUND },
|
||||
{ "mopps.", "moops.", ISC_R_NOTFOUND },
|
||||
{ "mopzop.", "moops.", ISC_R_NOTFOUND },
|
||||
{ "mop.", "moops.", ISC_R_NOTFOUND },
|
||||
{ "monbop.", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ "monpop.", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ "monps.", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ "monzop.", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ "mon.", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ "moop.", "moon.", ISC_R_NOTFOUND },
|
||||
{ "moopser.", "moops.", ISC_R_NOTFOUND },
|
||||
{ "monky.", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ "monkey.", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ "monker.", "a.b.c.d.e.", ISC_R_NOTFOUND },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
@@ -639,7 +692,7 @@ ISC_RUN_TEST_IMPL(predecessors) {
|
||||
insert_str(qp, root);
|
||||
|
||||
static struct check_predecessors check2[] = {
|
||||
{ ".", "a.b.c.d.e.", ISC_R_SUCCESS },
|
||||
{ ".", "moops.", ISC_R_SUCCESS },
|
||||
{ "a.", ".", ISC_R_SUCCESS },
|
||||
{ "b.a.", "a.", ISC_R_SUCCESS },
|
||||
{ "b.", "e.d.c.b.a.", ISC_R_SUCCESS },
|
||||
@@ -648,12 +701,28 @@ ISC_RUN_TEST_IMPL(predecessors) {
|
||||
{ "d.c.", "c.b.b.", DNS_R_PARTIALMATCH },
|
||||
{ "1.2.c.b.a.", "c.b.a.", DNS_R_PARTIALMATCH },
|
||||
{ "a.b.c.e.f.", "a.b.c.d.e.", DNS_R_PARTIALMATCH },
|
||||
{ "z.y.x.", "a.b.c.d.e.", DNS_R_PARTIALMATCH },
|
||||
{ "z.y.x.", "moops.", DNS_R_PARTIALMATCH },
|
||||
{ "w.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH },
|
||||
{ "z.z.z.z.k.c.d.", "a.b.c.d.", DNS_R_PARTIALMATCH },
|
||||
{ "z.z.z.z.k.c.d.", "x.k.c.d.", DNS_R_PARTIALMATCH },
|
||||
{ "w.k.c.d.", "a.b.c.d.", DNS_R_PARTIALMATCH },
|
||||
{ "d.a.", "e.d.c.b.a.", DNS_R_PARTIALMATCH },
|
||||
{ "0.b.c.d.e.", "x.k.c.d.", DNS_R_PARTIALMATCH },
|
||||
{ "moor.", "moops.", DNS_R_PARTIALMATCH },
|
||||
{ "mopbop.", "moops.", DNS_R_PARTIALMATCH },
|
||||
{ "moppop.", "moops.", DNS_R_PARTIALMATCH },
|
||||
{ "mopps.", "moops.", DNS_R_PARTIALMATCH },
|
||||
{ "mopzop.", "moops.", DNS_R_PARTIALMATCH },
|
||||
{ "mop.", "moops.", DNS_R_PARTIALMATCH },
|
||||
{ "monbop.", "a.b.c.d.e.", DNS_R_PARTIALMATCH },
|
||||
{ "monpop.", "a.b.c.d.e.", DNS_R_PARTIALMATCH },
|
||||
{ "monps.", "a.b.c.d.e.", DNS_R_PARTIALMATCH },
|
||||
{ "monzop.", "a.b.c.d.e.", DNS_R_PARTIALMATCH },
|
||||
{ "mon.", "a.b.c.d.e.", DNS_R_PARTIALMATCH },
|
||||
{ "moop.", "moon.", DNS_R_PARTIALMATCH },
|
||||
{ "moopser.", "moops.", DNS_R_PARTIALMATCH },
|
||||
{ "monky.", "a.b.c.d.e.", DNS_R_PARTIALMATCH },
|
||||
{ "monkey.", "a.b.c.d.e.", DNS_R_PARTIALMATCH },
|
||||
{ "monker.", "a.b.c.d.e.", DNS_R_PARTIALMATCH },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user