1*00b67f09SDavid van Moolenbroek /* $NetBSD: rbt_test.c,v 1.1.1.4 2014/12/10 03:34:43 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek *
6*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
7*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
8*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
9*00b67f09SDavid van Moolenbroek *
10*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
17*00b67f09SDavid van Moolenbroek */
18*00b67f09SDavid van Moolenbroek
19*00b67f09SDavid van Moolenbroek /* Id: rbt_test.c,v 1.1.14.8 2012/02/10 16:24:37 ckb Exp */
20*00b67f09SDavid van Moolenbroek
21*00b67f09SDavid van Moolenbroek /* ! \file */
22*00b67f09SDavid van Moolenbroek
23*00b67f09SDavid van Moolenbroek #include <config.h>
24*00b67f09SDavid van Moolenbroek #include <atf-c.h>
25*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
26*00b67f09SDavid van Moolenbroek #include <isc/random.h>
27*00b67f09SDavid van Moolenbroek #include <isc/string.h>
28*00b67f09SDavid van Moolenbroek #include <fcntl.h>
29*00b67f09SDavid van Moolenbroek #include <unistd.h>
30*00b67f09SDavid van Moolenbroek
31*00b67f09SDavid van Moolenbroek #ifdef HAVE_INTTYPES_H
32*00b67f09SDavid van Moolenbroek #include <inttypes.h> /* uintptr_t */
33*00b67f09SDavid van Moolenbroek #endif
34*00b67f09SDavid van Moolenbroek
35*00b67f09SDavid van Moolenbroek #include <dns/rbt.h>
36*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
37*00b67f09SDavid van Moolenbroek #include <dns/result.h>
38*00b67f09SDavid van Moolenbroek #include <dns/compress.h>
39*00b67f09SDavid van Moolenbroek #include "dnstest.h"
40*00b67f09SDavid van Moolenbroek
41*00b67f09SDavid van Moolenbroek #include <isc/app.h>
42*00b67f09SDavid van Moolenbroek #include <isc/buffer.h>
43*00b67f09SDavid van Moolenbroek #include <isc/entropy.h>
44*00b67f09SDavid van Moolenbroek #include <isc/file.h>
45*00b67f09SDavid van Moolenbroek #include <isc/hash.h>
46*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
47*00b67f09SDavid van Moolenbroek #include <isc/os.h>
48*00b67f09SDavid van Moolenbroek #include <isc/string.h>
49*00b67f09SDavid van Moolenbroek #include <isc/socket.h>
50*00b67f09SDavid van Moolenbroek #include <isc/stdio.h>
51*00b67f09SDavid van Moolenbroek #include <isc/task.h>
52*00b67f09SDavid van Moolenbroek #include <isc/timer.h>
53*00b67f09SDavid van Moolenbroek #include <isc/util.h>
54*00b67f09SDavid van Moolenbroek #include <isc/print.h>
55*00b67f09SDavid van Moolenbroek
56*00b67f09SDavid van Moolenbroek #include <dns/log.h>
57*00b67f09SDavid van Moolenbroek #include <dns/name.h>
58*00b67f09SDavid van Moolenbroek #include <dns/result.h>
59*00b67f09SDavid van Moolenbroek
60*00b67f09SDavid van Moolenbroek #include <dst/dst.h>
61*00b67f09SDavid van Moolenbroek
62*00b67f09SDavid van Moolenbroek #include <ctype.h>
63*00b67f09SDavid van Moolenbroek
64*00b67f09SDavid van Moolenbroek typedef struct {
65*00b67f09SDavid van Moolenbroek dns_rbt_t *rbt;
66*00b67f09SDavid van Moolenbroek dns_rbt_t *rbt_distances;
67*00b67f09SDavid van Moolenbroek } test_context_t;
68*00b67f09SDavid van Moolenbroek
69*00b67f09SDavid van Moolenbroek /* The initial structure of domain tree will be as follows:
70*00b67f09SDavid van Moolenbroek *
71*00b67f09SDavid van Moolenbroek * .
72*00b67f09SDavid van Moolenbroek * |
73*00b67f09SDavid van Moolenbroek * b
74*00b67f09SDavid van Moolenbroek * / \
75*00b67f09SDavid van Moolenbroek * a d.e.f
76*00b67f09SDavid van Moolenbroek * / | \
77*00b67f09SDavid van Moolenbroek * c | g.h
78*00b67f09SDavid van Moolenbroek * | |
79*00b67f09SDavid van Moolenbroek * w.y i
80*00b67f09SDavid van Moolenbroek * / | \ \
81*00b67f09SDavid van Moolenbroek * x | z k
82*00b67f09SDavid van Moolenbroek * | |
83*00b67f09SDavid van Moolenbroek * p j
84*00b67f09SDavid van Moolenbroek * / \
85*00b67f09SDavid van Moolenbroek * o q
86*00b67f09SDavid van Moolenbroek */
87*00b67f09SDavid van Moolenbroek
88*00b67f09SDavid van Moolenbroek /* The full absolute names of the nodes in the tree (the tree also
89*00b67f09SDavid van Moolenbroek * contains "." which is not included in this list).
90*00b67f09SDavid van Moolenbroek */
91*00b67f09SDavid van Moolenbroek static const char * const domain_names[] = {
92*00b67f09SDavid van Moolenbroek "c", "b", "a", "x.d.e.f", "z.d.e.f", "g.h", "i.g.h", "o.w.y.d.e.f",
93*00b67f09SDavid van Moolenbroek "j.z.d.e.f", "p.w.y.d.e.f", "q.w.y.d.e.f", "k.g.h"
94*00b67f09SDavid van Moolenbroek };
95*00b67f09SDavid van Moolenbroek
96*00b67f09SDavid van Moolenbroek static const size_t domain_names_count = (sizeof(domain_names) /
97*00b67f09SDavid van Moolenbroek sizeof(domain_names[0]));
98*00b67f09SDavid van Moolenbroek
99*00b67f09SDavid van Moolenbroek /* These are set as the node data for the tree used in distances check
100*00b67f09SDavid van Moolenbroek * (for the names in domain_names[] above).
101*00b67f09SDavid van Moolenbroek */
102*00b67f09SDavid van Moolenbroek static const int node_distances[] = {
103*00b67f09SDavid van Moolenbroek 3, 1, 2, 2, 2, 3, 1, 2, 1, 1, 2, 2
104*00b67f09SDavid van Moolenbroek };
105*00b67f09SDavid van Moolenbroek
106*00b67f09SDavid van Moolenbroek /*
107*00b67f09SDavid van Moolenbroek * The domain order should be:
108*00b67f09SDavid van Moolenbroek * ., 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,
109*00b67f09SDavid van Moolenbroek * q.w.y.d.e.f, z.d.e.f, j.z.d.e.f, g.h, i.g.h, k.g.h
110*00b67f09SDavid van Moolenbroek * . (no data, can't be found)
111*00b67f09SDavid van Moolenbroek * |
112*00b67f09SDavid van Moolenbroek * b
113*00b67f09SDavid van Moolenbroek * / \
114*00b67f09SDavid van Moolenbroek * a d.e.f
115*00b67f09SDavid van Moolenbroek * / | \
116*00b67f09SDavid van Moolenbroek * c | g.h
117*00b67f09SDavid van Moolenbroek * | |
118*00b67f09SDavid van Moolenbroek * w.y i
119*00b67f09SDavid van Moolenbroek * / | \ \
120*00b67f09SDavid van Moolenbroek * x | z k
121*00b67f09SDavid van Moolenbroek * | |
122*00b67f09SDavid van Moolenbroek * p j
123*00b67f09SDavid van Moolenbroek * / \
124*00b67f09SDavid van Moolenbroek * o q
125*00b67f09SDavid van Moolenbroek */
126*00b67f09SDavid van Moolenbroek
127*00b67f09SDavid van Moolenbroek static const char * const ordered_names[] = {
128*00b67f09SDavid van Moolenbroek "a", "b", "c", "d.e.f", "x.d.e.f", "w.y.d.e.f", "o.w.y.d.e.f",
129*00b67f09SDavid van Moolenbroek "p.w.y.d.e.f", "q.w.y.d.e.f", "z.d.e.f", "j.z.d.e.f",
130*00b67f09SDavid van Moolenbroek "g.h", "i.g.h", "k.g.h"};
131*00b67f09SDavid van Moolenbroek
132*00b67f09SDavid van Moolenbroek static const size_t ordered_names_count = (sizeof(ordered_names) /
133*00b67f09SDavid van Moolenbroek sizeof(*ordered_names));
134*00b67f09SDavid van Moolenbroek
135*00b67f09SDavid van Moolenbroek static void
delete_data(void * data,void * arg)136*00b67f09SDavid van Moolenbroek delete_data(void *data, void *arg) {
137*00b67f09SDavid van Moolenbroek UNUSED(arg);
138*00b67f09SDavid van Moolenbroek
139*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, data, sizeof(size_t));
140*00b67f09SDavid van Moolenbroek }
141*00b67f09SDavid van Moolenbroek
142*00b67f09SDavid van Moolenbroek static void
build_name_from_str(const char * namestr,dns_fixedname_t * fname)143*00b67f09SDavid van Moolenbroek build_name_from_str(const char *namestr, dns_fixedname_t *fname) {
144*00b67f09SDavid van Moolenbroek size_t length;
145*00b67f09SDavid van Moolenbroek isc_buffer_t *b = NULL;
146*00b67f09SDavid van Moolenbroek isc_result_t result;
147*00b67f09SDavid van Moolenbroek dns_name_t *name;
148*00b67f09SDavid van Moolenbroek
149*00b67f09SDavid van Moolenbroek length = strlen(namestr);
150*00b67f09SDavid van Moolenbroek
151*00b67f09SDavid van Moolenbroek result = isc_buffer_allocate(mctx, &b, length);
152*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
153*00b67f09SDavid van Moolenbroek isc_buffer_putmem(b, (const unsigned char *) namestr, length);
154*00b67f09SDavid van Moolenbroek
155*00b67f09SDavid van Moolenbroek dns_fixedname_init(fname);
156*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(fname);
157*00b67f09SDavid van Moolenbroek ATF_REQUIRE(name != NULL);
158*00b67f09SDavid van Moolenbroek result = dns_name_fromtext(name, b, dns_rootname, 0, NULL);
159*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
160*00b67f09SDavid van Moolenbroek
161*00b67f09SDavid van Moolenbroek isc_buffer_free(&b);
162*00b67f09SDavid van Moolenbroek }
163*00b67f09SDavid van Moolenbroek
164*00b67f09SDavid van Moolenbroek static test_context_t *
test_context_setup(void)165*00b67f09SDavid van Moolenbroek test_context_setup(void) {
166*00b67f09SDavid van Moolenbroek test_context_t *ctx;
167*00b67f09SDavid van Moolenbroek isc_result_t result;
168*00b67f09SDavid van Moolenbroek size_t i;
169*00b67f09SDavid van Moolenbroek
170*00b67f09SDavid van Moolenbroek ctx = isc_mem_get(mctx, sizeof(*ctx));
171*00b67f09SDavid van Moolenbroek
172*00b67f09SDavid van Moolenbroek ctx->rbt = NULL;
173*00b67f09SDavid van Moolenbroek result = dns_rbt_create(mctx, delete_data, NULL, &ctx->rbt);
174*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
175*00b67f09SDavid van Moolenbroek
176*00b67f09SDavid van Moolenbroek ctx->rbt_distances = NULL;
177*00b67f09SDavid van Moolenbroek result = dns_rbt_create(mctx, delete_data, NULL, &ctx->rbt_distances);
178*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
179*00b67f09SDavid van Moolenbroek
180*00b67f09SDavid van Moolenbroek for (i = 0; i < domain_names_count; i++) {
181*00b67f09SDavid van Moolenbroek size_t *n;
182*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
183*00b67f09SDavid van Moolenbroek dns_name_t *name;
184*00b67f09SDavid van Moolenbroek
185*00b67f09SDavid van Moolenbroek build_name_from_str(domain_names[i], &fname);
186*00b67f09SDavid van Moolenbroek
187*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
188*00b67f09SDavid van Moolenbroek
189*00b67f09SDavid van Moolenbroek n = isc_mem_get(mctx, sizeof(size_t));
190*00b67f09SDavid van Moolenbroek *n = i + 1;
191*00b67f09SDavid van Moolenbroek result = dns_rbt_addname(ctx->rbt, name, n);
192*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
193*00b67f09SDavid van Moolenbroek
194*00b67f09SDavid van Moolenbroek n = isc_mem_get(mctx, sizeof(size_t));
195*00b67f09SDavid van Moolenbroek *n = node_distances[i];
196*00b67f09SDavid van Moolenbroek result = dns_rbt_addname(ctx->rbt_distances, name, n);
197*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
198*00b67f09SDavid van Moolenbroek }
199*00b67f09SDavid van Moolenbroek
200*00b67f09SDavid van Moolenbroek return (ctx);
201*00b67f09SDavid van Moolenbroek }
202*00b67f09SDavid van Moolenbroek
203*00b67f09SDavid van Moolenbroek static void
test_context_teardown(test_context_t * ctx)204*00b67f09SDavid van Moolenbroek test_context_teardown(test_context_t *ctx) {
205*00b67f09SDavid van Moolenbroek dns_rbt_destroy(&ctx->rbt);
206*00b67f09SDavid van Moolenbroek dns_rbt_destroy(&ctx->rbt_distances);
207*00b67f09SDavid van Moolenbroek
208*00b67f09SDavid van Moolenbroek isc_mem_put(mctx, ctx, sizeof(*ctx));
209*00b67f09SDavid van Moolenbroek }
210*00b67f09SDavid van Moolenbroek
211*00b67f09SDavid van Moolenbroek /*
212*00b67f09SDavid van Moolenbroek * Walk the tree and ensure that all the test nodes are present.
213*00b67f09SDavid van Moolenbroek */
214*00b67f09SDavid van Moolenbroek static void
check_test_data(dns_rbt_t * rbt)215*00b67f09SDavid van Moolenbroek check_test_data(dns_rbt_t *rbt) {
216*00b67f09SDavid van Moolenbroek dns_fixedname_t fixed;
217*00b67f09SDavid van Moolenbroek isc_result_t result;
218*00b67f09SDavid van Moolenbroek dns_name_t *foundname;
219*00b67f09SDavid van Moolenbroek size_t i;
220*00b67f09SDavid van Moolenbroek
221*00b67f09SDavid van Moolenbroek dns_fixedname_init(&fixed);
222*00b67f09SDavid van Moolenbroek foundname = dns_fixedname_name(&fixed);
223*00b67f09SDavid van Moolenbroek
224*00b67f09SDavid van Moolenbroek for (i = 0; i < domain_names_count; i++) {
225*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
226*00b67f09SDavid van Moolenbroek dns_name_t *name;
227*00b67f09SDavid van Moolenbroek size_t *n;
228*00b67f09SDavid van Moolenbroek
229*00b67f09SDavid van Moolenbroek build_name_from_str(domain_names[i], &fname);
230*00b67f09SDavid van Moolenbroek
231*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
232*00b67f09SDavid van Moolenbroek n = NULL;
233*00b67f09SDavid van Moolenbroek result = dns_rbt_findname(rbt, name, 0, foundname,
234*00b67f09SDavid van Moolenbroek (void *) &n);
235*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
236*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(*n, i + 1);
237*00b67f09SDavid van Moolenbroek }
238*00b67f09SDavid van Moolenbroek }
239*00b67f09SDavid van Moolenbroek
240*00b67f09SDavid van Moolenbroek ATF_TC(rbt_create);
ATF_TC_HEAD(rbt_create,tc)241*00b67f09SDavid van Moolenbroek ATF_TC_HEAD(rbt_create, tc) {
242*00b67f09SDavid van Moolenbroek atf_tc_set_md_var(tc, "descr", "Test the creation of an rbt");
243*00b67f09SDavid van Moolenbroek }
ATF_TC_BODY(rbt_create,tc)244*00b67f09SDavid van Moolenbroek ATF_TC_BODY(rbt_create, tc) {
245*00b67f09SDavid van Moolenbroek isc_result_t result;
246*00b67f09SDavid van Moolenbroek test_context_t *ctx;
247*00b67f09SDavid van Moolenbroek isc_boolean_t tree_ok;
248*00b67f09SDavid van Moolenbroek
249*00b67f09SDavid van Moolenbroek UNUSED(tc);
250*00b67f09SDavid van Moolenbroek
251*00b67f09SDavid van Moolenbroek isc_mem_debugging = ISC_MEM_DEBUGRECORD;
252*00b67f09SDavid van Moolenbroek
253*00b67f09SDavid van Moolenbroek result = dns_test_begin(NULL, ISC_TRUE);
254*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
255*00b67f09SDavid van Moolenbroek
256*00b67f09SDavid van Moolenbroek ctx = test_context_setup();
257*00b67f09SDavid van Moolenbroek
258*00b67f09SDavid van Moolenbroek check_test_data(ctx->rbt);
259*00b67f09SDavid van Moolenbroek
260*00b67f09SDavid van Moolenbroek tree_ok = dns__rbt_checkproperties(ctx->rbt);
261*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(tree_ok, ISC_TRUE);
262*00b67f09SDavid van Moolenbroek
263*00b67f09SDavid van Moolenbroek test_context_teardown(ctx);
264*00b67f09SDavid van Moolenbroek
265*00b67f09SDavid van Moolenbroek dns_test_end();
266*00b67f09SDavid van Moolenbroek }
267*00b67f09SDavid van Moolenbroek
268*00b67f09SDavid van Moolenbroek ATF_TC(rbt_nodecount);
ATF_TC_HEAD(rbt_nodecount,tc)269*00b67f09SDavid van Moolenbroek ATF_TC_HEAD(rbt_nodecount, tc) {
270*00b67f09SDavid van Moolenbroek atf_tc_set_md_var(tc, "descr", "Test dns_rbt_nodecount() on a tree");
271*00b67f09SDavid van Moolenbroek }
ATF_TC_BODY(rbt_nodecount,tc)272*00b67f09SDavid van Moolenbroek ATF_TC_BODY(rbt_nodecount, tc) {
273*00b67f09SDavid van Moolenbroek isc_result_t result;
274*00b67f09SDavid van Moolenbroek test_context_t *ctx;
275*00b67f09SDavid van Moolenbroek
276*00b67f09SDavid van Moolenbroek UNUSED(tc);
277*00b67f09SDavid van Moolenbroek
278*00b67f09SDavid van Moolenbroek isc_mem_debugging = ISC_MEM_DEBUGRECORD;
279*00b67f09SDavid van Moolenbroek
280*00b67f09SDavid van Moolenbroek result = dns_test_begin(NULL, ISC_TRUE);
281*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
282*00b67f09SDavid van Moolenbroek
283*00b67f09SDavid van Moolenbroek ctx = test_context_setup();
284*00b67f09SDavid van Moolenbroek
285*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
286*00b67f09SDavid van Moolenbroek
287*00b67f09SDavid van Moolenbroek test_context_teardown(ctx);
288*00b67f09SDavid van Moolenbroek
289*00b67f09SDavid van Moolenbroek dns_test_end();
290*00b67f09SDavid van Moolenbroek }
291*00b67f09SDavid van Moolenbroek
292*00b67f09SDavid van Moolenbroek ATF_TC(rbtnode_get_distance);
ATF_TC_HEAD(rbtnode_get_distance,tc)293*00b67f09SDavid van Moolenbroek ATF_TC_HEAD(rbtnode_get_distance, tc) {
294*00b67f09SDavid van Moolenbroek atf_tc_set_md_var(tc, "descr",
295*00b67f09SDavid van Moolenbroek "Test dns_rbtnode_get_distance() on a tree");
296*00b67f09SDavid van Moolenbroek }
ATF_TC_BODY(rbtnode_get_distance,tc)297*00b67f09SDavid van Moolenbroek ATF_TC_BODY(rbtnode_get_distance, tc) {
298*00b67f09SDavid van Moolenbroek isc_result_t result;
299*00b67f09SDavid van Moolenbroek test_context_t *ctx;
300*00b67f09SDavid van Moolenbroek const char *name_str = "a";
301*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
302*00b67f09SDavid van Moolenbroek dns_name_t *name;
303*00b67f09SDavid van Moolenbroek dns_rbtnode_t *node = NULL;
304*00b67f09SDavid van Moolenbroek dns_rbtnodechain_t chain;
305*00b67f09SDavid van Moolenbroek
306*00b67f09SDavid van Moolenbroek UNUSED(tc);
307*00b67f09SDavid van Moolenbroek
308*00b67f09SDavid van Moolenbroek isc_mem_debugging = ISC_MEM_DEBUGRECORD;
309*00b67f09SDavid van Moolenbroek
310*00b67f09SDavid van Moolenbroek result = dns_test_begin(NULL, ISC_TRUE);
311*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
312*00b67f09SDavid van Moolenbroek
313*00b67f09SDavid van Moolenbroek ctx = test_context_setup();
314*00b67f09SDavid van Moolenbroek
315*00b67f09SDavid van Moolenbroek build_name_from_str(name_str, &fname);
316*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
317*00b67f09SDavid van Moolenbroek
318*00b67f09SDavid van Moolenbroek dns_rbtnodechain_init(&chain, mctx);
319*00b67f09SDavid van Moolenbroek
320*00b67f09SDavid van Moolenbroek result = dns_rbt_findnode(ctx->rbt_distances, name, NULL,
321*00b67f09SDavid van Moolenbroek &node, &chain, 0, NULL, NULL);
322*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
323*00b67f09SDavid van Moolenbroek
324*00b67f09SDavid van Moolenbroek while (node != NULL) {
325*00b67f09SDavid van Moolenbroek const size_t *distance = (const size_t *) node->data;
326*00b67f09SDavid van Moolenbroek if (distance != NULL)
327*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(*distance,
328*00b67f09SDavid van Moolenbroek dns__rbtnode_getdistance(node));
329*00b67f09SDavid van Moolenbroek result = dns_rbtnodechain_next(&chain, NULL, NULL);
330*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE)
331*00b67f09SDavid van Moolenbroek break;
332*00b67f09SDavid van Moolenbroek dns_rbtnodechain_current(&chain, NULL, NULL, &node);
333*00b67f09SDavid van Moolenbroek }
334*00b67f09SDavid van Moolenbroek
335*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_NOMORE);
336*00b67f09SDavid van Moolenbroek
337*00b67f09SDavid van Moolenbroek dns_rbtnodechain_invalidate(&chain);
338*00b67f09SDavid van Moolenbroek
339*00b67f09SDavid van Moolenbroek test_context_teardown(ctx);
340*00b67f09SDavid van Moolenbroek
341*00b67f09SDavid van Moolenbroek dns_test_end();
342*00b67f09SDavid van Moolenbroek }
343*00b67f09SDavid van Moolenbroek
344*00b67f09SDavid van Moolenbroek ATF_TC(rbt_check_distance_random);
ATF_TC_HEAD(rbt_check_distance_random,tc)345*00b67f09SDavid van Moolenbroek ATF_TC_HEAD(rbt_check_distance_random, tc) {
346*00b67f09SDavid van Moolenbroek atf_tc_set_md_var(tc, "descr",
347*00b67f09SDavid van Moolenbroek "Test tree balance, inserting names in random order");
348*00b67f09SDavid van Moolenbroek }
ATF_TC_BODY(rbt_check_distance_random,tc)349*00b67f09SDavid van Moolenbroek ATF_TC_BODY(rbt_check_distance_random, tc) {
350*00b67f09SDavid van Moolenbroek /* This test checks an important performance-related property of
351*00b67f09SDavid van Moolenbroek * the red-black tree, which is important for us: the longest
352*00b67f09SDavid van Moolenbroek * path from a sub-tree's root to a node is no more than
353*00b67f09SDavid van Moolenbroek * 2log(n). This check verifies that the tree is balanced.
354*00b67f09SDavid van Moolenbroek */
355*00b67f09SDavid van Moolenbroek dns_rbt_t *mytree = NULL;
356*00b67f09SDavid van Moolenbroek const unsigned int log_num_nodes = 16;
357*00b67f09SDavid van Moolenbroek
358*00b67f09SDavid van Moolenbroek int i;
359*00b67f09SDavid van Moolenbroek isc_result_t result;
360*00b67f09SDavid van Moolenbroek isc_boolean_t tree_ok;
361*00b67f09SDavid van Moolenbroek
362*00b67f09SDavid van Moolenbroek UNUSED(tc);
363*00b67f09SDavid van Moolenbroek
364*00b67f09SDavid van Moolenbroek isc_mem_debugging = ISC_MEM_DEBUGRECORD;
365*00b67f09SDavid van Moolenbroek
366*00b67f09SDavid van Moolenbroek result = dns_test_begin(NULL, ISC_TRUE);
367*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
368*00b67f09SDavid van Moolenbroek
369*00b67f09SDavid van Moolenbroek result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
370*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
371*00b67f09SDavid van Moolenbroek
372*00b67f09SDavid van Moolenbroek /* Names are inserted in random order. */
373*00b67f09SDavid van Moolenbroek
374*00b67f09SDavid van Moolenbroek /* Make a large 65536 node top-level domain tree, i.e., the
375*00b67f09SDavid van Moolenbroek * following code inserts names such as:
376*00b67f09SDavid van Moolenbroek *
377*00b67f09SDavid van Moolenbroek * savoucnsrkrqzpkqypbygwoiliawpbmz.
378*00b67f09SDavid van Moolenbroek * wkadamcbbpjtundbxcmuayuycposvngx.
379*00b67f09SDavid van Moolenbroek * wzbpznemtooxdpjecdxynsfztvnuyfao.
380*00b67f09SDavid van Moolenbroek * yueojmhyffslpvfmgyfwioxegfhepnqq.
381*00b67f09SDavid van Moolenbroek */
382*00b67f09SDavid van Moolenbroek for (i = 0; i < (1 << log_num_nodes); i++) {
383*00b67f09SDavid van Moolenbroek size_t *n;
384*00b67f09SDavid van Moolenbroek char namebuf[34];
385*00b67f09SDavid van Moolenbroek
386*00b67f09SDavid van Moolenbroek n = isc_mem_get(mctx, sizeof(size_t));
387*00b67f09SDavid van Moolenbroek *n = i + 1;
388*00b67f09SDavid van Moolenbroek
389*00b67f09SDavid van Moolenbroek while (1) {
390*00b67f09SDavid van Moolenbroek int j;
391*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
392*00b67f09SDavid van Moolenbroek dns_name_t *name;
393*00b67f09SDavid van Moolenbroek
394*00b67f09SDavid van Moolenbroek for (j = 0; j < 32; j++) {
395*00b67f09SDavid van Moolenbroek isc_uint32_t v;
396*00b67f09SDavid van Moolenbroek isc_random_get(&v);
397*00b67f09SDavid van Moolenbroek namebuf[j] = 'a' + (v % 26);
398*00b67f09SDavid van Moolenbroek }
399*00b67f09SDavid van Moolenbroek namebuf[32] = '.';
400*00b67f09SDavid van Moolenbroek namebuf[33] = 0;
401*00b67f09SDavid van Moolenbroek
402*00b67f09SDavid van Moolenbroek build_name_from_str(namebuf, &fname);
403*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
404*00b67f09SDavid van Moolenbroek
405*00b67f09SDavid van Moolenbroek result = dns_rbt_addname(mytree, name, n);
406*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS)
407*00b67f09SDavid van Moolenbroek break;
408*00b67f09SDavid van Moolenbroek }
409*00b67f09SDavid van Moolenbroek }
410*00b67f09SDavid van Moolenbroek
411*00b67f09SDavid van Moolenbroek /* 1 (root . node) + (1 << log_num_nodes) */
412*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree));
413*00b67f09SDavid van Moolenbroek
414*00b67f09SDavid van Moolenbroek /* The distance from each node to its sub-tree root must be less
415*00b67f09SDavid van Moolenbroek * than 2 * log(n).
416*00b67f09SDavid van Moolenbroek */
417*00b67f09SDavid van Moolenbroek ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree));
418*00b67f09SDavid van Moolenbroek
419*00b67f09SDavid van Moolenbroek /* Also check RB tree properties */
420*00b67f09SDavid van Moolenbroek tree_ok = dns__rbt_checkproperties(mytree);
421*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(tree_ok, ISC_TRUE);
422*00b67f09SDavid van Moolenbroek
423*00b67f09SDavid van Moolenbroek dns_rbt_destroy(&mytree);
424*00b67f09SDavid van Moolenbroek
425*00b67f09SDavid van Moolenbroek dns_test_end();
426*00b67f09SDavid van Moolenbroek }
427*00b67f09SDavid van Moolenbroek
428*00b67f09SDavid van Moolenbroek ATF_TC(rbt_check_distance_ordered);
ATF_TC_HEAD(rbt_check_distance_ordered,tc)429*00b67f09SDavid van Moolenbroek ATF_TC_HEAD(rbt_check_distance_ordered, tc) {
430*00b67f09SDavid van Moolenbroek atf_tc_set_md_var(tc, "descr",
431*00b67f09SDavid van Moolenbroek "Test tree balance, inserting names in sorted order");
432*00b67f09SDavid van Moolenbroek }
ATF_TC_BODY(rbt_check_distance_ordered,tc)433*00b67f09SDavid van Moolenbroek ATF_TC_BODY(rbt_check_distance_ordered, tc) {
434*00b67f09SDavid van Moolenbroek /* This test checks an important performance-related property of
435*00b67f09SDavid van Moolenbroek * the red-black tree, which is important for us: the longest
436*00b67f09SDavid van Moolenbroek * path from a sub-tree's root to a node is no more than
437*00b67f09SDavid van Moolenbroek * 2log(n). This check verifies that the tree is balanced.
438*00b67f09SDavid van Moolenbroek */
439*00b67f09SDavid van Moolenbroek dns_rbt_t *mytree = NULL;
440*00b67f09SDavid van Moolenbroek const unsigned int log_num_nodes = 16;
441*00b67f09SDavid van Moolenbroek
442*00b67f09SDavid van Moolenbroek int i;
443*00b67f09SDavid van Moolenbroek isc_result_t result;
444*00b67f09SDavid van Moolenbroek isc_boolean_t tree_ok;
445*00b67f09SDavid van Moolenbroek
446*00b67f09SDavid van Moolenbroek UNUSED(tc);
447*00b67f09SDavid van Moolenbroek
448*00b67f09SDavid van Moolenbroek isc_mem_debugging = ISC_MEM_DEBUGRECORD;
449*00b67f09SDavid van Moolenbroek
450*00b67f09SDavid van Moolenbroek result = dns_test_begin(NULL, ISC_TRUE);
451*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
452*00b67f09SDavid van Moolenbroek
453*00b67f09SDavid van Moolenbroek result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
454*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
455*00b67f09SDavid van Moolenbroek
456*00b67f09SDavid van Moolenbroek /* Names are inserted in sorted order. */
457*00b67f09SDavid van Moolenbroek
458*00b67f09SDavid van Moolenbroek /* Make a large 65536 node top-level domain tree, i.e., the
459*00b67f09SDavid van Moolenbroek * following code inserts names such as:
460*00b67f09SDavid van Moolenbroek *
461*00b67f09SDavid van Moolenbroek * name00000000.
462*00b67f09SDavid van Moolenbroek * name00000001.
463*00b67f09SDavid van Moolenbroek * name00000002.
464*00b67f09SDavid van Moolenbroek * name00000003.
465*00b67f09SDavid van Moolenbroek */
466*00b67f09SDavid van Moolenbroek for (i = 0; i < (1 << log_num_nodes); i++) {
467*00b67f09SDavid van Moolenbroek size_t *n;
468*00b67f09SDavid van Moolenbroek char namebuf[14];
469*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
470*00b67f09SDavid van Moolenbroek dns_name_t *name;
471*00b67f09SDavid van Moolenbroek
472*00b67f09SDavid van Moolenbroek n = isc_mem_get(mctx, sizeof(size_t));
473*00b67f09SDavid van Moolenbroek *n = i + 1;
474*00b67f09SDavid van Moolenbroek
475*00b67f09SDavid van Moolenbroek snprintf(namebuf, sizeof(namebuf), "name%08x.", i);
476*00b67f09SDavid van Moolenbroek build_name_from_str(namebuf, &fname);
477*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
478*00b67f09SDavid van Moolenbroek
479*00b67f09SDavid van Moolenbroek result = dns_rbt_addname(mytree, name, n);
480*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
481*00b67f09SDavid van Moolenbroek }
482*00b67f09SDavid van Moolenbroek
483*00b67f09SDavid van Moolenbroek /* 1 (root . node) + (1 << log_num_nodes) */
484*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(1U + (1U << log_num_nodes), dns_rbt_nodecount(mytree));
485*00b67f09SDavid van Moolenbroek
486*00b67f09SDavid van Moolenbroek /* The distance from each node to its sub-tree root must be less
487*00b67f09SDavid van Moolenbroek * than 2 * log(n).
488*00b67f09SDavid van Moolenbroek */
489*00b67f09SDavid van Moolenbroek ATF_CHECK((2U * log_num_nodes) >= dns__rbt_getheight(mytree));
490*00b67f09SDavid van Moolenbroek
491*00b67f09SDavid van Moolenbroek /* Also check RB tree properties */
492*00b67f09SDavid van Moolenbroek tree_ok = dns__rbt_checkproperties(mytree);
493*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(tree_ok, ISC_TRUE);
494*00b67f09SDavid van Moolenbroek
495*00b67f09SDavid van Moolenbroek dns_rbt_destroy(&mytree);
496*00b67f09SDavid van Moolenbroek
497*00b67f09SDavid van Moolenbroek dns_test_end();
498*00b67f09SDavid van Moolenbroek }
499*00b67f09SDavid van Moolenbroek
500*00b67f09SDavid van Moolenbroek static isc_result_t
insert_helper(dns_rbt_t * rbt,const char * namestr,dns_rbtnode_t ** node)501*00b67f09SDavid van Moolenbroek insert_helper(dns_rbt_t *rbt, const char *namestr, dns_rbtnode_t **node) {
502*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
503*00b67f09SDavid van Moolenbroek dns_name_t *name;
504*00b67f09SDavid van Moolenbroek
505*00b67f09SDavid van Moolenbroek build_name_from_str(namestr, &fname);
506*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
507*00b67f09SDavid van Moolenbroek
508*00b67f09SDavid van Moolenbroek return (dns_rbt_addnode(rbt, name, node));
509*00b67f09SDavid van Moolenbroek }
510*00b67f09SDavid van Moolenbroek
511*00b67f09SDavid van Moolenbroek static isc_boolean_t
compare_labelsequences(dns_rbtnode_t * node,const char * labelstr)512*00b67f09SDavid van Moolenbroek compare_labelsequences(dns_rbtnode_t *node, const char *labelstr) {
513*00b67f09SDavid van Moolenbroek dns_name_t name;
514*00b67f09SDavid van Moolenbroek isc_result_t result;
515*00b67f09SDavid van Moolenbroek char *nodestr = NULL;
516*00b67f09SDavid van Moolenbroek isc_boolean_t is_equal;
517*00b67f09SDavid van Moolenbroek
518*00b67f09SDavid van Moolenbroek dns_name_init(&name, NULL);
519*00b67f09SDavid van Moolenbroek dns_rbt_namefromnode(node, &name);
520*00b67f09SDavid van Moolenbroek
521*00b67f09SDavid van Moolenbroek result = dns_name_tostring(&name, &nodestr, mctx);
522*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
523*00b67f09SDavid van Moolenbroek
524*00b67f09SDavid van Moolenbroek is_equal = strcmp(labelstr, nodestr) == 0 ? ISC_TRUE : ISC_FALSE;
525*00b67f09SDavid van Moolenbroek
526*00b67f09SDavid van Moolenbroek isc_mem_free(mctx, nodestr);
527*00b67f09SDavid van Moolenbroek
528*00b67f09SDavid van Moolenbroek return (is_equal);
529*00b67f09SDavid van Moolenbroek }
530*00b67f09SDavid van Moolenbroek
531*00b67f09SDavid van Moolenbroek ATF_TC(rbt_insert);
ATF_TC_HEAD(rbt_insert,tc)532*00b67f09SDavid van Moolenbroek ATF_TC_HEAD(rbt_insert, tc) {
533*00b67f09SDavid van Moolenbroek atf_tc_set_md_var(tc, "descr", "Test insertion into a tree");
534*00b67f09SDavid van Moolenbroek }
ATF_TC_BODY(rbt_insert,tc)535*00b67f09SDavid van Moolenbroek ATF_TC_BODY(rbt_insert, tc) {
536*00b67f09SDavid van Moolenbroek isc_result_t result;
537*00b67f09SDavid van Moolenbroek test_context_t *ctx;
538*00b67f09SDavid van Moolenbroek dns_rbtnode_t *node;
539*00b67f09SDavid van Moolenbroek
540*00b67f09SDavid van Moolenbroek UNUSED(tc);
541*00b67f09SDavid van Moolenbroek
542*00b67f09SDavid van Moolenbroek isc_mem_debugging = ISC_MEM_DEBUGRECORD;
543*00b67f09SDavid van Moolenbroek
544*00b67f09SDavid van Moolenbroek result = dns_test_begin(NULL, ISC_TRUE);
545*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
546*00b67f09SDavid van Moolenbroek
547*00b67f09SDavid van Moolenbroek ctx = test_context_setup();
548*00b67f09SDavid van Moolenbroek
549*00b67f09SDavid van Moolenbroek /* Check node count before beginning. */
550*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
551*00b67f09SDavid van Moolenbroek
552*00b67f09SDavid van Moolenbroek /* Try to insert a node that already exists. */
553*00b67f09SDavid van Moolenbroek node = NULL;
554*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "d.e.f", &node);
555*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_EXISTS);
556*00b67f09SDavid van Moolenbroek
557*00b67f09SDavid van Moolenbroek /* Node count must not have changed. */
558*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(15, dns_rbt_nodecount(ctx->rbt));
559*00b67f09SDavid van Moolenbroek
560*00b67f09SDavid van Moolenbroek /* Try to insert a node that doesn't exist. */
561*00b67f09SDavid van Moolenbroek node = NULL;
562*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "0", &node);
563*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
564*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(compare_labelsequences(node, "0"), ISC_TRUE);
565*00b67f09SDavid van Moolenbroek
566*00b67f09SDavid van Moolenbroek /* Node count must have increased. */
567*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(16, dns_rbt_nodecount(ctx->rbt));
568*00b67f09SDavid van Moolenbroek
569*00b67f09SDavid van Moolenbroek /* Another. */
570*00b67f09SDavid van Moolenbroek node = NULL;
571*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "example.com", &node);
572*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
573*00b67f09SDavid van Moolenbroek ATF_REQUIRE(node != NULL);
574*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(node->data, NULL);
575*00b67f09SDavid van Moolenbroek
576*00b67f09SDavid van Moolenbroek /* Node count must have increased. */
577*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(17, dns_rbt_nodecount(ctx->rbt));
578*00b67f09SDavid van Moolenbroek
579*00b67f09SDavid van Moolenbroek /* Re-adding it should return EXISTS */
580*00b67f09SDavid van Moolenbroek node = NULL;
581*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "example.com", &node);
582*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_EXISTS);
583*00b67f09SDavid van Moolenbroek
584*00b67f09SDavid van Moolenbroek /* Node count must not have changed. */
585*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(17, dns_rbt_nodecount(ctx->rbt));
586*00b67f09SDavid van Moolenbroek
587*00b67f09SDavid van Moolenbroek /* Fission the node d.e.f */
588*00b67f09SDavid van Moolenbroek node = NULL;
589*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "k.e.f", &node);
590*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
591*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(compare_labelsequences(node, "k"), ISC_TRUE);
592*00b67f09SDavid van Moolenbroek
593*00b67f09SDavid van Moolenbroek /* Node count must have incremented twice ("d.e.f" fissioned to
594*00b67f09SDavid van Moolenbroek * "d" and "e.f", and the newly added "k").
595*00b67f09SDavid van Moolenbroek */
596*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(19, dns_rbt_nodecount(ctx->rbt));
597*00b67f09SDavid van Moolenbroek
598*00b67f09SDavid van Moolenbroek /* Fission the node "g.h" */
599*00b67f09SDavid van Moolenbroek node = NULL;
600*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "h", &node);
601*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
602*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(compare_labelsequences(node, "h"), ISC_TRUE);
603*00b67f09SDavid van Moolenbroek
604*00b67f09SDavid van Moolenbroek /* Node count must have incremented ("g.h" fissioned to "g" and
605*00b67f09SDavid van Moolenbroek * "h").
606*00b67f09SDavid van Moolenbroek */
607*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(20, dns_rbt_nodecount(ctx->rbt));
608*00b67f09SDavid van Moolenbroek
609*00b67f09SDavid van Moolenbroek /* Add child domains */
610*00b67f09SDavid van Moolenbroek
611*00b67f09SDavid van Moolenbroek node = NULL;
612*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "m.p.w.y.d.e.f", &node);
613*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
614*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(compare_labelsequences(node, "m"), ISC_TRUE);
615*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(21, dns_rbt_nodecount(ctx->rbt));
616*00b67f09SDavid van Moolenbroek
617*00b67f09SDavid van Moolenbroek node = NULL;
618*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "n.p.w.y.d.e.f", &node);
619*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
620*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(compare_labelsequences(node, "n"), ISC_TRUE);
621*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(22, dns_rbt_nodecount(ctx->rbt));
622*00b67f09SDavid van Moolenbroek
623*00b67f09SDavid van Moolenbroek node = NULL;
624*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "l.a", &node);
625*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
626*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(compare_labelsequences(node, "l"), ISC_TRUE);
627*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(23, dns_rbt_nodecount(ctx->rbt));
628*00b67f09SDavid van Moolenbroek
629*00b67f09SDavid van Moolenbroek node = NULL;
630*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "r.d.e.f", &node);
631*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
632*00b67f09SDavid van Moolenbroek node = NULL;
633*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "s.d.e.f", &node);
634*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
635*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(25, dns_rbt_nodecount(ctx->rbt));
636*00b67f09SDavid van Moolenbroek
637*00b67f09SDavid van Moolenbroek node = NULL;
638*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "h.w.y.d.e.f", &node);
639*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
640*00b67f09SDavid van Moolenbroek
641*00b67f09SDavid van Moolenbroek /* Add more nodes one by one to cover left and right rotation
642*00b67f09SDavid van Moolenbroek * functions.
643*00b67f09SDavid van Moolenbroek */
644*00b67f09SDavid van Moolenbroek node = NULL;
645*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "f", &node);
646*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
647*00b67f09SDavid van Moolenbroek
648*00b67f09SDavid van Moolenbroek node = NULL;
649*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "m", &node);
650*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
651*00b67f09SDavid van Moolenbroek
652*00b67f09SDavid van Moolenbroek node = NULL;
653*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "nm", &node);
654*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
655*00b67f09SDavid van Moolenbroek
656*00b67f09SDavid van Moolenbroek node = NULL;
657*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "om", &node);
658*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
659*00b67f09SDavid van Moolenbroek
660*00b67f09SDavid van Moolenbroek node = NULL;
661*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "k", &node);
662*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
663*00b67f09SDavid van Moolenbroek
664*00b67f09SDavid van Moolenbroek node = NULL;
665*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "l", &node);
666*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
667*00b67f09SDavid van Moolenbroek
668*00b67f09SDavid van Moolenbroek node = NULL;
669*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "fe", &node);
670*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
671*00b67f09SDavid van Moolenbroek
672*00b67f09SDavid van Moolenbroek node = NULL;
673*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "ge", &node);
674*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
675*00b67f09SDavid van Moolenbroek
676*00b67f09SDavid van Moolenbroek node = NULL;
677*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "i", &node);
678*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
679*00b67f09SDavid van Moolenbroek
680*00b67f09SDavid van Moolenbroek node = NULL;
681*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "ae", &node);
682*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
683*00b67f09SDavid van Moolenbroek
684*00b67f09SDavid van Moolenbroek node = NULL;
685*00b67f09SDavid van Moolenbroek result = insert_helper(ctx->rbt, "n", &node);
686*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
687*00b67f09SDavid van Moolenbroek
688*00b67f09SDavid van Moolenbroek test_context_teardown(ctx);
689*00b67f09SDavid van Moolenbroek
690*00b67f09SDavid van Moolenbroek dns_test_end();
691*00b67f09SDavid van Moolenbroek }
692*00b67f09SDavid van Moolenbroek
693*00b67f09SDavid van Moolenbroek ATF_TC(rbt_remove);
ATF_TC_HEAD(rbt_remove,tc)694*00b67f09SDavid van Moolenbroek ATF_TC_HEAD(rbt_remove, tc) {
695*00b67f09SDavid van Moolenbroek atf_tc_set_md_var(tc, "descr", "Test removal from a tree");
696*00b67f09SDavid van Moolenbroek }
ATF_TC_BODY(rbt_remove,tc)697*00b67f09SDavid van Moolenbroek ATF_TC_BODY(rbt_remove, tc) {
698*00b67f09SDavid van Moolenbroek /*
699*00b67f09SDavid van Moolenbroek * This testcase checks that after node removal, the
700*00b67f09SDavid van Moolenbroek * binary-search tree is valid and all nodes that are supposed
701*00b67f09SDavid van Moolenbroek * to exist are present in the correct order. It mainly tests
702*00b67f09SDavid van Moolenbroek * DomainTree as a BST, and not particularly as a red-black
703*00b67f09SDavid van Moolenbroek * tree. This test checks node deletion when upper nodes have
704*00b67f09SDavid van Moolenbroek * data.
705*00b67f09SDavid van Moolenbroek */
706*00b67f09SDavid van Moolenbroek isc_result_t result;
707*00b67f09SDavid van Moolenbroek size_t j;
708*00b67f09SDavid van Moolenbroek
709*00b67f09SDavid van Moolenbroek UNUSED(tc);
710*00b67f09SDavid van Moolenbroek
711*00b67f09SDavid van Moolenbroek isc_mem_debugging = ISC_MEM_DEBUGRECORD;
712*00b67f09SDavid van Moolenbroek
713*00b67f09SDavid van Moolenbroek result = dns_test_begin(NULL, ISC_TRUE);
714*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
715*00b67f09SDavid van Moolenbroek
716*00b67f09SDavid van Moolenbroek /*
717*00b67f09SDavid van Moolenbroek * Delete single nodes and check if the rest of the nodes exist.
718*00b67f09SDavid van Moolenbroek */
719*00b67f09SDavid van Moolenbroek for (j = 0; j < ordered_names_count; j++) {
720*00b67f09SDavid van Moolenbroek dns_rbt_t *mytree = NULL;
721*00b67f09SDavid van Moolenbroek dns_rbtnode_t *node;
722*00b67f09SDavid van Moolenbroek size_t i;
723*00b67f09SDavid van Moolenbroek size_t *n;
724*00b67f09SDavid van Moolenbroek isc_boolean_t tree_ok;
725*00b67f09SDavid van Moolenbroek dns_rbtnodechain_t chain;
726*00b67f09SDavid van Moolenbroek size_t start_node;
727*00b67f09SDavid van Moolenbroek
728*00b67f09SDavid van Moolenbroek /* Create a tree. */
729*00b67f09SDavid van Moolenbroek result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
730*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
731*00b67f09SDavid van Moolenbroek
732*00b67f09SDavid van Moolenbroek /* Insert test data into the tree. */
733*00b67f09SDavid van Moolenbroek for (i = 0; i < domain_names_count; i++) {
734*00b67f09SDavid van Moolenbroek node = NULL;
735*00b67f09SDavid van Moolenbroek result = insert_helper(mytree, domain_names[i], &node);
736*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
737*00b67f09SDavid van Moolenbroek }
738*00b67f09SDavid van Moolenbroek
739*00b67f09SDavid van Moolenbroek /* Check that all names exist in order. */
740*00b67f09SDavid van Moolenbroek for (i = 0; i < ordered_names_count; i++) {
741*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
742*00b67f09SDavid van Moolenbroek dns_name_t *name;
743*00b67f09SDavid van Moolenbroek
744*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[i], &fname);
745*00b67f09SDavid van Moolenbroek
746*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
747*00b67f09SDavid van Moolenbroek node = NULL;
748*00b67f09SDavid van Moolenbroek result = dns_rbt_findnode(mytree, name, NULL,
749*00b67f09SDavid van Moolenbroek &node, NULL,
750*00b67f09SDavid van Moolenbroek DNS_RBTFIND_EMPTYDATA,
751*00b67f09SDavid van Moolenbroek NULL, NULL);
752*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
753*00b67f09SDavid van Moolenbroek
754*00b67f09SDavid van Moolenbroek /* Add node data */
755*00b67f09SDavid van Moolenbroek ATF_REQUIRE(node != NULL);
756*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(node->data, NULL);
757*00b67f09SDavid van Moolenbroek
758*00b67f09SDavid van Moolenbroek n = isc_mem_get(mctx, sizeof(size_t));
759*00b67f09SDavid van Moolenbroek *n = i;
760*00b67f09SDavid van Moolenbroek
761*00b67f09SDavid van Moolenbroek node->data = n;
762*00b67f09SDavid van Moolenbroek }
763*00b67f09SDavid van Moolenbroek
764*00b67f09SDavid van Moolenbroek /* Now, delete the j'th node from the tree. */
765*00b67f09SDavid van Moolenbroek {
766*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
767*00b67f09SDavid van Moolenbroek dns_name_t *name;
768*00b67f09SDavid van Moolenbroek
769*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[j], &fname);
770*00b67f09SDavid van Moolenbroek
771*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
772*00b67f09SDavid van Moolenbroek
773*00b67f09SDavid van Moolenbroek result = dns_rbt_deletename(mytree, name, ISC_FALSE);
774*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
775*00b67f09SDavid van Moolenbroek }
776*00b67f09SDavid van Moolenbroek
777*00b67f09SDavid van Moolenbroek /* Check RB tree properties. */
778*00b67f09SDavid van Moolenbroek tree_ok = dns__rbt_checkproperties(mytree);
779*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(tree_ok, ISC_TRUE);
780*00b67f09SDavid van Moolenbroek
781*00b67f09SDavid van Moolenbroek dns_rbtnodechain_init(&chain, mctx);
782*00b67f09SDavid van Moolenbroek
783*00b67f09SDavid van Moolenbroek /* Now, walk through nodes in order. */
784*00b67f09SDavid van Moolenbroek if (j == 0) {
785*00b67f09SDavid van Moolenbroek /*
786*00b67f09SDavid van Moolenbroek * Node for ordered_names[0] was already deleted
787*00b67f09SDavid van Moolenbroek * above. We start from node 1.
788*00b67f09SDavid van Moolenbroek */
789*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
790*00b67f09SDavid van Moolenbroek dns_name_t *name;
791*00b67f09SDavid van Moolenbroek
792*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[0], &fname);
793*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
794*00b67f09SDavid van Moolenbroek node = NULL;
795*00b67f09SDavid van Moolenbroek result = dns_rbt_findnode(mytree, name, NULL,
796*00b67f09SDavid van Moolenbroek &node, NULL,
797*00b67f09SDavid van Moolenbroek 0,
798*00b67f09SDavid van Moolenbroek NULL, NULL);
799*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_NOTFOUND);
800*00b67f09SDavid van Moolenbroek
801*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[1], &fname);
802*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
803*00b67f09SDavid van Moolenbroek node = NULL;
804*00b67f09SDavid van Moolenbroek result = dns_rbt_findnode(mytree, name, NULL,
805*00b67f09SDavid van Moolenbroek &node, &chain,
806*00b67f09SDavid van Moolenbroek 0,
807*00b67f09SDavid van Moolenbroek NULL, NULL);
808*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
809*00b67f09SDavid van Moolenbroek start_node = 1;
810*00b67f09SDavid van Moolenbroek } else {
811*00b67f09SDavid van Moolenbroek /* Start from node 0. */
812*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
813*00b67f09SDavid van Moolenbroek dns_name_t *name;
814*00b67f09SDavid van Moolenbroek
815*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[0], &fname);
816*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
817*00b67f09SDavid van Moolenbroek node = NULL;
818*00b67f09SDavid van Moolenbroek result = dns_rbt_findnode(mytree, name, NULL,
819*00b67f09SDavid van Moolenbroek &node, &chain,
820*00b67f09SDavid van Moolenbroek 0,
821*00b67f09SDavid van Moolenbroek NULL, NULL);
822*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
823*00b67f09SDavid van Moolenbroek start_node = 0;
824*00b67f09SDavid van Moolenbroek }
825*00b67f09SDavid van Moolenbroek
826*00b67f09SDavid van Moolenbroek /*
827*00b67f09SDavid van Moolenbroek * node and chain have been set by the code above at
828*00b67f09SDavid van Moolenbroek * this point.
829*00b67f09SDavid van Moolenbroek */
830*00b67f09SDavid van Moolenbroek for (i = start_node; i < ordered_names_count; i++) {
831*00b67f09SDavid van Moolenbroek dns_fixedname_t fname_j, fname_i;
832*00b67f09SDavid van Moolenbroek dns_name_t *name_j, *name_i;
833*00b67f09SDavid van Moolenbroek
834*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[j], &fname_j);
835*00b67f09SDavid van Moolenbroek name_j = dns_fixedname_name(&fname_j);
836*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[i], &fname_i);
837*00b67f09SDavid van Moolenbroek name_i = dns_fixedname_name(&fname_i);
838*00b67f09SDavid van Moolenbroek
839*00b67f09SDavid van Moolenbroek if (dns_name_equal(name_i, name_j)) {
840*00b67f09SDavid van Moolenbroek /*
841*00b67f09SDavid van Moolenbroek * This may be true for the last node if
842*00b67f09SDavid van Moolenbroek * we seek ahead in the loop using
843*00b67f09SDavid van Moolenbroek * dns_rbtnodechain_next() below.
844*00b67f09SDavid van Moolenbroek */
845*00b67f09SDavid van Moolenbroek if (node == NULL) {
846*00b67f09SDavid van Moolenbroek break;
847*00b67f09SDavid van Moolenbroek }
848*00b67f09SDavid van Moolenbroek
849*00b67f09SDavid van Moolenbroek /* All ordered nodes have data
850*00b67f09SDavid van Moolenbroek * initially. If any node is empty, it
851*00b67f09SDavid van Moolenbroek * means it was removed, but an empty
852*00b67f09SDavid van Moolenbroek * node exists because it is a
853*00b67f09SDavid van Moolenbroek * super-domain. Just skip it.
854*00b67f09SDavid van Moolenbroek */
855*00b67f09SDavid van Moolenbroek if (node->data == NULL) {
856*00b67f09SDavid van Moolenbroek result = dns_rbtnodechain_next(&chain,
857*00b67f09SDavid van Moolenbroek NULL,
858*00b67f09SDavid van Moolenbroek NULL);
859*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE) {
860*00b67f09SDavid van Moolenbroek node = NULL;
861*00b67f09SDavid van Moolenbroek } else {
862*00b67f09SDavid van Moolenbroek dns_rbtnodechain_current(&chain,
863*00b67f09SDavid van Moolenbroek NULL,
864*00b67f09SDavid van Moolenbroek NULL,
865*00b67f09SDavid van Moolenbroek &node);
866*00b67f09SDavid van Moolenbroek }
867*00b67f09SDavid van Moolenbroek }
868*00b67f09SDavid van Moolenbroek continue;
869*00b67f09SDavid van Moolenbroek }
870*00b67f09SDavid van Moolenbroek
871*00b67f09SDavid van Moolenbroek ATF_REQUIRE(node != NULL);
872*00b67f09SDavid van Moolenbroek
873*00b67f09SDavid van Moolenbroek n = (size_t *) node->data;
874*00b67f09SDavid van Moolenbroek if (n != NULL) {
875*00b67f09SDavid van Moolenbroek /* printf("n=%zu, i=%zu\n", *n, i); */
876*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(*n, i);
877*00b67f09SDavid van Moolenbroek }
878*00b67f09SDavid van Moolenbroek
879*00b67f09SDavid van Moolenbroek result = dns_rbtnodechain_next(&chain, NULL, NULL);
880*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE) {
881*00b67f09SDavid van Moolenbroek node = NULL;
882*00b67f09SDavid van Moolenbroek } else {
883*00b67f09SDavid van Moolenbroek dns_rbtnodechain_current(&chain, NULL, NULL,
884*00b67f09SDavid van Moolenbroek &node);
885*00b67f09SDavid van Moolenbroek }
886*00b67f09SDavid van Moolenbroek }
887*00b67f09SDavid van Moolenbroek
888*00b67f09SDavid van Moolenbroek /* We should have reached the end of the tree. */
889*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(node, NULL);
890*00b67f09SDavid van Moolenbroek
891*00b67f09SDavid van Moolenbroek dns_rbt_destroy(&mytree);
892*00b67f09SDavid van Moolenbroek }
893*00b67f09SDavid van Moolenbroek
894*00b67f09SDavid van Moolenbroek dns_test_end();
895*00b67f09SDavid van Moolenbroek }
896*00b67f09SDavid van Moolenbroek
897*00b67f09SDavid van Moolenbroek ATF_TC(rbt_remove_empty);
ATF_TC_HEAD(rbt_remove_empty,tc)898*00b67f09SDavid van Moolenbroek ATF_TC_HEAD(rbt_remove_empty, tc) {
899*00b67f09SDavid van Moolenbroek atf_tc_set_md_var(tc, "descr",
900*00b67f09SDavid van Moolenbroek "Test removal from a tree when "
901*00b67f09SDavid van Moolenbroek "upper nodes are empty");
902*00b67f09SDavid van Moolenbroek }
ATF_TC_BODY(rbt_remove_empty,tc)903*00b67f09SDavid van Moolenbroek ATF_TC_BODY(rbt_remove_empty, tc) {
904*00b67f09SDavid van Moolenbroek /*
905*00b67f09SDavid van Moolenbroek * This test is similar to the rbt_remove test, but checks node
906*00b67f09SDavid van Moolenbroek * deletion when upper nodes are empty.
907*00b67f09SDavid van Moolenbroek */
908*00b67f09SDavid van Moolenbroek isc_result_t result;
909*00b67f09SDavid van Moolenbroek size_t j;
910*00b67f09SDavid van Moolenbroek
911*00b67f09SDavid van Moolenbroek UNUSED(tc);
912*00b67f09SDavid van Moolenbroek
913*00b67f09SDavid van Moolenbroek isc_mem_debugging = ISC_MEM_DEBUGRECORD;
914*00b67f09SDavid van Moolenbroek
915*00b67f09SDavid van Moolenbroek result = dns_test_begin(NULL, ISC_TRUE);
916*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
917*00b67f09SDavid van Moolenbroek
918*00b67f09SDavid van Moolenbroek /*
919*00b67f09SDavid van Moolenbroek * Delete single nodes and check if the rest of the nodes exist.
920*00b67f09SDavid van Moolenbroek */
921*00b67f09SDavid van Moolenbroek for (j = 0; j < ordered_names_count; j++) {
922*00b67f09SDavid van Moolenbroek dns_rbt_t *mytree = NULL;
923*00b67f09SDavid van Moolenbroek dns_rbtnode_t *node;
924*00b67f09SDavid van Moolenbroek size_t i;
925*00b67f09SDavid van Moolenbroek isc_boolean_t tree_ok;
926*00b67f09SDavid van Moolenbroek dns_rbtnodechain_t chain;
927*00b67f09SDavid van Moolenbroek size_t start_node;
928*00b67f09SDavid van Moolenbroek
929*00b67f09SDavid van Moolenbroek /* Create a tree. */
930*00b67f09SDavid van Moolenbroek result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
931*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
932*00b67f09SDavid van Moolenbroek
933*00b67f09SDavid van Moolenbroek /* Insert test data into the tree. */
934*00b67f09SDavid van Moolenbroek for (i = 0; i < domain_names_count; i++) {
935*00b67f09SDavid van Moolenbroek node = NULL;
936*00b67f09SDavid van Moolenbroek result = insert_helper(mytree, domain_names[i], &node);
937*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
938*00b67f09SDavid van Moolenbroek }
939*00b67f09SDavid van Moolenbroek
940*00b67f09SDavid van Moolenbroek /* Check that all names exist in order. */
941*00b67f09SDavid van Moolenbroek for (i = 0; i < ordered_names_count; i++) {
942*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
943*00b67f09SDavid van Moolenbroek dns_name_t *name;
944*00b67f09SDavid van Moolenbroek
945*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[i], &fname);
946*00b67f09SDavid van Moolenbroek
947*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
948*00b67f09SDavid van Moolenbroek node = NULL;
949*00b67f09SDavid van Moolenbroek result = dns_rbt_findnode(mytree, name, NULL,
950*00b67f09SDavid van Moolenbroek &node, NULL,
951*00b67f09SDavid van Moolenbroek DNS_RBTFIND_EMPTYDATA,
952*00b67f09SDavid van Moolenbroek NULL, NULL);
953*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
954*00b67f09SDavid van Moolenbroek
955*00b67f09SDavid van Moolenbroek /* Check that node data is empty */
956*00b67f09SDavid van Moolenbroek ATF_REQUIRE(node != NULL);
957*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(node->data, NULL);
958*00b67f09SDavid van Moolenbroek }
959*00b67f09SDavid van Moolenbroek
960*00b67f09SDavid van Moolenbroek /* Now, delete the j'th node from the tree. */
961*00b67f09SDavid van Moolenbroek {
962*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
963*00b67f09SDavid van Moolenbroek dns_name_t *name;
964*00b67f09SDavid van Moolenbroek
965*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[j], &fname);
966*00b67f09SDavid van Moolenbroek
967*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
968*00b67f09SDavid van Moolenbroek
969*00b67f09SDavid van Moolenbroek node = NULL;
970*00b67f09SDavid van Moolenbroek result = dns_rbt_findnode(mytree, name, NULL, &node,
971*00b67f09SDavid van Moolenbroek NULL, DNS_RBTFIND_EMPTYDATA,
972*00b67f09SDavid van Moolenbroek NULL, NULL);
973*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
974*00b67f09SDavid van Moolenbroek
975*00b67f09SDavid van Moolenbroek result = dns_rbt_deletenode(mytree, node, ISC_FALSE);
976*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
977*00b67f09SDavid van Moolenbroek }
978*00b67f09SDavid van Moolenbroek
979*00b67f09SDavid van Moolenbroek /* Check RB tree properties. */
980*00b67f09SDavid van Moolenbroek tree_ok = dns__rbt_checkproperties(mytree);
981*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(tree_ok, ISC_TRUE);
982*00b67f09SDavid van Moolenbroek
983*00b67f09SDavid van Moolenbroek dns_rbtnodechain_init(&chain, mctx);
984*00b67f09SDavid van Moolenbroek
985*00b67f09SDavid van Moolenbroek /* Now, walk through nodes in order. */
986*00b67f09SDavid van Moolenbroek if (j == 0) {
987*00b67f09SDavid van Moolenbroek /*
988*00b67f09SDavid van Moolenbroek * Node for ordered_names[0] was already deleted
989*00b67f09SDavid van Moolenbroek * above. We start from node 1.
990*00b67f09SDavid van Moolenbroek */
991*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
992*00b67f09SDavid van Moolenbroek dns_name_t *name;
993*00b67f09SDavid van Moolenbroek
994*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[0], &fname);
995*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
996*00b67f09SDavid van Moolenbroek node = NULL;
997*00b67f09SDavid van Moolenbroek result = dns_rbt_findnode(mytree, name, NULL,
998*00b67f09SDavid van Moolenbroek &node, NULL,
999*00b67f09SDavid van Moolenbroek DNS_RBTFIND_EMPTYDATA,
1000*00b67f09SDavid van Moolenbroek NULL, NULL);
1001*00b67f09SDavid van Moolenbroek ATF_CHECK(result != ISC_R_SUCCESS);
1002*00b67f09SDavid van Moolenbroek
1003*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[1], &fname);
1004*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
1005*00b67f09SDavid van Moolenbroek node = NULL;
1006*00b67f09SDavid van Moolenbroek result = dns_rbt_findnode(mytree, name, NULL,
1007*00b67f09SDavid van Moolenbroek &node, &chain,
1008*00b67f09SDavid van Moolenbroek DNS_RBTFIND_EMPTYDATA,
1009*00b67f09SDavid van Moolenbroek NULL, NULL);
1010*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
1011*00b67f09SDavid van Moolenbroek start_node = 1;
1012*00b67f09SDavid van Moolenbroek } else {
1013*00b67f09SDavid van Moolenbroek /* Start from node 0. */
1014*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
1015*00b67f09SDavid van Moolenbroek dns_name_t *name;
1016*00b67f09SDavid van Moolenbroek
1017*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[0], &fname);
1018*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
1019*00b67f09SDavid van Moolenbroek node = NULL;
1020*00b67f09SDavid van Moolenbroek result = dns_rbt_findnode(mytree, name, NULL,
1021*00b67f09SDavid van Moolenbroek &node, &chain,
1022*00b67f09SDavid van Moolenbroek DNS_RBTFIND_EMPTYDATA,
1023*00b67f09SDavid van Moolenbroek NULL, NULL);
1024*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
1025*00b67f09SDavid van Moolenbroek start_node = 0;
1026*00b67f09SDavid van Moolenbroek }
1027*00b67f09SDavid van Moolenbroek
1028*00b67f09SDavid van Moolenbroek /*
1029*00b67f09SDavid van Moolenbroek * node and chain have been set by the code above at
1030*00b67f09SDavid van Moolenbroek * this point.
1031*00b67f09SDavid van Moolenbroek */
1032*00b67f09SDavid van Moolenbroek for (i = start_node; i < ordered_names_count; i++) {
1033*00b67f09SDavid van Moolenbroek dns_fixedname_t fntmp1, fntmp2;
1034*00b67f09SDavid van Moolenbroek dns_name_t *ntmp1, *ntmp2;
1035*00b67f09SDavid van Moolenbroek dns_fixedname_t fname_j, fname_i;
1036*00b67f09SDavid van Moolenbroek dns_name_t *name_j, *name_i;
1037*00b67f09SDavid van Moolenbroek
1038*00b67f09SDavid van Moolenbroek build_name_from_str("j.z.d.e.f", &fntmp1);
1039*00b67f09SDavid van Moolenbroek ntmp1 = dns_fixedname_name(&fntmp1);
1040*00b67f09SDavid van Moolenbroek build_name_from_str("z.d.e.f", &fntmp2);
1041*00b67f09SDavid van Moolenbroek ntmp2 = dns_fixedname_name(&fntmp2);
1042*00b67f09SDavid van Moolenbroek
1043*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[j], &fname_j);
1044*00b67f09SDavid van Moolenbroek name_j = dns_fixedname_name(&fname_j);
1045*00b67f09SDavid van Moolenbroek build_name_from_str(ordered_names[i], &fname_i);
1046*00b67f09SDavid van Moolenbroek name_i = dns_fixedname_name(&fname_i);
1047*00b67f09SDavid van Moolenbroek
1048*00b67f09SDavid van Moolenbroek if (dns_name_equal(name_j, ntmp1) &&
1049*00b67f09SDavid van Moolenbroek dns_name_equal(name_j, ntmp2))
1050*00b67f09SDavid van Moolenbroek {
1051*00b67f09SDavid van Moolenbroek /*
1052*00b67f09SDavid van Moolenbroek * The only special case in the
1053*00b67f09SDavid van Moolenbroek * tree. Here, "z.d.e.f" will not exist
1054*00b67f09SDavid van Moolenbroek * as it would have been removed during
1055*00b67f09SDavid van Moolenbroek * removal of "j.z.d.e.f".
1056*00b67f09SDavid van Moolenbroek */
1057*00b67f09SDavid van Moolenbroek continue;
1058*00b67f09SDavid van Moolenbroek }
1059*00b67f09SDavid van Moolenbroek
1060*00b67f09SDavid van Moolenbroek if (dns_name_equal(name_i, name_j)) {
1061*00b67f09SDavid van Moolenbroek dns_fixedname_t fntmp3, fntmp4, fntmp5, fntmp6;
1062*00b67f09SDavid van Moolenbroek dns_name_t *ntmp3, *ntmp4, *ntmp5, *ntmp6;
1063*00b67f09SDavid van Moolenbroek
1064*00b67f09SDavid van Moolenbroek /*
1065*00b67f09SDavid van Moolenbroek * This may be true for the last node if
1066*00b67f09SDavid van Moolenbroek * we seek ahead in the loop using
1067*00b67f09SDavid van Moolenbroek * dns_rbtnodechain_next() below.
1068*00b67f09SDavid van Moolenbroek */
1069*00b67f09SDavid van Moolenbroek if (node == NULL) {
1070*00b67f09SDavid van Moolenbroek break;
1071*00b67f09SDavid van Moolenbroek }
1072*00b67f09SDavid van Moolenbroek
1073*00b67f09SDavid van Moolenbroek /*
1074*00b67f09SDavid van Moolenbroek * All ordered nodes are empty
1075*00b67f09SDavid van Moolenbroek * initially. If an empty removed node
1076*00b67f09SDavid van Moolenbroek * exists because it is a super-domain,
1077*00b67f09SDavid van Moolenbroek * just skip it.
1078*00b67f09SDavid van Moolenbroek */
1079*00b67f09SDavid van Moolenbroek build_name_from_str("d.e.f", &fntmp3);
1080*00b67f09SDavid van Moolenbroek ntmp3 = dns_fixedname_name(&fntmp3);
1081*00b67f09SDavid van Moolenbroek build_name_from_str("w.y.d.e.f", &fntmp4);
1082*00b67f09SDavid van Moolenbroek ntmp4 = dns_fixedname_name(&fntmp4);
1083*00b67f09SDavid van Moolenbroek build_name_from_str("z.d.e.f", &fntmp5);
1084*00b67f09SDavid van Moolenbroek ntmp5 = dns_fixedname_name(&fntmp5);
1085*00b67f09SDavid van Moolenbroek build_name_from_str("g.h", &fntmp6);
1086*00b67f09SDavid van Moolenbroek ntmp6 = dns_fixedname_name(&fntmp6);
1087*00b67f09SDavid van Moolenbroek
1088*00b67f09SDavid van Moolenbroek if (dns_name_equal(name_j, ntmp3) ||
1089*00b67f09SDavid van Moolenbroek dns_name_equal(name_j, ntmp4) ||
1090*00b67f09SDavid van Moolenbroek dns_name_equal(name_j, ntmp5) ||
1091*00b67f09SDavid van Moolenbroek dns_name_equal(name_j, ntmp6))
1092*00b67f09SDavid van Moolenbroek {
1093*00b67f09SDavid van Moolenbroek result = dns_rbtnodechain_next(&chain,
1094*00b67f09SDavid van Moolenbroek NULL,
1095*00b67f09SDavid van Moolenbroek NULL);
1096*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE) {
1097*00b67f09SDavid van Moolenbroek node = NULL;
1098*00b67f09SDavid van Moolenbroek } else {
1099*00b67f09SDavid van Moolenbroek dns_rbtnodechain_current(&chain,
1100*00b67f09SDavid van Moolenbroek NULL,
1101*00b67f09SDavid van Moolenbroek NULL,
1102*00b67f09SDavid van Moolenbroek &node);
1103*00b67f09SDavid van Moolenbroek }
1104*00b67f09SDavid van Moolenbroek }
1105*00b67f09SDavid van Moolenbroek continue;
1106*00b67f09SDavid van Moolenbroek }
1107*00b67f09SDavid van Moolenbroek
1108*00b67f09SDavid van Moolenbroek ATF_REQUIRE(node != NULL);
1109*00b67f09SDavid van Moolenbroek
1110*00b67f09SDavid van Moolenbroek result = dns_rbtnodechain_next(&chain, NULL, NULL);
1111*00b67f09SDavid van Moolenbroek if (result == ISC_R_NOMORE) {
1112*00b67f09SDavid van Moolenbroek node = NULL;
1113*00b67f09SDavid van Moolenbroek } else {
1114*00b67f09SDavid van Moolenbroek dns_rbtnodechain_current(&chain, NULL, NULL,
1115*00b67f09SDavid van Moolenbroek &node);
1116*00b67f09SDavid van Moolenbroek }
1117*00b67f09SDavid van Moolenbroek }
1118*00b67f09SDavid van Moolenbroek
1119*00b67f09SDavid van Moolenbroek /* We should have reached the end of the tree. */
1120*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(node, NULL);
1121*00b67f09SDavid van Moolenbroek
1122*00b67f09SDavid van Moolenbroek dns_rbt_destroy(&mytree);
1123*00b67f09SDavid van Moolenbroek }
1124*00b67f09SDavid van Moolenbroek
1125*00b67f09SDavid van Moolenbroek dns_test_end();
1126*00b67f09SDavid van Moolenbroek }
1127*00b67f09SDavid van Moolenbroek
1128*00b67f09SDavid van Moolenbroek static void
insert_nodes(dns_rbt_t * mytree,char ** names,size_t * names_count,isc_uint32_t num_names)1129*00b67f09SDavid van Moolenbroek insert_nodes(dns_rbt_t *mytree, char **names,
1130*00b67f09SDavid van Moolenbroek size_t *names_count, isc_uint32_t num_names)
1131*00b67f09SDavid van Moolenbroek {
1132*00b67f09SDavid van Moolenbroek isc_uint32_t i;
1133*00b67f09SDavid van Moolenbroek
1134*00b67f09SDavid van Moolenbroek for (i = 0; i < num_names; i++) {
1135*00b67f09SDavid van Moolenbroek size_t *n;
1136*00b67f09SDavid van Moolenbroek char namebuf[34];
1137*00b67f09SDavid van Moolenbroek
1138*00b67f09SDavid van Moolenbroek n = isc_mem_get(mctx, sizeof(size_t));
1139*00b67f09SDavid van Moolenbroek *n = i; /* Unused value */
1140*00b67f09SDavid van Moolenbroek
1141*00b67f09SDavid van Moolenbroek while (1) {
1142*00b67f09SDavid van Moolenbroek int j;
1143*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
1144*00b67f09SDavid van Moolenbroek dns_name_t *name;
1145*00b67f09SDavid van Moolenbroek isc_result_t result;
1146*00b67f09SDavid van Moolenbroek
1147*00b67f09SDavid van Moolenbroek for (j = 0; j < 32; j++) {
1148*00b67f09SDavid van Moolenbroek isc_uint32_t v;
1149*00b67f09SDavid van Moolenbroek isc_random_get(&v);
1150*00b67f09SDavid van Moolenbroek namebuf[j] = 'a' + (v % 26);
1151*00b67f09SDavid van Moolenbroek }
1152*00b67f09SDavid van Moolenbroek namebuf[32] = '.';
1153*00b67f09SDavid van Moolenbroek namebuf[33] = 0;
1154*00b67f09SDavid van Moolenbroek
1155*00b67f09SDavid van Moolenbroek build_name_from_str(namebuf, &fname);
1156*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
1157*00b67f09SDavid van Moolenbroek
1158*00b67f09SDavid van Moolenbroek result = dns_rbt_addname(mytree, name, n);
1159*00b67f09SDavid van Moolenbroek if (result == ISC_R_SUCCESS) {
1160*00b67f09SDavid van Moolenbroek names[*names_count] = isc_mem_strdup(mctx,
1161*00b67f09SDavid van Moolenbroek namebuf);
1162*00b67f09SDavid van Moolenbroek *names_count += 1;
1163*00b67f09SDavid van Moolenbroek break;
1164*00b67f09SDavid van Moolenbroek }
1165*00b67f09SDavid van Moolenbroek }
1166*00b67f09SDavid van Moolenbroek }
1167*00b67f09SDavid van Moolenbroek }
1168*00b67f09SDavid van Moolenbroek
1169*00b67f09SDavid van Moolenbroek static void
remove_nodes(dns_rbt_t * mytree,char ** names,size_t * names_count,isc_uint32_t num_names)1170*00b67f09SDavid van Moolenbroek remove_nodes(dns_rbt_t *mytree, char **names,
1171*00b67f09SDavid van Moolenbroek size_t *names_count, isc_uint32_t num_names)
1172*00b67f09SDavid van Moolenbroek {
1173*00b67f09SDavid van Moolenbroek isc_uint32_t i;
1174*00b67f09SDavid van Moolenbroek
1175*00b67f09SDavid van Moolenbroek UNUSED(mytree);
1176*00b67f09SDavid van Moolenbroek
1177*00b67f09SDavid van Moolenbroek for (i = 0; i < num_names; i++) {
1178*00b67f09SDavid van Moolenbroek isc_uint32_t node;
1179*00b67f09SDavid van Moolenbroek dns_fixedname_t fname;
1180*00b67f09SDavid van Moolenbroek dns_name_t *name;
1181*00b67f09SDavid van Moolenbroek isc_result_t result;
1182*00b67f09SDavid van Moolenbroek
1183*00b67f09SDavid van Moolenbroek isc_random_get(&node);
1184*00b67f09SDavid van Moolenbroek
1185*00b67f09SDavid van Moolenbroek node %= *names_count;
1186*00b67f09SDavid van Moolenbroek
1187*00b67f09SDavid van Moolenbroek build_name_from_str(names[node], &fname);
1188*00b67f09SDavid van Moolenbroek name = dns_fixedname_name(&fname);
1189*00b67f09SDavid van Moolenbroek
1190*00b67f09SDavid van Moolenbroek result = dns_rbt_deletename(mytree, name, ISC_FALSE);
1191*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
1192*00b67f09SDavid van Moolenbroek
1193*00b67f09SDavid van Moolenbroek isc_mem_free(mctx, names[node]);
1194*00b67f09SDavid van Moolenbroek if (*names_count > 0) {
1195*00b67f09SDavid van Moolenbroek names[node] = names[*names_count - 1];
1196*00b67f09SDavid van Moolenbroek names[*names_count - 1] = NULL;
1197*00b67f09SDavid van Moolenbroek *names_count -= 1;
1198*00b67f09SDavid van Moolenbroek }
1199*00b67f09SDavid van Moolenbroek }
1200*00b67f09SDavid van Moolenbroek }
1201*00b67f09SDavid van Moolenbroek
1202*00b67f09SDavid van Moolenbroek static void
check_tree(dns_rbt_t * mytree,char ** names,size_t names_count)1203*00b67f09SDavid van Moolenbroek check_tree(dns_rbt_t *mytree, char **names, size_t names_count) {
1204*00b67f09SDavid van Moolenbroek isc_boolean_t tree_ok;
1205*00b67f09SDavid van Moolenbroek
1206*00b67f09SDavid van Moolenbroek UNUSED(names);
1207*00b67f09SDavid van Moolenbroek
1208*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(names_count + 1, dns_rbt_nodecount(mytree));
1209*00b67f09SDavid van Moolenbroek
1210*00b67f09SDavid van Moolenbroek /*
1211*00b67f09SDavid van Moolenbroek * The distance from each node to its sub-tree root must be less
1212*00b67f09SDavid van Moolenbroek * than 2 * log_2(1024).
1213*00b67f09SDavid van Moolenbroek */
1214*00b67f09SDavid van Moolenbroek ATF_CHECK((2 * 10) >= dns__rbt_getheight(mytree));
1215*00b67f09SDavid van Moolenbroek
1216*00b67f09SDavid van Moolenbroek /* Also check RB tree properties */
1217*00b67f09SDavid van Moolenbroek tree_ok = dns__rbt_checkproperties(mytree);
1218*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(tree_ok, ISC_TRUE);
1219*00b67f09SDavid van Moolenbroek }
1220*00b67f09SDavid van Moolenbroek
1221*00b67f09SDavid van Moolenbroek ATF_TC(rbt_insert_and_remove);
ATF_TC_HEAD(rbt_insert_and_remove,tc)1222*00b67f09SDavid van Moolenbroek ATF_TC_HEAD(rbt_insert_and_remove, tc) {
1223*00b67f09SDavid van Moolenbroek atf_tc_set_md_var(tc, "descr",
1224*00b67f09SDavid van Moolenbroek "Test insert and remove in a loop");
1225*00b67f09SDavid van Moolenbroek }
ATF_TC_BODY(rbt_insert_and_remove,tc)1226*00b67f09SDavid van Moolenbroek ATF_TC_BODY(rbt_insert_and_remove, tc) {
1227*00b67f09SDavid van Moolenbroek /*
1228*00b67f09SDavid van Moolenbroek * What is the best way to test our red-black tree code? It is
1229*00b67f09SDavid van Moolenbroek * not a good method to test every case handled in the actual
1230*00b67f09SDavid van Moolenbroek * code itself. This is because our approach itself may be
1231*00b67f09SDavid van Moolenbroek * incorrect.
1232*00b67f09SDavid van Moolenbroek *
1233*00b67f09SDavid van Moolenbroek * We test our code at the interface level here by exercising the
1234*00b67f09SDavid van Moolenbroek * tree randomly multiple times, checking that red-black tree
1235*00b67f09SDavid van Moolenbroek * properties are valid, and all the nodes that are supposed to be
1236*00b67f09SDavid van Moolenbroek * in the tree exist and are in order.
1237*00b67f09SDavid van Moolenbroek *
1238*00b67f09SDavid van Moolenbroek * NOTE: These tests are run within a single tree level in the
1239*00b67f09SDavid van Moolenbroek * forest. The number of nodes in the tree level doesn't grow
1240*00b67f09SDavid van Moolenbroek * over 1024.
1241*00b67f09SDavid van Moolenbroek */
1242*00b67f09SDavid van Moolenbroek isc_result_t result;
1243*00b67f09SDavid van Moolenbroek dns_rbt_t *mytree = NULL;
1244*00b67f09SDavid van Moolenbroek /*
1245*00b67f09SDavid van Moolenbroek * We use an array for storing names instead of a set
1246*00b67f09SDavid van Moolenbroek * structure. It's slow, but works and is good enough for tests.
1247*00b67f09SDavid van Moolenbroek */
1248*00b67f09SDavid van Moolenbroek char *names[1024];
1249*00b67f09SDavid van Moolenbroek size_t names_count;
1250*00b67f09SDavid van Moolenbroek int i;
1251*00b67f09SDavid van Moolenbroek
1252*00b67f09SDavid van Moolenbroek UNUSED(tc);
1253*00b67f09SDavid van Moolenbroek
1254*00b67f09SDavid van Moolenbroek isc_mem_debugging = ISC_MEM_DEBUGRECORD;
1255*00b67f09SDavid van Moolenbroek
1256*00b67f09SDavid van Moolenbroek result = dns_test_begin(NULL, ISC_TRUE);
1257*00b67f09SDavid van Moolenbroek ATF_CHECK_EQ(result, ISC_R_SUCCESS);
1258*00b67f09SDavid van Moolenbroek
1259*00b67f09SDavid van Moolenbroek result = dns_rbt_create(mctx, delete_data, NULL, &mytree);
1260*00b67f09SDavid van Moolenbroek ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
1261*00b67f09SDavid van Moolenbroek
1262*00b67f09SDavid van Moolenbroek memset(names, 0, sizeof(names));
1263*00b67f09SDavid van Moolenbroek names_count = 0;
1264*00b67f09SDavid van Moolenbroek
1265*00b67f09SDavid van Moolenbroek /* Repeat the insert/remove test some 4096 times */
1266*00b67f09SDavid van Moolenbroek for (i = 0; i < 4096; i++) {
1267*00b67f09SDavid van Moolenbroek isc_uint32_t num_names;
1268*00b67f09SDavid van Moolenbroek isc_random_get(&num_names);
1269*00b67f09SDavid van Moolenbroek
1270*00b67f09SDavid van Moolenbroek if (names_count < 1024) {
1271*00b67f09SDavid van Moolenbroek num_names %= 1024 - names_count;
1272*00b67f09SDavid van Moolenbroek num_names++;
1273*00b67f09SDavid van Moolenbroek } else {
1274*00b67f09SDavid van Moolenbroek num_names = 0;
1275*00b67f09SDavid van Moolenbroek }
1276*00b67f09SDavid van Moolenbroek
1277*00b67f09SDavid van Moolenbroek insert_nodes(mytree, names, &names_count, num_names);
1278*00b67f09SDavid van Moolenbroek check_tree(mytree, names, names_count);
1279*00b67f09SDavid van Moolenbroek
1280*00b67f09SDavid van Moolenbroek isc_random_get(&num_names);
1281*00b67f09SDavid van Moolenbroek if (names_count > 0) {
1282*00b67f09SDavid van Moolenbroek num_names %= names_count;
1283*00b67f09SDavid van Moolenbroek num_names++;
1284*00b67f09SDavid van Moolenbroek } else {
1285*00b67f09SDavid van Moolenbroek num_names = 0;
1286*00b67f09SDavid van Moolenbroek }
1287*00b67f09SDavid van Moolenbroek
1288*00b67f09SDavid van Moolenbroek remove_nodes(mytree, names, &names_count, num_names);
1289*00b67f09SDavid van Moolenbroek check_tree(mytree, names, names_count);
1290*00b67f09SDavid van Moolenbroek }
1291*00b67f09SDavid van Moolenbroek
1292*00b67f09SDavid van Moolenbroek /* Remove the rest of the nodes */
1293*00b67f09SDavid van Moolenbroek remove_nodes(mytree, names, &names_count, names_count);
1294*00b67f09SDavid van Moolenbroek check_tree(mytree, names, names_count);
1295*00b67f09SDavid van Moolenbroek
1296*00b67f09SDavid van Moolenbroek for (i = 0; i < 1024; i++) {
1297*00b67f09SDavid van Moolenbroek if (names[i] != NULL) {
1298*00b67f09SDavid van Moolenbroek isc_mem_free(mctx, names[i]);
1299*00b67f09SDavid van Moolenbroek }
1300*00b67f09SDavid van Moolenbroek }
1301*00b67f09SDavid van Moolenbroek
1302*00b67f09SDavid van Moolenbroek dns_rbt_destroy(&mytree);
1303*00b67f09SDavid van Moolenbroek
1304*00b67f09SDavid van Moolenbroek dns_test_end();
1305*00b67f09SDavid van Moolenbroek }
1306*00b67f09SDavid van Moolenbroek
1307*00b67f09SDavid van Moolenbroek /*
1308*00b67f09SDavid van Moolenbroek * Main
1309*00b67f09SDavid van Moolenbroek */
ATF_TP_ADD_TCS(tp)1310*00b67f09SDavid van Moolenbroek ATF_TP_ADD_TCS(tp) {
1311*00b67f09SDavid van Moolenbroek ATF_TP_ADD_TC(tp, rbt_create);
1312*00b67f09SDavid van Moolenbroek ATF_TP_ADD_TC(tp, rbt_nodecount);
1313*00b67f09SDavid van Moolenbroek ATF_TP_ADD_TC(tp, rbtnode_get_distance);
1314*00b67f09SDavid van Moolenbroek ATF_TP_ADD_TC(tp, rbt_check_distance_random);
1315*00b67f09SDavid van Moolenbroek ATF_TP_ADD_TC(tp, rbt_check_distance_ordered);
1316*00b67f09SDavid van Moolenbroek ATF_TP_ADD_TC(tp, rbt_insert);
1317*00b67f09SDavid van Moolenbroek ATF_TP_ADD_TC(tp, rbt_remove);
1318*00b67f09SDavid van Moolenbroek ATF_TP_ADD_TC(tp, rbt_remove_empty);
1319*00b67f09SDavid van Moolenbroek ATF_TP_ADD_TC(tp, rbt_insert_and_remove);
1320*00b67f09SDavid van Moolenbroek
1321*00b67f09SDavid van Moolenbroek return (atf_no_error());
1322*00b67f09SDavid van Moolenbroek }
1323