2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-02 15:45:25 +00:00

convert rbt_serialize_test

This commit is contained in:
Joey
2018-11-14 20:23:32 +08:00
committed by Evan Hunt
parent 1b48e710d5
commit dfd90dbb82

View File

@@ -10,17 +10,23 @@
*/ */
/* ! \file */
#include <config.h> #include <config.h>
#include <atf-c.h> #if HAVE_CMOCKA
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdlib.h>
#include <inttypes.h> #include <inttypes.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include <sys/mman.h> #include <sys/mman.h>
#define UNIT_TESTING
#include <cmocka.h>
#include <isc/mem.h> #include <isc/mem.h>
#include <isc/print.h> #include <isc/print.h>
#include <isc/random.h> #include <isc/random.h>
@@ -55,6 +61,27 @@
#define MAP_FILE 0 #define MAP_FILE 0
#endif #endif
static int
_setup(void **state) {
isc_result_t result;
UNUSED(state);
result = dns_test_begin(NULL, false);
assert_int_equal(result, ISC_R_SUCCESS);
return (0);
}
static int
_teardown(void **state) {
UNUSED(state);
dns_test_end();
return (0);
}
typedef struct data_holder { typedef struct data_holder {
int len; int len;
const char *data; const char *data;
@@ -117,8 +144,9 @@ write_data(FILE *file, unsigned char *datap, void *arg, uint64_t *crc) {
(data->len != 0 && data->data != NULL)); (data->len != 0 && data->data != NULL));
result = isc_stdio_tell(file, &where); result = isc_stdio_tell(file, &where);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS) {
return (result); return (result);
}
temp = *data; temp = *data;
temp.data = (data->len == 0 temp.data = (data->len == 0
@@ -127,22 +155,22 @@ write_data(FILE *file, unsigned char *datap, void *arg, uint64_t *crc) {
isc_crc64_update(crc, (void *)&temp, sizeof(temp)); isc_crc64_update(crc, (void *)&temp, sizeof(temp));
ret = fwrite(&temp, sizeof(data_holder_t), 1, file); ret = fwrite(&temp, sizeof(data_holder_t), 1, file);
if (ret != 1) if (ret != 1) {
return (ISC_R_FAILURE); return (ISC_R_FAILURE);
}
if (data->len > 0) { if (data->len > 0) {
isc_crc64_update(crc, (const void *)data->data, data->len); isc_crc64_update(crc, (const void *)data->data, data->len);
ret = fwrite(data->data, data->len, 1, file); ret = fwrite(data->data, data->len, 1, file);
if (ret != 1) if (ret != 1) {
return (ISC_R_FAILURE); return (ISC_R_FAILURE);
} }
}
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
static isc_result_t static isc_result_t
fix_data(dns_rbtnode_t *p, void *base, size_t max, void *arg, fix_data(dns_rbtnode_t *p, void *base, size_t max, void *arg, uint64_t *crc) {
uint64_t *crc)
{
data_holder_t *data = p->data; data_holder_t *data = p->data;
size_t size; size_t size;
@@ -154,31 +182,29 @@ fix_data(dns_rbtnode_t *p, void *base, size_t max, void *arg,
REQUIRE(p != NULL); REQUIRE(p != NULL);
if (data == NULL)
printf("fixing data: data NULL\n");
else
printf("fixing data: len %d, data %p\n", data->len, data->data);
if (data == NULL || if (data == NULL ||
(data->len == 0 && data->data != NULL) || (data->len == 0 && data->data != NULL) ||
(data->len != 0 && data->data == NULL)) (data->len != 0 && data->data == NULL))
{
return (ISC_R_INVALIDFILE); return (ISC_R_INVALIDFILE);
}
size = max - ((char *)p - (char *)base); size = max - ((char *)p - (char *)base);
if (data->len > (int) size || data->data > (const char *) max) { if (data->len > (int) size || data->data > (const char *) max) {
printf("data invalid\n");
return (ISC_R_INVALIDFILE); return (ISC_R_INVALIDFILE);
} }
isc_crc64_update(crc, (void *)data, sizeof(*data)); isc_crc64_update(crc, (void *)data, sizeof(*data));
data->data = (data->len == 0) data->data = NULL;
? NULL if (data->len != 0) {
: (char *)data + sizeof(data_holder_t); data->data = (char *)data + sizeof(data_holder_t);
}
if (data->len > 0) if (data->len > 0) {
isc_crc64_update(crc, (const void *)data->data, data->len); isc_crc64_update(crc, (const void *)data->data, data->len);
}
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
@@ -212,7 +238,7 @@ add_test_data(isc_mem_t *mymctx, dns_rbt_t *rbt) {
if (name != NULL) { if (name != NULL) {
result = dns_rbt_addname(rbt, name, &testdatap->data); result = dns_rbt_addname(rbt, name, &testdatap->data);
ATF_CHECK_STREQ(dns_result_totext(result), "success"); assert_int_equal(result, ISC_R_SUCCESS);
} }
testdatap++; testdatap++;
} }
@@ -254,25 +280,22 @@ check_test_data(dns_rbt_t *rbt) {
data = NULL; data = NULL;
result = dns_rbt_findname(rbt, name, 0, foundname, result = dns_rbt_findname(rbt, name, 0, foundname,
(void *) &data); (void *) &data);
ATF_CHECK_STREQ(dns_result_totext(result), "success"); assert_int_equal(result, ISC_R_SUCCESS);
testdatap++; testdatap++;
} }
} }
static void static void
data_printer(FILE *out, void *datap) data_printer(FILE *out, void *datap) {
{
data_holder_t *data = (data_holder_t *)datap; data_holder_t *data = (data_holder_t *)datap;
fprintf(out, "%d bytes, %s", data->len, data->data); fprintf(out, "%d bytes, %s", data->len, data->data);
} }
ATF_TC(serialize); /* Test writing an rbt to file */
ATF_TC_HEAD(serialize, tc) { static void
atf_tc_set_md_var(tc, "descr", "Test writing an rbt to file"); serialize_test(void **state) {
}
ATF_TC_BODY(serialize, tc) {
dns_rbt_t *rbt = NULL; dns_rbt_t *rbt = NULL;
isc_result_t result; isc_result_t result;
FILE *rbtfile = NULL; FILE *rbtfile = NULL;
@@ -282,14 +305,12 @@ ATF_TC_BODY(serialize, tc) {
off_t filesize = 0; off_t filesize = 0;
char *base; char *base;
UNUSED(tc); UNUSED(state);
isc_mem_debugging = ISC_MEM_DEBUGRECORD; isc_mem_debugging = ISC_MEM_DEBUGRECORD;
result = dns_test_begin(NULL, true);
ATF_CHECK_STREQ(dns_result_totext(result), "success");
result = dns_rbt_create(mctx, delete_data, NULL, &rbt); result = dns_rbt_create(mctx, delete_data, NULL, &rbt);
ATF_CHECK_STREQ(dns_result_totext(result), "success"); assert_int_equal(result, ISC_R_SUCCESS);
add_test_data(mctx, rbt); add_test_data(mctx, rbt);
@@ -298,28 +319,22 @@ ATF_TC_BODY(serialize, tc) {
/* /*
* Serialize the tree. * Serialize the tree.
*/ */
printf("serialization begins.\n");
rbtfile = fopen("./zone.bin", "w+b"); rbtfile = fopen("./zone.bin", "w+b");
ATF_REQUIRE(rbtfile != NULL); assert_non_null(rbtfile);
result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL, result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL,
&offset); &offset);
ATF_REQUIRE(result == ISC_R_SUCCESS); assert_true(result == ISC_R_SUCCESS);
dns_rbt_destroy(&rbt); dns_rbt_destroy(&rbt);
/* /*
* Deserialize the tree * Deserialize the tree.
*/
printf("deserialization begins.\n");
/*
* Map in the whole file in one go * Map in the whole file in one go
*/ */
fd = open("zone.bin", O_RDWR); fd = open("zone.bin", O_RDWR);
isc_file_getsizefd(fd, &filesize); isc_file_getsizefd(fd, &filesize);
base = mmap(NULL, filesize, base = mmap(NULL, filesize, PROT_READ|PROT_WRITE,
PROT_READ|PROT_WRITE,
MAP_FILE|MAP_PRIVATE, fd, 0); MAP_FILE|MAP_PRIVATE, fd, 0);
ATF_REQUIRE(base != NULL && base != MAP_FAILED); assert_true(base != NULL && base != MAP_FAILED);
close(fd); close(fd);
result = dns_rbt_deserialize_tree(base, filesize, 0, mctx, result = dns_rbt_deserialize_tree(base, filesize, 0, mctx,
@@ -327,9 +342,10 @@ ATF_TC_BODY(serialize, tc) {
NULL, &rbt_deserialized); NULL, &rbt_deserialized);
/* Test to make sure we have a valid tree */ /* Test to make sure we have a valid tree */
ATF_REQUIRE(result == ISC_R_SUCCESS); assert_true(result == ISC_R_SUCCESS);
if (rbt_deserialized == NULL) if (rbt_deserialized == NULL) {
atf_tc_fail("deserialized rbt is null!"); /* Abort execution. */ fail_msg("deserialized rbt is null!"); /* Abort execution. */
}
check_test_data(rbt_deserialized); check_test_data(rbt_deserialized);
@@ -338,14 +354,11 @@ ATF_TC_BODY(serialize, tc) {
dns_rbt_destroy(&rbt_deserialized); dns_rbt_destroy(&rbt_deserialized);
munmap(base, filesize); munmap(base, filesize);
unlink("zone.bin"); unlink("zone.bin");
dns_test_end();
} }
ATF_TC(deserialize_corrupt); /* Test reading a corrupt map file */
ATF_TC_HEAD(deserialize_corrupt, tc) { static void
atf_tc_set_md_var(tc, "descr", "Test reading a corrupt map file"); deserialize_corrupt_test(void **state) {
}
ATF_TC_BODY(deserialize_corrupt, tc) {
dns_rbt_t *rbt = NULL; dns_rbt_t *rbt = NULL;
isc_result_t result; isc_result_t result;
FILE *rbtfile = NULL; FILE *rbtfile = NULL;
@@ -355,23 +368,20 @@ ATF_TC_BODY(deserialize_corrupt, tc) {
char *base, *p, *q; char *base, *p, *q;
int i; int i;
UNUSED(tc); UNUSED(state);
isc_mem_debugging = ISC_MEM_DEBUGRECORD; isc_mem_debugging = ISC_MEM_DEBUGRECORD;
result = dns_test_begin(NULL, true);
ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
/* Set up map file */ /* Set up map file */
result = dns_rbt_create(mctx, delete_data, NULL, &rbt); result = dns_rbt_create(mctx, delete_data, NULL, &rbt);
ATF_CHECK_EQ(result, ISC_R_SUCCESS); assert_int_equal(result, ISC_R_SUCCESS);
add_test_data(mctx, rbt); add_test_data(mctx, rbt);
rbtfile = fopen("./zone.bin", "w+b"); rbtfile = fopen("./zone.bin", "w+b");
ATF_REQUIRE(rbtfile != NULL); assert_non_null(rbtfile);
result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL, result = dns_rbt_serialize_tree(rbtfile, rbt, write_data, NULL,
&offset); &offset);
ATF_REQUIRE(result == ISC_R_SUCCESS); assert_true(result == ISC_R_SUCCESS);
dns_rbt_destroy(&rbt); dns_rbt_destroy(&rbt);
/* Read back with random fuzzing */ /* Read back with random fuzzing */
@@ -380,10 +390,9 @@ ATF_TC_BODY(deserialize_corrupt, tc) {
fd = open("zone.bin", O_RDWR); fd = open("zone.bin", O_RDWR);
isc_file_getsizefd(fd, &filesize); isc_file_getsizefd(fd, &filesize);
base = mmap(NULL, filesize, base = mmap(NULL, filesize, PROT_READ|PROT_WRITE,
PROT_READ|PROT_WRITE,
MAP_FILE|MAP_PRIVATE, fd, 0); MAP_FILE|MAP_PRIVATE, fd, 0);
ATF_REQUIRE(base != NULL && base != MAP_FAILED); assert_true(base != NULL && base != MAP_FAILED);
close(fd); close(fd);
/* Randomly fuzz a portion of the memory */ /* Randomly fuzz a portion of the memory */
@@ -398,54 +407,64 @@ ATF_TC_BODY(deserialize_corrupt, tc) {
delete_data, NULL, delete_data, NULL,
fix_data, NULL, fix_data, NULL,
NULL, &rbt_deserialized); NULL, &rbt_deserialized);
printf("%d: %s\n", i, isc_result_totext(result));
/* Test to make sure we have a valid tree */ /* Test to make sure we have a valid tree */
ATF_REQUIRE(result == ISC_R_SUCCESS || assert_true(result == ISC_R_SUCCESS ||
result == ISC_R_INVALIDFILE); result == ISC_R_INVALIDFILE);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS) {
ATF_REQUIRE(rbt_deserialized == NULL); assert_null(rbt_deserialized);
}
if (rbt_deserialized != NULL) if (rbt_deserialized != NULL) {
dns_rbt_destroy(&rbt_deserialized); dns_rbt_destroy(&rbt_deserialized);
}
munmap(base, filesize); munmap(base, filesize);
} }
unlink("zone.bin"); unlink("zone.bin");
dns_test_end();
} }
/* Test the dns_rbt_serialize_align() function */
static void
serialize_align_test(void **state) {
UNUSED(state);
ATF_TC(serialize_align); assert_true(dns_rbt_serialize_align(0) == 0);
ATF_TC_HEAD(serialize_align, tc) { assert_true(dns_rbt_serialize_align(1) == 8);
atf_tc_set_md_var(tc, "descr", assert_true(dns_rbt_serialize_align(2) == 8);
"Test the dns_rbt_serialize_align() function."); assert_true(dns_rbt_serialize_align(3) == 8);
} assert_true(dns_rbt_serialize_align(4) == 8);
ATF_TC_BODY(serialize_align, tc) { assert_true(dns_rbt_serialize_align(5) == 8);
UNUSED(tc); assert_true(dns_rbt_serialize_align(6) == 8);
assert_true(dns_rbt_serialize_align(7) == 8);
ATF_CHECK(dns_rbt_serialize_align(0) == 0); assert_true(dns_rbt_serialize_align(8) == 8);
ATF_CHECK(dns_rbt_serialize_align(1) == 8); assert_true(dns_rbt_serialize_align(9) == 16);
ATF_CHECK(dns_rbt_serialize_align(2) == 8); assert_true(dns_rbt_serialize_align(0xff) == 0x100);
ATF_CHECK(dns_rbt_serialize_align(3) == 8); assert_true(dns_rbt_serialize_align(0x301) == 0x308);
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);
} }
/* int
* Main main(void) {
*/ const struct CMUnitTest tests[] = {
ATF_TP_ADD_TCS(tp) { cmocka_unit_test_setup_teardown(serialize_test,
ATF_TP_ADD_TC(tp, serialize); _setup, _teardown),
ATF_TP_ADD_TC(tp, deserialize_corrupt); cmocka_unit_test_setup_teardown(deserialize_corrupt_test,
ATF_TP_ADD_TC(tp, serialize_align); _setup, _teardown),
cmocka_unit_test(serialize_align_test),
};
return (atf_no_error()); return (cmocka_run_group_tests(tests, NULL, NULL));
} }
#else /* HAVE_CMOCKA */
#include <stdio.h>
int
main(void) {
printf("1..0 # Skipped: cmocka not available\n");
return (0);
}
#endif