rbt_test.c 8.76 KB
Newer Older
1
/*
Tinderbox User's avatar
Tinderbox User committed
2
 * Copyright (C) 2012, 2013  Internet Systems Consortium, Inc. ("ISC")
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

/* $Id: rbt_test.c,v 1.1.14.8 2012/02/10 16:24:37 ckb Exp $ */

/* ! \file */

#include <config.h>
#include <atf-c.h>
#include <isc/mem.h>
#include <isc/string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

29
30
31
32
#ifdef HAVE_INTTYPES_H
#include <inttypes.h> /* uintptr_t */
#endif

33
34
35
36
#include <dns/rbt.h>
#include <dns/fixedname.h>
#include <dns/result.h>
#include <dns/compress.h>
37
#include "dnstest.h"
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

#include <isc/app.h>
#include <isc/buffer.h>
#include <isc/entropy.h>
#include <isc/file.h>
#include <isc/hash.h>
#include <isc/mem.h>
#include <isc/os.h>
#include <isc/string.h>
#include <isc/socket.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>

#include <dns/log.h>
#include <dns/name.h>
#include <dns/result.h>

#include <dst/dst.h>

typedef struct data_holder {
Tinderbox User's avatar
Tinderbox User committed
59
	int len;
60
61
62
63
64
65
66
67
68
69
70
	const char *data;
} data_holder_t;

typedef struct rbt_testdata {
	const char *name;
	size_t name_len;
	data_holder_t data;
} rbt_testdata_t;

#define DATA_ITEM(name) { (name), sizeof(name) - 1, { sizeof(name), (name) } }

Tinderbox User's avatar
Tinderbox User committed
71
rbt_testdata_t testdata[] = {
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
	DATA_ITEM("first.com."),
	DATA_ITEM("one.net."),
	DATA_ITEM("two.com."),
	DATA_ITEM("three.org."),
	DATA_ITEM("asdf.com."),
	DATA_ITEM("ghjkl.com."),
	DATA_ITEM("1.edu."),
	DATA_ITEM("2.edu."),
	DATA_ITEM("3.edu."),
	DATA_ITEM("123.edu."),
	DATA_ITEM("1236.com."),
	DATA_ITEM("and_so_forth.com."),
	DATA_ITEM("thisisalongname.com."),
	DATA_ITEM("a.b."),
	DATA_ITEM("test.net."),
	DATA_ITEM("whoknows.org."),
	DATA_ITEM("blargh.com."),
	DATA_ITEM("www.joe.com."),
	DATA_ITEM("test.com."),
	DATA_ITEM("isc.org."),
	DATA_ITEM("uiop.mil."),
	DATA_ITEM("last.fm."),
	{ NULL, 0, { 0, NULL } }
};

static void
delete_data(void *data, void *arg) {
	UNUSED(arg);
	UNUSED(data);
}

static isc_result_t
write_data(FILE *file, unsigned char *datap, isc_uint32_t serial) {
Tinderbox User's avatar
Tinderbox User committed
105
106
	size_t ret = 0;
	data_holder_t *data = (data_holder_t *)datap;
107
	data_holder_t temp;
108
	uintptr_t where = ftell(file);
109
110

	UNUSED(serial);
Tinderbox User's avatar
Tinderbox User committed
111

112
113
114
	REQUIRE(data != NULL);
	REQUIRE((data->len == 0 && data->data == NULL) ||
		(data->len != 0 && data->data != NULL));
Tinderbox User's avatar
Tinderbox User committed
115

116
	temp = *data;
Tinderbox User's avatar
Tinderbox User committed
117
	temp.data = (data->len == 0
118
119
120
		     ? NULL
		     : (char *)(where + sizeof(data_holder_t)));

Tinderbox User's avatar
Tinderbox User committed
121
	ret = fwrite(&temp, sizeof(data_holder_t), 1, file);
Mark Andrews's avatar
Mark Andrews committed
122
123
124
	if (ret != 1)
		return (ISC_R_FAILURE);
	if (data->len > 0) {
125
		ret = fwrite(data->data, data->len, 1, file);
Mark Andrews's avatar
Mark Andrews committed
126
127
128
		if (ret != 1)
			return (ISC_R_FAILURE);
	}
129

Tinderbox User's avatar
Tinderbox User committed
130
	return (ISC_R_SUCCESS);
131
132
133
134
}

static void
fix_data(dns_rbtnode_t *p) {
Tinderbox User's avatar
Tinderbox User committed
135
136
	data_holder_t *data = p->data;

137
138
139
	REQUIRE(data != NULL);
	REQUIRE((data->len == 0 && data->data == NULL) ||
		(data->len != 0 && data->data != NULL));
Tinderbox User's avatar
Tinderbox User committed
140

141
	printf("fixing data: len %d, data %p\n", data->len, data->data);
Tinderbox User's avatar
Tinderbox User committed
142
143

	data->data = (data->len == 0)
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
		? NULL
		: (char *)data + sizeof(data_holder_t);
}

/*
 * Load test data into the RBT.
 */
static void
add_test_data(isc_mem_t *mctx, dns_rbt_t *rbt)
{
	char buffer[1024];
	isc_buffer_t b;
	isc_result_t result;
	dns_fixedname_t fname;
	dns_name_t *name;
	dns_compress_t cctx;
Tinderbox User's avatar
Tinderbox User committed
160
	rbt_testdata_t *testdatap = testdata;
161
162

	dns_compress_init(&cctx, -1, mctx);
Tinderbox User's avatar
Tinderbox User committed
163
164

	while (testdatap->name != NULL && testdatap->data.data != NULL) {
165
		memcpy(buffer, testdatap->name, testdatap->name_len);
Tinderbox User's avatar
Tinderbox User committed
166

167
168
169
170
171
172
173
174
175
		isc_buffer_init(&b, buffer, testdatap->name_len);
		isc_buffer_add(&b, testdatap->name_len);
		dns_fixedname_init(&fname);
		name = dns_fixedname_name(&fname);
		result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
		if (result != ISC_R_SUCCESS) {
			testdatap++;
			continue;
		}
Tinderbox User's avatar
Tinderbox User committed
176

177
178
179
180
181
182
183
		if (name != NULL) {
			result = dns_rbt_addname(rbt, name, &testdatap->data);
			ATF_CHECK_STREQ(dns_result_totext(result), "success");
		}
		testdatap++;
	}

Tinderbox User's avatar
Tinderbox User committed
184
	dns_compress_invalidate(&cctx);
185
186
187
188
189
190
191
192
193
194
195
196
}

/*
 * Walk the tree and ensure that all the test nodes are present.
 */
static void
check_test_data(dns_rbt_t *rbt)
{
	char buffer[1024];
	char *arg;
	dns_fixedname_t fname;
	dns_fixedname_t fixed;
Tinderbox User's avatar
Tinderbox User committed
197
198
199
200
	dns_name_t *name;
	isc_buffer_t b;
	data_holder_t *data;
	isc_result_t result;
201
202
	dns_name_t *foundname;
	rbt_testdata_t *testdatap = testdata;
Tinderbox User's avatar
Tinderbox User committed
203

204
205
	dns_fixedname_init(&fixed);
	foundname = dns_fixedname_name(&fixed);
Tinderbox User's avatar
Tinderbox User committed
206
207

	while (testdatap->name != NULL && testdatap->data.data != NULL) {
208
209
210
211
212
213
214
215
216
217
218
219
		memcpy(buffer, testdatap->name, testdatap->name_len + 1);
		arg = buffer;

		isc_buffer_init(&b, arg, testdatap->name_len);
		isc_buffer_add(&b, testdatap->name_len);
		dns_fixedname_init(&fname);
		name = dns_fixedname_name(&fname);
		result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
		if (result != ISC_R_SUCCESS) {
			testdatap++;
			continue;
		}
Tinderbox User's avatar
Tinderbox User committed
220

221
222
223
224
		data = NULL;
		result = dns_rbt_findname(rbt, name, 0, foundname,
					  (void *) &data);
		ATF_CHECK_STREQ(dns_result_totext(result), "success");
Tinderbox User's avatar
Tinderbox User committed
225

226
227
228
229
230
231
232
233
		testdatap++;
	}
}

static void
data_printer(FILE *out, void *datap)
{
	data_holder_t *data = (data_holder_t *)datap;
Tinderbox User's avatar
Tinderbox User committed
234

235
236
237
238
239
240
241
242
243
244
	fprintf(out, "%d bytes, %s", data->len, data->data);
}

ATF_TC(isc_rbt);
ATF_TC_HEAD(isc_rbt, tc) {
	atf_tc_set_md_var(tc, "descr", "Test the creation of an rbt");
}
ATF_TC_BODY(isc_rbt, tc) {
	dns_rbt_t *rbt = NULL;
	isc_result_t result;
Tinderbox User's avatar
Tinderbox User committed
245

246
247
248
	UNUSED(tc);

	isc_mem_debugging = ISC_MEM_DEBUGRECORD;
Tinderbox User's avatar
Tinderbox User committed
249

250
251
252
253
254
255
	result = dns_test_begin(NULL, ISC_TRUE);
	ATF_CHECK_STREQ(dns_result_totext(result), "success");
	result = dns_rbt_create(mctx, delete_data, NULL, &rbt);
	ATF_CHECK_STREQ(dns_result_totext(result), "success");

	add_test_data(mctx, rbt);
Tinderbox User's avatar
Tinderbox User committed
256

257
258
259
	check_test_data(rbt);

	dns_rbt_printall(rbt, data_printer);
Tinderbox User's avatar
Tinderbox User committed
260

261
	dns_rbt_destroy(&rbt);
Tinderbox User's avatar
Tinderbox User committed
262

263
264
265
266
267
268
269
270
271
272
273
274
	dns_test_end();
}

ATF_TC(isc_serialize_rbt);
ATF_TC_HEAD(isc_serialize_rbt, tc) {
	atf_tc_set_md_var(tc, "descr", "Test writing an rbt to file");
}
ATF_TC_BODY(isc_serialize_rbt, tc) {
	dns_rbt_t *rbt = NULL;
	isc_result_t result;
	FILE *rbtfile = NULL;
	dns_rbt_t *rbt_deserialized = NULL;
Mark Andrews's avatar
Mark Andrews committed
275
	long offset;
276
277
278
	int fd;
	off_t filesize = 0;
	char *base;
Tinderbox User's avatar
Tinderbox User committed
279

280
281
282
	UNUSED(tc);

	isc_mem_debugging = ISC_MEM_DEBUGRECORD;
Tinderbox User's avatar
Tinderbox User committed
283

284
285
286
287
	result = dns_test_begin(NULL, ISC_TRUE);
	ATF_CHECK_STREQ(dns_result_totext(result), "success");
	result = dns_rbt_create(mctx, delete_data, NULL, &rbt);
	ATF_CHECK_STREQ(dns_result_totext(result), "success");
Tinderbox User's avatar
Tinderbox User committed
288

289
	add_test_data(mctx, rbt);
Tinderbox User's avatar
Tinderbox User committed
290

291
292
293
294
295
296
297
298
	dns_rbt_printall(rbt, data_printer);

	/*
	 * Serialize the tree.
	 */
	printf("serialization begins.\n");
	rbtfile = fopen("./zone.bin", "w+b");
	ATF_REQUIRE(rbtfile != NULL);
Mark Andrews's avatar
Mark Andrews committed
299
	result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, 0, &offset);
300
301
	ATF_REQUIRE(result == ISC_R_SUCCESS);
	dns_rbt_destroy(&rbt);
Tinderbox User's avatar
Tinderbox User committed
302

303
304
305
306
307
308
309
310
311
312
313
314
315
316
	/*
	 * Deserialize the tree
	 */
	printf("deserialization begins.\n");

	/*
	 * Map in the whole file in one go
	 */
	fd = open("zone.bin", O_RDWR);
	isc_file_getsizefd(fd, &filesize);
	base = mmap(NULL, filesize,
		    PROT_READ|PROT_WRITE,
		    MAP_FILE|MAP_PRIVATE, fd, 0);
	ATF_REQUIRE(base != NULL && base != MAP_FAILED);
Tinderbox User's avatar
Tinderbox User committed
317

318
319
	result = dns_rbt_deserialize_tree(base, 0, mctx, delete_data, NULL,
					  fix_data, NULL, &rbt_deserialized);
Tinderbox User's avatar
Tinderbox User committed
320

321
322
323
	/* Test to make sure we have a valid tree */
	ATF_REQUIRE(result == ISC_R_SUCCESS);
	if (rbt_deserialized == NULL)
Tinderbox User's avatar
Tinderbox User committed
324
325
		atf_tc_fail("deserialized rbt is null!"); /* Abort execution. */

326
327
328
	check_test_data(rbt_deserialized);

	dns_rbt_printall(rbt_deserialized, data_printer);
Tinderbox User's avatar
Tinderbox User committed
329

330
331
332
333
334
335
336
337
338
339
340
341
	dns_rbt_destroy(&rbt_deserialized);
	munmap(base, filesize);
	unlink("zone.bin");
	dns_test_end();
}

ATF_TC(dns_rbt_serialize_align);
ATF_TC_HEAD(dns_rbt_serialize_align, tc) {
	atf_tc_set_md_var(tc, "descr", "Test the dns_rbt_serialize_align() function.");
}
ATF_TC_BODY(dns_rbt_serialize_align, tc) {
	UNUSED(tc);
Tinderbox User's avatar
Tinderbox User committed
342

343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
	ATF_CHECK(dns_rbt_serialize_align(0) == 0);
	ATF_CHECK(dns_rbt_serialize_align(1) == 8);
	ATF_CHECK(dns_rbt_serialize_align(2) == 8);
	ATF_CHECK(dns_rbt_serialize_align(3) == 8);
	ATF_CHECK(dns_rbt_serialize_align(4) == 8);
	ATF_CHECK(dns_rbt_serialize_align(5) == 8);
	ATF_CHECK(dns_rbt_serialize_align(6) == 8);
	ATF_CHECK(dns_rbt_serialize_align(7) == 8);
	ATF_CHECK(dns_rbt_serialize_align(8) == 8);
	ATF_CHECK(dns_rbt_serialize_align(9) == 16);
	ATF_CHECK(dns_rbt_serialize_align(0xff) == 0x100);
	ATF_CHECK(dns_rbt_serialize_align(0x301) == 0x308);
}

/*
 * Main
 */
ATF_TP_ADD_TCS(tp) {
	ATF_TP_ADD_TC(tp, isc_rbt);
	ATF_TP_ADD_TC(tp, isc_serialize_rbt);
	ATF_TP_ADD_TC(tp, dns_rbt_serialize_align);

	return (atf_no_error());
}