00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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>
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
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
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
00098
00099
00100 static const int node_distances[] = {
00101 3, 1, 2, 2, 2, 3, 1, 2, 1, 1, 2, 2
00102 };
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
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
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
00350
00351
00352
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
00372
00373
00374
00375
00376
00377
00378
00379
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
00411 ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree));
00412
00413
00414
00415
00416 ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree));
00417
00418
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
00434
00435
00436
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
00456
00457
00458
00459
00460
00461
00462
00463
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
00483 ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree));
00484
00485
00486
00487
00488 ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree));
00489
00490
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
00549 ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
00550
00551
00552 node = NULL;
00553 result = insert_helper(ctx->rbt, "d.e.f", &node);
00554 ATF_CHECK_EQ(result, ISC_R_EXISTS);
00555
00556
00557 ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
00558
00559
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
00566 ATF_CHECK_EQ(16, dns_rbt_nodecount(ctx->rbt));
00567
00568
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
00576 ATF_CHECK_EQ(17, dns_rbt_nodecount(ctx->rbt));
00577
00578
00579 node = NULL;
00580 result = insert_helper(ctx->rbt, "example.com", &node);
00581 ATF_CHECK_EQ(result, ISC_R_EXISTS);
00582
00583
00584 ATF_CHECK_EQ(17, dns_rbt_nodecount(ctx->rbt));
00585
00586
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
00593
00594
00595 ATF_CHECK_EQ(19, dns_rbt_nodecount(ctx->rbt));
00596
00597
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
00604
00605
00606 ATF_CHECK_EQ(20, dns_rbt_nodecount(ctx->rbt));
00607
00608
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
00641
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
00699
00700
00701
00702
00703
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
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
00728 result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
00729 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00730
00731
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
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
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
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
00777 tree_ok = dns__rbt_checkproperties(mytree);
00778 ATF_CHECK_EQ(tree_ok, ISC_TRUE);
00779
00780 dns_rbtnodechain_init(&chain, mctx);
00781
00782
00783 if (j == 0) {
00784
00785
00786
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
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
00827
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
00841
00842
00843
00844 if (node == NULL) {
00845 break;
00846 }
00847
00848
00849
00850
00851
00852
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
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
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
00905
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
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
00929 result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
00930 ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
00931
00932
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
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
00955 ATF_REQUIRE(node != NULL);
00956 ATF_REQUIRE_EQ(node->data, NULL);
00957 }
00958
00959
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
00979 tree_ok = dns__rbt_checkproperties(mytree);
00980 ATF_CHECK_EQ(tree_ok, ISC_TRUE);
00981
00982 dns_rbtnodechain_init(&chain, mctx);
00983
00984
00985 if (j == 0) {
00986
00987
00988
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
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
01029
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
01052
01053
01054
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
01065
01066
01067
01068 if (node == NULL) {
01069 break;
01070 }
01071
01072
01073
01074
01075
01076
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
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;
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
01213
01214
01215 ATF_CHECK((2 * 10) >= dns__rbt_getheight(mytree));
01216
01217
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
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243 isc_result_t result;
01244 dns_rbt_t *mytree = NULL;
01245
01246
01247
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
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
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
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 }