rbt_test.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012-2014  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /* $Id: rbt_test.c,v 1.1.14.8 2012/02/10 16:24:37 ckb Exp $ */
00018 
00019 /* ! \file */
00020 
00021 #include <config.h>
00022 #include <atf-c.h>
00023 #include <isc/mem.h>
00024 #include <isc/random.h>
00025 #include <isc/string.h>
00026 #include <fcntl.h>
00027 #include <unistd.h>
00028 
00029 #ifdef HAVE_INTTYPES_H
00030 #include <inttypes.h> /* uintptr_t */
00031 #endif
00032 
00033 #include <dns/rbt.h>
00034 #include <dns/fixedname.h>
00035 #include <dns/result.h>
00036 #include <dns/compress.h>
00037 #include "dnstest.h"
00038 
00039 #include <isc/app.h>
00040 #include <isc/buffer.h>
00041 #include <isc/entropy.h>
00042 #include <isc/file.h>
00043 #include <isc/hash.h>
00044 #include <isc/mem.h>
00045 #include <isc/os.h>
00046 #include <isc/string.h>
00047 #include <isc/socket.h>
00048 #include <isc/stdio.h>
00049 #include <isc/task.h>
00050 #include <isc/timer.h>
00051 #include <isc/util.h>
00052 #include <isc/print.h>
00053 
00054 #include <dns/log.h>
00055 #include <dns/name.h>
00056 #include <dns/result.h>
00057 
00058 #include <dst/dst.h>
00059 
00060 #include <ctype.h>
00061 
00062 typedef struct {
00063         dns_rbt_t *rbt;
00064         dns_rbt_t *rbt_distances;
00065 } test_context_t;
00066 
00067 /* The initial structure of domain tree will be as follows:
00068  *
00069  *             .
00070  *             |
00071  *             b
00072  *           /   \
00073  *          a    d.e.f
00074  *              /  |   \
00075  *             c   |    g.h
00076  *                 |     |
00077  *                w.y    i
00078  *              /  |  \   \
00079  *             x   |   z   k
00080  *                 |   |
00081  *                 p   j
00082  *               /   \
00083  *              o     q
00084  */
00085 
00086 /* The full absolute names of the nodes in the tree (the tree also
00087  * contains "." which is not included in this list).
00088  */
00089 static const char * const domain_names[] = {
00090     "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
00091     "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"
00092 };
00093 
00094 static const size_t domain_names_count = (sizeof(domain_names) /
00095                                           sizeof(domain_names[0]));
00096 
00097 /* These are set as the node data for the tree used in distances check
00098  * (for the names in domain_names[] above).
00099  */
00100 static const int node_distances[] = {
00101     3, 1, 2, 2, 2, 3, 1, 2, 1, 1, 2, 2
00102 };
00103 
00104 /*
00105  * The domain order should be:
00106  * ., a, b, c, d.e.f, x.d.e.f, w.y.d.e.f, o.w.y.d.e.f, p.w.y.d.e.f,
00107  * q.w.y.d.e.f, z.d.e.f, j.z.d.e.f, g.h, i.g.h, k.g.h
00108  *             . (no data, can't be found)
00109  *             |
00110  *             b
00111  *           /   \
00112  *          a    d.e.f
00113  *              /  |   \
00114  *             c   |    g.h
00115  *                 |     |
00116  *                w.y    i
00117  *              /  |  \   \
00118  *             x   |   z   k
00119  *                 |   |
00120  *                 p   j
00121  *               /   \
00122  *              o     q
00123  */
00124 
00125 static const char * const ordered_names[] = {
00126     "a", "b", "c", "d.e.f", "x.d.e.f", "w.y.d.e.f", "o.w.y.d.e.f",
00127     "p.w.y.d.e.f", "q.w.y.d.e.f", "z.d.e.f", "j.z.d.e.f",
00128     "g.h", "i.g.h", "k.g.h"};
00129 
00130 static const size_t ordered_names_count = (sizeof(ordered_names) /
00131                                            sizeof(*ordered_names));
00132 
00133 static void
00134 delete_data(void *data, void *arg) {
00135         UNUSED(arg);
00136 
00137         isc_mem_put(mctx, data, sizeof(size_t));
00138 }
00139 
00140 static void
00141 build_name_from_str(const char *namestr, dns_fixedname_t *fname) {
00142         size_t length;
00143         isc_buffer_t *b = NULL;
00144         isc_result_t result;
00145         dns_name_t *name;
00146 
00147         length = strlen(namestr);
00148 
00149         result = isc_buffer_allocate(mctx, &b, length);
00150         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00151         isc_buffer_putmem(b, (const unsigned char *) namestr, length);
00152 
00153         dns_fixedname_init(fname);
00154         name = dns_fixedname_name(fname);
00155         ATF_REQUIRE(name != NULL);
00156         result = dns_name_fromtext(name, b, dns_rootname, 0, NULL);
00157         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00158 
00159         isc_buffer_free(&b);
00160 }
00161 
00162 static test_context_t *
00163 test_context_setup(void) {
00164         test_context_t *ctx;
00165         isc_result_t result;
00166         size_t i;
00167 
00168         ctx = isc_mem_get(mctx, sizeof(*ctx));
00169         ATF_REQUIRE(ctx != NULL);
00170 
00171         ctx->rbt = NULL;
00172         result = dns_rbt_create(mctx, delete_data, NULL, &ctx->rbt);
00173         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00174 
00175         ctx->rbt_distances = NULL;
00176         result = dns_rbt_create(mctx, delete_data, NULL, &ctx->rbt_distances);
00177         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00178 
00179         for (i = 0; i < domain_names_count; i++) {
00180                 size_t *n;
00181                 dns_fixedname_t fname;
00182                 dns_name_t *name;
00183 
00184                 build_name_from_str(domain_names[i], &fname);
00185 
00186                 name = dns_fixedname_name(&fname);
00187 
00188                 n = isc_mem_get(mctx, sizeof(size_t));
00189                 *n = i + 1;
00190                 result = dns_rbt_addname(ctx->rbt, name, n);
00191                 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00192 
00193                 n = isc_mem_get(mctx, sizeof(size_t));
00194                 *n = node_distances[i];
00195                 result = dns_rbt_addname(ctx->rbt_distances, name, n);
00196                 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00197         }
00198 
00199         return (ctx);
00200 }
00201 
00202 static void
00203 test_context_teardown(test_context_t *ctx) {
00204         dns_rbt_destroy(&ctx->rbt);
00205         dns_rbt_destroy(&ctx->rbt_distances);
00206 
00207         isc_mem_put(mctx, ctx, sizeof(*ctx));
00208 }
00209 
00210 /*
00211  * Walk the tree and ensure that all the test nodes are present.
00212  */
00213 static void
00214 check_test_data(dns_rbt_t *rbt) {
00215         dns_fixedname_t fixed;
00216         isc_result_t result;
00217         dns_name_t *foundname;
00218         size_t i;
00219 
00220         dns_fixedname_init(&fixed);
00221         foundname = dns_fixedname_name(&fixed);
00222 
00223         for (i = 0; i < domain_names_count; i++) {
00224                 dns_fixedname_t fname;
00225                 dns_name_t *name;
00226                 size_t *n;
00227 
00228                 build_name_from_str(domain_names[i], &fname);
00229 
00230                 name = dns_fixedname_name(&fname);
00231                 n = NULL;
00232                 result = dns_rbt_findname(rbt, name, 0, foundname,
00233                                           (void *) &n);
00234                 ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00235                 ATF_CHECK_EQ(*n, i + 1);
00236         }
00237 }
00238 
00239 ATF_TC(rbt_create);
00240 ATF_TC_HEAD(rbt_create, tc) {
00241         atf_tc_set_md_var(tc, "descr", "Test the creation of an rbt");
00242 }
00243 ATF_TC_BODY(rbt_create, tc) {
00244         isc_result_t result;
00245         test_context_t *ctx;
00246         isc_boolean_t tree_ok;
00247 
00248         UNUSED(tc);
00249 
00250         isc_mem_debugging = ISC_MEM_DEBUGRECORD;
00251 
00252         result = dns_test_begin(NULL, ISC_TRUE);
00253         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00254 
00255         ctx = test_context_setup();
00256 
00257         check_test_data(ctx->rbt);
00258 
00259         tree_ok = dns__rbt_checkproperties(ctx->rbt);
00260         ATF_CHECK_EQ(tree_ok, ISC_TRUE);
00261 
00262         test_context_teardown(ctx);
00263 
00264         dns_test_end();
00265 }
00266 
00267 ATF_TC(rbt_nodecount);
00268 ATF_TC_HEAD(rbt_nodecount, tc) {
00269         atf_tc_set_md_var(tc, "descr", "Test dns_rbt_nodecount() on a tree");
00270 }
00271 ATF_TC_BODY(rbt_nodecount, tc) {
00272         isc_result_t result;
00273         test_context_t *ctx;
00274 
00275         UNUSED(tc);
00276 
00277         isc_mem_debugging = ISC_MEM_DEBUGRECORD;
00278 
00279         result = dns_test_begin(NULL, ISC_TRUE);
00280         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00281 
00282         ctx = test_context_setup();
00283 
00284         ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
00285 
00286         test_context_teardown(ctx);
00287 
00288         dns_test_end();
00289 }
00290 
00291 ATF_TC(rbtnode_get_distance);
00292 ATF_TC_HEAD(rbtnode_get_distance, tc) {
00293         atf_tc_set_md_var(tc, "descr",
00294                           "Test dns_rbtnode_get_distance() on a tree");
00295 }
00296 ATF_TC_BODY(rbtnode_get_distance, tc) {
00297         isc_result_t result;
00298         test_context_t *ctx;
00299         const char *name_str = "a";
00300         dns_fixedname_t fname;
00301         dns_name_t *name;
00302         dns_rbtnode_t *node = NULL;
00303         dns_rbtnodechain_t chain;
00304 
00305         UNUSED(tc);
00306 
00307         isc_mem_debugging = ISC_MEM_DEBUGRECORD;
00308 
00309         result = dns_test_begin(NULL, ISC_TRUE);
00310         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00311 
00312         ctx = test_context_setup();
00313 
00314         build_name_from_str(name_str, &fname);
00315         name = dns_fixedname_name(&fname);
00316 
00317         dns_rbtnodechain_init(&chain, mctx);
00318 
00319         result = dns_rbt_findnode(ctx->rbt_distances, name, NULL,
00320                                   &node, &chain, 0, NULL, NULL);
00321         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00322 
00323         while (node != NULL) {
00324                 const size_t *distance = (const size_t *) node->data;
00325                 if (distance != NULL)
00326                         ATF_CHECK_EQ(*distance,
00327                                      dns__rbtnode_getdistance(node));
00328                 result = dns_rbtnodechain_next(&chain, NULL, NULL);
00329                 if (result == ISC_R_NOMORE)
00330                       break;
00331                 dns_rbtnodechain_current(&chain, NULL, NULL, &node);
00332         }
00333 
00334         ATF_CHECK_EQ(result, ISC_R_NOMORE);
00335 
00336         dns_rbtnodechain_invalidate(&chain);
00337 
00338         test_context_teardown(ctx);
00339 
00340         dns_test_end();
00341 }
00342 
00343 ATF_TC(rbt_check_distance_random);
00344 ATF_TC_HEAD(rbt_check_distance_random, tc) {
00345         atf_tc_set_md_var(tc, "descr",
00346                           "Test tree balance, inserting names in random order");
00347 }
00348 ATF_TC_BODY(rbt_check_distance_random, tc) {
00349         /* This test checks an important performance-related property of
00350          * the red-black tree, which is important for us: the longest
00351          * path from a sub-tree's root to a node is no more than
00352          * 2log(n). This check verifies that the tree is balanced.
00353          */
00354         dns_rbt_t *mytree = NULL;
00355         const unsigned int log_num_nodes = 16;
00356 
00357         int i;
00358         isc_result_t result;
00359         isc_boolean_t tree_ok;
00360 
00361         UNUSED(tc);
00362 
00363         isc_mem_debugging = ISC_MEM_DEBUGRECORD;
00364 
00365         result = dns_test_begin(NULL, ISC_TRUE);
00366         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00367 
00368         result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
00369         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00370 
00371         /* Names are inserted in random order. */
00372 
00373         /* Make a large 65536 node top-level domain tree, i.e., the
00374          * following code inserts names such as:
00375          *
00376          * savoucnsrkrqzpkqypbygwoiliawpbmz.
00377          * wkadamcbbpjtundbxcmuayuycposvngx.
00378          * wzbpznemtooxdpjecdxynsfztvnuyfao.
00379          * yueojmhyffslpvfmgyfwioxegfhepnqq.
00380          */
00381         for (i = 0; i < (1 << log_num_nodes); i++) {
00382                 size_t *n;
00383                 char namebuf[34];
00384 
00385                 n = isc_mem_get(mctx, sizeof(size_t));
00386                 *n = i + 1;
00387 
00388                 while (1) {
00389                         int j;
00390                         dns_fixedname_t fname;
00391                         dns_name_t *name;
00392 
00393                         for (j = 0; j < 32; j++) {
00394                                 isc_uint32_t v;
00395                                 isc_random_get(&v);
00396                                 namebuf[j] = 'a' + (v % 26);
00397                         }
00398                         namebuf[32] = '.';
00399                         namebuf[33] = 0;
00400 
00401                         build_name_from_str(namebuf, &fname);
00402                         name = dns_fixedname_name(&fname);
00403 
00404                         result = dns_rbt_addname(mytree, name, n);
00405                         if (result == ISC_R_SUCCESS)
00406                                 break;
00407                 }
00408         }
00409 
00410         /* 1 (root . node) + (1 << log_num_nodes) */
00411         ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree));
00412 
00413         /* The distance from each node to its sub-tree root must be less
00414          * than 2 * log(n).
00415          */
00416         ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree));
00417 
00418         /* Also check RB tree properties */
00419         tree_ok = dns__rbt_checkproperties(mytree);
00420         ATF_CHECK_EQ(tree_ok, ISC_TRUE);
00421 
00422         dns_rbt_destroy(&mytree);
00423 
00424         dns_test_end();
00425 }
00426 
00427 ATF_TC(rbt_check_distance_ordered);
00428 ATF_TC_HEAD(rbt_check_distance_ordered, tc) {
00429         atf_tc_set_md_var(tc, "descr",
00430                           "Test tree balance, inserting names in sorted order");
00431 }
00432 ATF_TC_BODY(rbt_check_distance_ordered, tc) {
00433         /* This test checks an important performance-related property of
00434          * the red-black tree, which is important for us: the longest
00435          * path from a sub-tree's root to a node is no more than
00436          * 2log(n). This check verifies that the tree is balanced.
00437          */
00438         dns_rbt_t *mytree = NULL;
00439         const unsigned int log_num_nodes = 16;
00440 
00441         int i;
00442         isc_result_t result;
00443         isc_boolean_t tree_ok;
00444 
00445         UNUSED(tc);
00446 
00447         isc_mem_debugging = ISC_MEM_DEBUGRECORD;
00448 
00449         result = dns_test_begin(NULL, ISC_TRUE);
00450         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00451 
00452         result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
00453         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00454 
00455         /* Names are inserted in sorted order. */
00456 
00457         /* Make a large 65536 node top-level domain tree, i.e., the
00458          * following code inserts names such as:
00459          *
00460          *   name00000000.
00461          *   name00000001.
00462          *   name00000002.
00463          *   name00000003.
00464          */
00465         for (i = 0; i < (1 << log_num_nodes); i++) {
00466                 size_t *n;
00467                 char namebuf[14];
00468                 dns_fixedname_t fname;
00469                 dns_name_t *name;
00470 
00471                 n = isc_mem_get(mctx, sizeof(size_t));
00472                 *n = i + 1;
00473 
00474                 snprintf(namebuf, sizeof(namebuf), "name%08x.", i);
00475                 build_name_from_str(namebuf, &fname);
00476                 name = dns_fixedname_name(&fname);
00477 
00478                 result = dns_rbt_addname(mytree, name, n);
00479                 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00480         }
00481 
00482         /* 1 (root . node) + (1 << log_num_nodes) */
00483         ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree));
00484 
00485         /* The distance from each node to its sub-tree root must be less
00486          * than 2 * log(n).
00487          */
00488         ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree));
00489 
00490         /* Also check RB tree properties */
00491         tree_ok = dns__rbt_checkproperties(mytree);
00492         ATF_CHECK_EQ(tree_ok, ISC_TRUE);
00493 
00494         dns_rbt_destroy(&mytree);
00495 
00496         dns_test_end();
00497 }
00498 
00499 static isc_result_t
00500 insert_helper(dns_rbt_t *rbt, const char *namestr, dns_rbtnode_t **node) {
00501         dns_fixedname_t fname;
00502         dns_name_t *name;
00503 
00504         build_name_from_str(namestr, &fname);
00505         name = dns_fixedname_name(&fname);
00506 
00507         return (dns_rbt_addnode(rbt, name, node));
00508 }
00509 
00510 static isc_boolean_t
00511 compare_labelsequences(dns_rbtnode_t *node, const char *labelstr) {
00512         dns_name_t name;
00513         isc_result_t result;
00514         char *nodestr = NULL;
00515         isc_boolean_t is_equal;
00516 
00517         dns_name_init(&name, NULL);
00518         dns_rbt_namefromnode(node, &name);
00519 
00520         result = dns_name_tostring(&name, &nodestr, mctx);
00521         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00522 
00523         is_equal = strcmp(labelstr, nodestr) == 0 ? ISC_TRUE : ISC_FALSE;
00524 
00525         isc_mem_free(mctx, nodestr);
00526 
00527         return (is_equal);
00528 }
00529 
00530 ATF_TC(rbt_insert);
00531 ATF_TC_HEAD(rbt_insert, tc) {
00532         atf_tc_set_md_var(tc, "descr", "Test insertion into a tree");
00533 }
00534 ATF_TC_BODY(rbt_insert, tc) {
00535         isc_result_t result;
00536         test_context_t *ctx;
00537         dns_rbtnode_t *node;
00538 
00539         UNUSED(tc);
00540 
00541         isc_mem_debugging = ISC_MEM_DEBUGRECORD;
00542 
00543         result = dns_test_begin(NULL, ISC_TRUE);
00544         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00545 
00546         ctx = test_context_setup();
00547 
00548         /* Check node count before beginning. */
00549         ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
00550 
00551         /* Try to insert a node that already exists. */
00552         node = NULL;
00553         result = insert_helper(ctx->rbt, "d.e.f", &node);
00554         ATF_CHECK_EQ(result, ISC_R_EXISTS);
00555 
00556         /* Node count must not have changed. */
00557         ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
00558 
00559         /* Try to insert a node that doesn't exist. */
00560         node = NULL;
00561         result = insert_helper(ctx->rbt, "0", &node);
00562         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00563         ATF_CHECK_EQ(compare_labelsequences(node, "0"), ISC_TRUE);
00564 
00565         /* Node count must have increased. */
00566         ATF_CHECK_EQ(16, dns_rbt_nodecount(ctx->rbt));
00567 
00568         /* Another. */
00569         node = NULL;
00570         result = insert_helper(ctx->rbt, "example.com", &node);
00571         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00572         ATF_REQUIRE(node != NULL);
00573         ATF_CHECK_EQ(node->data, NULL);
00574 
00575         /* Node count must have increased. */
00576         ATF_CHECK_EQ(17, dns_rbt_nodecount(ctx->rbt));
00577 
00578         /* Re-adding it should return EXISTS */
00579         node = NULL;
00580         result = insert_helper(ctx->rbt, "example.com", &node);
00581         ATF_CHECK_EQ(result, ISC_R_EXISTS);
00582 
00583         /* Node count must not have changed. */
00584         ATF_CHECK_EQ(17, dns_rbt_nodecount(ctx->rbt));
00585 
00586         /* Fission the node d.e.f */
00587         node = NULL;
00588         result = insert_helper(ctx->rbt, "k.e.f", &node);
00589         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00590         ATF_CHECK_EQ(compare_labelsequences(node, "k"), ISC_TRUE);
00591 
00592         /* Node count must have incremented twice ("d.e.f" fissioned to
00593          * "d" and "e.f", and the newly added "k").
00594          */
00595         ATF_CHECK_EQ(19, dns_rbt_nodecount(ctx->rbt));
00596 
00597         /* Fission the node "g.h" */
00598         node = NULL;
00599         result = insert_helper(ctx->rbt, "h", &node);
00600         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00601         ATF_CHECK_EQ(compare_labelsequences(node, "h"), ISC_TRUE);
00602 
00603         /* Node count must have incremented ("g.h" fissioned to "g" and
00604          * "h").
00605          */
00606         ATF_CHECK_EQ(20, dns_rbt_nodecount(ctx->rbt));
00607 
00608         /* Add child domains */
00609 
00610         node = NULL;
00611         result = insert_helper(ctx->rbt, "m.p.w.y.d.e.f", &node);
00612         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00613         ATF_CHECK_EQ(compare_labelsequences(node, "m"), ISC_TRUE);
00614         ATF_CHECK_EQ(21, dns_rbt_nodecount(ctx->rbt));
00615 
00616         node = NULL;
00617         result = insert_helper(ctx->rbt, "n.p.w.y.d.e.f", &node);
00618         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00619         ATF_CHECK_EQ(compare_labelsequences(node, "n"), ISC_TRUE);
00620         ATF_CHECK_EQ(22, dns_rbt_nodecount(ctx->rbt));
00621 
00622         node = NULL;
00623         result = insert_helper(ctx->rbt, "l.a", &node);
00624         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00625         ATF_CHECK_EQ(compare_labelsequences(node, "l"), ISC_TRUE);
00626         ATF_CHECK_EQ(23, dns_rbt_nodecount(ctx->rbt));
00627 
00628         node = NULL;
00629         result = insert_helper(ctx->rbt, "r.d.e.f", &node);
00630         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00631         node = NULL;
00632         result = insert_helper(ctx->rbt, "s.d.e.f", &node);
00633         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00634         ATF_CHECK_EQ(25, dns_rbt_nodecount(ctx->rbt));
00635 
00636         node = NULL;
00637         result = insert_helper(ctx->rbt, "h.w.y.d.e.f", &node);
00638         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00639 
00640         /* Add more nodes one by one to cover left and right rotation
00641          * functions.
00642          */
00643         node = NULL;
00644         result = insert_helper(ctx->rbt, "f", &node);
00645         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00646 
00647         node = NULL;
00648         result = insert_helper(ctx->rbt, "m", &node);
00649         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00650 
00651         node = NULL;
00652         result = insert_helper(ctx->rbt, "nm", &node);
00653         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00654 
00655         node = NULL;
00656         result = insert_helper(ctx->rbt, "om", &node);
00657         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00658 
00659         node = NULL;
00660         result = insert_helper(ctx->rbt, "k", &node);
00661         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00662 
00663         node = NULL;
00664         result = insert_helper(ctx->rbt, "l", &node);
00665         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00666 
00667         node = NULL;
00668         result = insert_helper(ctx->rbt, "fe", &node);
00669         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00670 
00671         node = NULL;
00672         result = insert_helper(ctx->rbt, "ge", &node);
00673         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00674 
00675         node = NULL;
00676         result = insert_helper(ctx->rbt, "i", &node);
00677         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00678 
00679         node = NULL;
00680         result = insert_helper(ctx->rbt, "ae", &node);
00681         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00682 
00683         node = NULL;
00684         result = insert_helper(ctx->rbt, "n", &node);
00685         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00686 
00687         test_context_teardown(ctx);
00688 
00689         dns_test_end();
00690 }
00691 
00692 ATF_TC(rbt_remove);
00693 ATF_TC_HEAD(rbt_remove, tc) {
00694         atf_tc_set_md_var(tc, "descr", "Test removal from a tree");
00695 }
00696 ATF_TC_BODY(rbt_remove, tc) {
00697         /*
00698          * This testcase checks that after node removal, the
00699          * binary-search tree is valid and all nodes that are supposed
00700          * to exist are present in the correct order. It mainly tests
00701          * DomainTree as a BST, and not particularly as a red-black
00702          * tree. This test checks node deletion when upper nodes have
00703          * data.
00704          */
00705         isc_result_t result;
00706         size_t j;
00707 
00708         UNUSED(tc);
00709 
00710         isc_mem_debugging = ISC_MEM_DEBUGRECORD;
00711 
00712         result = dns_test_begin(NULL, ISC_TRUE);
00713         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00714 
00715         /*
00716          * Delete single nodes and check if the rest of the nodes exist.
00717          */
00718         for (j = 0; j < ordered_names_count; j++) {
00719                 dns_rbt_t *mytree = NULL;
00720                 dns_rbtnode_t *node;
00721                 size_t i;
00722                 size_t *n;
00723                 isc_boolean_t tree_ok;
00724                 dns_rbtnodechain_t chain;
00725                 size_t start_node;
00726 
00727                 /* Create a tree. */
00728                 result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
00729                 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00730 
00731                 /* Insert test data into the tree. */
00732                 for (i = 0; i < domain_names_count; i++) {
00733                         node = NULL;
00734                         result = insert_helper(mytree, domain_names[i], &node);
00735                         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00736                 }
00737 
00738                 /* Check that all names exist in order. */
00739                 for (i = 0; i < ordered_names_count; i++) {
00740                         dns_fixedname_t fname;
00741                         dns_name_t *name;
00742 
00743                         build_name_from_str(ordered_names[i], &fname);
00744 
00745                         name = dns_fixedname_name(&fname);
00746                         node = NULL;
00747                         result = dns_rbt_findnode(mytree, name, NULL,
00748                                                   &node, NULL,
00749                                                   DNS_RBTFIND_EMPTYDATA,
00750                                                   NULL, NULL);
00751                         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00752 
00753                         /* Add node data */
00754                         ATF_REQUIRE(node != NULL);
00755                         ATF_REQUIRE_EQ(node->data, NULL);
00756 
00757                         n = isc_mem_get(mctx, sizeof(size_t));
00758                         *n = i;
00759 
00760                         node->data = n;
00761                 }
00762 
00763                 /* Now, delete the j'th node from the tree. */
00764                 {
00765                         dns_fixedname_t fname;
00766                         dns_name_t *name;
00767 
00768                         build_name_from_str(ordered_names[j], &fname);
00769 
00770                         name = dns_fixedname_name(&fname);
00771 
00772                         result = dns_rbt_deletename(mytree, name, ISC_FALSE);
00773                         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00774                 }
00775 
00776                 /* Check RB tree properties. */
00777                 tree_ok = dns__rbt_checkproperties(mytree);
00778                 ATF_CHECK_EQ(tree_ok, ISC_TRUE);
00779 
00780                 dns_rbtnodechain_init(&chain, mctx);
00781 
00782                 /* Now, walk through nodes in order. */
00783                 if (j == 0) {
00784                         /*
00785                          * Node for ordered_names[0] was already deleted
00786                          * above. We start from node 1.
00787                          */
00788                         dns_fixedname_t fname;
00789                         dns_name_t *name;
00790 
00791                         build_name_from_str(ordered_names[0], &fname);
00792                         name = dns_fixedname_name(&fname);
00793                         node = NULL;
00794                         result = dns_rbt_findnode(mytree, name, NULL,
00795                                                   &node, NULL,
00796                                                   0,
00797                                                   NULL, NULL);
00798                         ATF_CHECK_EQ(result, ISC_R_NOTFOUND);
00799 
00800                         build_name_from_str(ordered_names[1], &fname);
00801                         name = dns_fixedname_name(&fname);
00802                         node = NULL;
00803                         result = dns_rbt_findnode(mytree, name, NULL,
00804                                                   &node, &chain,
00805                                                   0,
00806                                                   NULL, NULL);
00807                         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00808                         start_node = 1;
00809                 } else {
00810                         /* Start from node 0. */
00811                         dns_fixedname_t fname;
00812                         dns_name_t *name;
00813 
00814                         build_name_from_str(ordered_names[0], &fname);
00815                         name = dns_fixedname_name(&fname);
00816                         node = NULL;
00817                         result = dns_rbt_findnode(mytree, name, NULL,
00818                                                   &node, &chain,
00819                                                   0,
00820                                                   NULL, NULL);
00821                         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00822                         start_node = 0;
00823                 }
00824 
00825                 /*
00826                  * node and chain have been set by the code above at
00827                  * this point.
00828                  */
00829                 for (i = start_node; i < ordered_names_count; i++) {
00830                         dns_fixedname_t fname_j, fname_i;
00831                         dns_name_t *name_j, *name_i;
00832 
00833                         build_name_from_str(ordered_names[j], &fname_j);
00834                         name_j = dns_fixedname_name(&fname_j);
00835                         build_name_from_str(ordered_names[i], &fname_i);
00836                         name_i = dns_fixedname_name(&fname_i);
00837 
00838                         if (dns_name_equal(name_i, name_j)) {
00839                                 /*
00840                                  * This may be true for the last node if
00841                                  * we seek ahead in the loop using
00842                                  * dns_rbtnodechain_next() below.
00843                                  */
00844                                 if (node == NULL) {
00845                                         break;
00846                                 }
00847 
00848                                 /* All ordered nodes have data
00849                                  * initially. If any node is empty, it
00850                                  * means it was removed, but an empty
00851                                  * node exists because it is a
00852                                  * super-domain. Just skip it.
00853                                  */
00854                                 if (node->data == NULL) {
00855                                         result = dns_rbtnodechain_next(&chain,
00856                                                                        NULL,
00857                                                                        NULL);
00858                                         if (result == ISC_R_NOMORE) {
00859                                                 node = NULL;
00860                                         } else {
00861                                                 dns_rbtnodechain_current(&chain,
00862                                                                          NULL,
00863                                                                          NULL,
00864                                                                          &node);
00865                                         }
00866                                 }
00867                                 continue;
00868                         }
00869 
00870                         ATF_REQUIRE(node != NULL);
00871 
00872                         n = (size_t *) node->data;
00873                         if (n != NULL) {
00874                                 /* printf("n=%zu, i=%zu\n", *n, i); */
00875                                 ATF_CHECK_EQ(*n, i);
00876                         }
00877 
00878                         result = dns_rbtnodechain_next(&chain, NULL, NULL);
00879                         if (result == ISC_R_NOMORE) {
00880                                 node = NULL;
00881                         } else {
00882                                 dns_rbtnodechain_current(&chain, NULL, NULL,
00883                                                          &node);
00884                         }
00885                 }
00886 
00887                 /* We should have reached the end of the tree. */
00888                 ATF_REQUIRE_EQ(node, NULL);
00889 
00890                 dns_rbt_destroy(&mytree);
00891         }
00892 
00893         dns_test_end();
00894 }
00895 
00896 ATF_TC(rbt_remove_empty);
00897 ATF_TC_HEAD(rbt_remove_empty, tc) {
00898         atf_tc_set_md_var(tc, "descr",
00899                           "Test removal from a tree when "
00900                           "upper nodes are empty");
00901 }
00902 ATF_TC_BODY(rbt_remove_empty, tc) {
00903         /*
00904          * This test is similar to the rbt_remove test, but checks node
00905          * deletion when upper nodes are empty.
00906          */
00907         isc_result_t result;
00908         size_t j;
00909 
00910         UNUSED(tc);
00911 
00912         isc_mem_debugging = ISC_MEM_DEBUGRECORD;
00913 
00914         result = dns_test_begin(NULL, ISC_TRUE);
00915         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00916 
00917         /*
00918          * Delete single nodes and check if the rest of the nodes exist.
00919          */
00920         for (j = 0; j < ordered_names_count; j++) {
00921                 dns_rbt_t *mytree = NULL;
00922                 dns_rbtnode_t *node;
00923                 size_t i;
00924                 isc_boolean_t tree_ok;
00925                 dns_rbtnodechain_t chain;
00926                 size_t start_node;
00927 
00928                 /* Create a tree. */
00929                 result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
00930                 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00931 
00932                 /* Insert test data into the tree. */
00933                 for (i = 0; i < domain_names_count; i++) {
00934                         node = NULL;
00935                         result = insert_helper(mytree, domain_names[i], &node);
00936                         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00937                 }
00938 
00939                 /* Check that all names exist in order. */
00940                 for (i = 0; i < ordered_names_count; i++) {
00941                         dns_fixedname_t fname;
00942                         dns_name_t *name;
00943 
00944                         build_name_from_str(ordered_names[i], &fname);
00945 
00946                         name = dns_fixedname_name(&fname);
00947                         node = NULL;
00948                         result = dns_rbt_findnode(mytree, name, NULL,
00949                                                   &node, NULL,
00950                                                   DNS_RBTFIND_EMPTYDATA,
00951                                                   NULL, NULL);
00952                         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00953 
00954                         /* Check that node data is empty */
00955                         ATF_REQUIRE(node != NULL);
00956                         ATF_REQUIRE_EQ(node->data, NULL);
00957                 }
00958 
00959                 /* Now, delete the j'th node from the tree. */
00960                 {
00961                         dns_fixedname_t fname;
00962                         dns_name_t *name;
00963 
00964                         build_name_from_str(ordered_names[j], &fname);
00965 
00966                         name = dns_fixedname_name(&fname);
00967 
00968                         node = NULL;
00969                         result = dns_rbt_findnode(mytree, name, NULL, &node,
00970                                                   NULL, DNS_RBTFIND_EMPTYDATA,
00971                                                   NULL, NULL);
00972                         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00973 
00974                         result = dns_rbt_deletenode(mytree, node, ISC_FALSE);
00975                         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
00976                 }
00977 
00978                 /* Check RB tree properties. */
00979                 tree_ok = dns__rbt_checkproperties(mytree);
00980                 ATF_CHECK_EQ(tree_ok, ISC_TRUE);
00981 
00982                 dns_rbtnodechain_init(&chain, mctx);
00983 
00984                 /* Now, walk through nodes in order. */
00985                 if (j == 0) {
00986                         /*
00987                          * Node for ordered_names[0] was already deleted
00988                          * above. We start from node 1.
00989                          */
00990                         dns_fixedname_t fname;
00991                         dns_name_t *name;
00992 
00993                         build_name_from_str(ordered_names[0], &fname);
00994                         name = dns_fixedname_name(&fname);
00995                         node = NULL;
00996                         result = dns_rbt_findnode(mytree, name, NULL,
00997                                                   &node, NULL,
00998                                                   DNS_RBTFIND_EMPTYDATA,
00999                                                   NULL, NULL);
01000                         ATF_CHECK(result != ISC_R_SUCCESS);
01001 
01002                         build_name_from_str(ordered_names[1], &fname);
01003                         name = dns_fixedname_name(&fname);
01004                         node = NULL;
01005                         result = dns_rbt_findnode(mytree, name, NULL,
01006                                                   &node, &chain,
01007                                                   DNS_RBTFIND_EMPTYDATA,
01008                                                   NULL, NULL);
01009                         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
01010                         start_node = 1;
01011                 } else {
01012                         /* Start from node 0. */
01013                         dns_fixedname_t fname;
01014                         dns_name_t *name;
01015 
01016                         build_name_from_str(ordered_names[0], &fname);
01017                         name = dns_fixedname_name(&fname);
01018                         node = NULL;
01019                         result = dns_rbt_findnode(mytree, name, NULL,
01020                                                   &node, &chain,
01021                                                   DNS_RBTFIND_EMPTYDATA,
01022                                                   NULL, NULL);
01023                         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
01024                         start_node = 0;
01025                 }
01026 
01027                 /*
01028                  * node and chain have been set by the code above at
01029                  * this point.
01030                  */
01031                 for (i = start_node; i < ordered_names_count; i++) {
01032                         dns_fixedname_t fntmp1, fntmp2;
01033                         dns_name_t *ntmp1, *ntmp2;
01034                         dns_fixedname_t fname_j, fname_i;
01035                         dns_name_t *name_j, *name_i;
01036 
01037                         build_name_from_str("j.z.d.e.f", &fntmp1);
01038                         ntmp1 = dns_fixedname_name(&fntmp1);
01039                         build_name_from_str("z.d.e.f", &fntmp2);
01040                         ntmp2 = dns_fixedname_name(&fntmp2);
01041 
01042                         build_name_from_str(ordered_names[j], &fname_j);
01043                         name_j = dns_fixedname_name(&fname_j);
01044                         build_name_from_str(ordered_names[i], &fname_i);
01045                         name_i = dns_fixedname_name(&fname_i);
01046 
01047                         if (dns_name_equal(name_j, ntmp1) &&
01048                             dns_name_equal(name_j, ntmp2))
01049                         {
01050                                 /*
01051                                  * The only special case in the
01052                                  * tree. Here, "z.d.e.f" will not exist
01053                                  * as it would have been removed during
01054                                  * removal of "j.z.d.e.f".
01055                                  */
01056                                 continue;
01057                         }
01058 
01059                         if (dns_name_equal(name_i, name_j)) {
01060                                 dns_fixedname_t fntmp3, fntmp4, fntmp5, fntmp6;
01061                                 dns_name_t *ntmp3, *ntmp4, *ntmp5, *ntmp6;
01062 
01063                                 /*
01064                                  * This may be true for the last node if
01065                                  * we seek ahead in the loop using
01066                                  * dns_rbtnodechain_next() below.
01067                                  */
01068                                 if (node == NULL) {
01069                                         break;
01070                                 }
01071 
01072                                 /*
01073                                  * All ordered nodes are empty
01074                                  * initially. If an empty removed node
01075                                  * exists because it is a super-domain,
01076                                  * just skip it.
01077                                  */
01078                                 build_name_from_str("d.e.f", &fntmp3);
01079                                 ntmp3 = dns_fixedname_name(&fntmp3);
01080                                 build_name_from_str("w.y.d.e.f", &fntmp4);
01081                                 ntmp4 = dns_fixedname_name(&fntmp4);
01082                                 build_name_from_str("z.d.e.f", &fntmp5);
01083                                 ntmp5 = dns_fixedname_name(&fntmp5);
01084                                 build_name_from_str("g.h", &fntmp6);
01085                                 ntmp6 = dns_fixedname_name(&fntmp6);
01086 
01087                                 if (dns_name_equal(name_j, ntmp3) ||
01088                                     dns_name_equal(name_j, ntmp4) ||
01089                                     dns_name_equal(name_j, ntmp5) ||
01090                                     dns_name_equal(name_j, ntmp6))
01091                                 {
01092                                         result = dns_rbtnodechain_next(&chain,
01093                                                                        NULL,
01094                                                                        NULL);
01095                                         if (result == ISC_R_NOMORE) {
01096                                                 node = NULL;
01097                                         } else {
01098                                                 dns_rbtnodechain_current(&chain,
01099                                                                          NULL,
01100                                                                          NULL,
01101                                                                          &node);
01102                                         }
01103                                 }
01104                                 continue;
01105                         }
01106 
01107                         ATF_REQUIRE(node != NULL);
01108 
01109                         result = dns_rbtnodechain_next(&chain, NULL, NULL);
01110                         if (result == ISC_R_NOMORE) {
01111                                 node = NULL;
01112                         } else {
01113                                 dns_rbtnodechain_current(&chain, NULL, NULL,
01114                                                          &node);
01115                         }
01116                 }
01117 
01118                 /* We should have reached the end of the tree. */
01119                 ATF_REQUIRE_EQ(node, NULL);
01120 
01121                 dns_rbt_destroy(&mytree);
01122         }
01123 
01124         dns_test_end();
01125 }
01126 
01127 static void
01128 insert_nodes(dns_rbt_t *mytree, char **names,
01129              size_t *names_count, isc_uint32_t num_names)
01130 {
01131         isc_uint32_t i;
01132 
01133         for (i = 0; i < num_names; i++) {
01134                 size_t *n;
01135                 char namebuf[34];
01136 
01137                 n = isc_mem_get(mctx, sizeof(size_t));
01138                 ATF_REQUIRE(n != NULL);
01139 
01140                 *n = i; /* Unused value */
01141 
01142                 while (1) {
01143                         int j;
01144                         dns_fixedname_t fname;
01145                         dns_name_t *name;
01146                         isc_result_t result;
01147 
01148                         for (j = 0; j < 32; j++) {
01149                                 isc_uint32_t v;
01150                                 isc_random_get(&v);
01151                                 namebuf[j] = 'a' + (v % 26);
01152                         }
01153                         namebuf[32] = '.';
01154                         namebuf[33] = 0;
01155 
01156                         build_name_from_str(namebuf, &fname);
01157                         name = dns_fixedname_name(&fname);
01158 
01159                         result = dns_rbt_addname(mytree, name, n);
01160                         if (result == ISC_R_SUCCESS) {
01161                                 names[*names_count] = isc_mem_strdup(mctx,
01162                                                                      namebuf);
01163                                 *names_count += 1;
01164                                 break;
01165                         }
01166                 }
01167         }
01168 }
01169 
01170 static void
01171 remove_nodes(dns_rbt_t *mytree, char **names,
01172              size_t *names_count, isc_uint32_t num_names)
01173 {
01174         isc_uint32_t i;
01175 
01176         UNUSED(mytree);
01177 
01178         for (i = 0; i < num_names; i++) {
01179                 isc_uint32_t node;
01180                 dns_fixedname_t fname;
01181                 dns_name_t *name;
01182                 isc_result_t result;
01183 
01184                 isc_random_get(&node);
01185 
01186                 node %= *names_count;
01187 
01188                 build_name_from_str(names[node], &fname);
01189                 name = dns_fixedname_name(&fname);
01190 
01191                 result = dns_rbt_deletename(mytree, name, ISC_FALSE);
01192                 ATF_CHECK_EQ(result, ISC_R_SUCCESS);
01193 
01194                 isc_mem_free(mctx, names[node]);
01195                 if (*names_count > 0) {
01196                         names[node] = names[*names_count - 1];
01197                         names[*names_count - 1] = NULL;
01198                         *names_count -= 1;
01199                 }
01200         }
01201 }
01202 
01203 static void
01204 check_tree(dns_rbt_t *mytree, char **names, size_t names_count) {
01205         isc_boolean_t tree_ok;
01206 
01207         UNUSED(names);
01208 
01209         ATF_CHECK_EQ(names_count + 1, dns_rbt_nodecount(mytree));
01210 
01211         /*
01212          * The distance from each node to its sub-tree root must be less
01213          * than 2 * log_2(1024).
01214          */
01215         ATF_CHECK((2 * 10) >= dns__rbt_getheight(mytree));
01216 
01217         /* Also check RB tree properties */
01218         tree_ok = dns__rbt_checkproperties(mytree);
01219         ATF_CHECK_EQ(tree_ok, ISC_TRUE);
01220 }
01221 
01222 ATF_TC(rbt_insert_and_remove);
01223 ATF_TC_HEAD(rbt_insert_and_remove, tc) {
01224         atf_tc_set_md_var(tc, "descr",
01225                           "Test insert and remove in a loop");
01226 }
01227 ATF_TC_BODY(rbt_insert_and_remove, tc) {
01228         /*
01229          * What is the best way to test our red-black tree code? It is
01230          * not a good method to test every case handled in the actual
01231          * code itself. This is because our approach itself may be
01232          * incorrect.
01233          *
01234          * We test our code at the interface level here by exercising the
01235          * tree randomly multiple times, checking that red-black tree
01236          * properties are valid, and all the nodes that are supposed to be
01237          * in the tree exist and are in order.
01238          *
01239          * NOTE: These tests are run within a single tree level in the
01240          * forest. The number of nodes in the tree level doesn't grow
01241          * over 1024.
01242          */
01243         isc_result_t result;
01244         dns_rbt_t *mytree = NULL;
01245         /*
01246          * We use an array for storing names instead of a set
01247          * structure. It's slow, but works and is good enough for tests.
01248          */
01249         char *names[1024];
01250         size_t names_count;
01251         int i;
01252 
01253         UNUSED(tc);
01254 
01255         isc_mem_debugging = ISC_MEM_DEBUGRECORD;
01256 
01257         result = dns_test_begin(NULL, ISC_TRUE);
01258         ATF_CHECK_EQ(result, ISC_R_SUCCESS);
01259 
01260         result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
01261         ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
01262 
01263         memset(names, 0, sizeof(names));
01264         names_count = 0;
01265 
01266         /* Repeat the insert/remove test some 4096 times */
01267         for (i = 0; i < 4096; i++) {
01268                 isc_uint32_t num_names;
01269                 isc_random_get(&num_names);
01270 
01271                 if (names_count < 1024) {
01272                         num_names %= 1024 - names_count;
01273                         num_names++;
01274                 } else {
01275                         num_names = 0;
01276                 }
01277 
01278                 insert_nodes(mytree, names, &names_count, num_names);
01279                 check_tree(mytree, names, names_count);
01280 
01281                 isc_random_get(&num_names);
01282                 if (names_count > 0) {
01283                         num_names %= names_count;
01284                         num_names++;
01285                 } else {
01286                         num_names = 0;
01287                 }
01288 
01289                 remove_nodes(mytree, names, &names_count, num_names);
01290                 check_tree(mytree, names, names_count);
01291         }
01292 
01293         /* Remove the rest of the nodes */
01294         remove_nodes(mytree, names, &names_count, names_count);
01295         check_tree(mytree, names, names_count);
01296 
01297         for (i = 0; i < 1024; i++) {
01298                 if (names[i] != NULL) {
01299                         isc_mem_free(mctx, names[i]);
01300                 }
01301         }
01302 
01303         dns_rbt_destroy(&mytree);
01304 
01305         dns_test_end();
01306 }
01307 
01308 /*
01309  * Main
01310  */
01311 ATF_TP_ADD_TCS(tp) {
01312         ATF_TP_ADD_TC(tp, rbt_create);
01313         ATF_TP_ADD_TC(tp, rbt_nodecount);
01314         ATF_TP_ADD_TC(tp, rbtnode_get_distance);
01315         ATF_TP_ADD_TC(tp, rbt_check_distance_random);
01316         ATF_TP_ADD_TC(tp, rbt_check_distance_ordered);
01317         ATF_TP_ADD_TC(tp, rbt_insert);
01318         ATF_TP_ADD_TC(tp, rbt_remove);
01319         ATF_TP_ADD_TC(tp, rbt_remove_empty);
01320         ATF_TP_ADD_TC(tp, rbt_insert_and_remove);
01321 
01322         return (atf_no_error());
01323 }

Generated on Tue Apr 28 17:41:01 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha