mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-15 22:09:31 -04:00
Instead of relying on unreliable order of execution of the library constructors and destructors, move them to individual binaries. The advantage is that the execution time and order will remain constant and will not depend on the dynamic load dependency solver. This requires more work, but that was mitigated by a simple requirement, any executable using libisc and libdns, must include <isc/lib.h> and <dns/lib.h> respectively (in this particular order). In turn, these two headers must not be included from within any library as they contain inlined functions marked with constructor/destructor attributes.
332 lines
12 KiB
C
332 lines
12 KiB
C
/*
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
*
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
* information regarding copyright ownership.
|
|
*/
|
|
|
|
#include <inttypes.h>
|
|
#include <sched.h> /* IWYU pragma: keep */
|
|
#include <setjmp.h>
|
|
#include <stdarg.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
#define UNIT_TESTING
|
|
#include <cmocka.h>
|
|
|
|
#include <isc/base64.h>
|
|
#include <isc/buffer.h>
|
|
#include <isc/lib.h>
|
|
#include <isc/md.h>
|
|
#include <isc/util.h>
|
|
|
|
#include <dns/fixedname.h>
|
|
#include <dns/lib.h>
|
|
#include <dns/name.h>
|
|
#include <dns/nametree.h>
|
|
|
|
#include <dst/dst.h>
|
|
|
|
#include <tests/dns.h>
|
|
|
|
dns_nametree_t *booltree = NULL;
|
|
dns_nametree_t *bitstree = NULL;
|
|
dns_nametree_t *counttree = NULL;
|
|
|
|
/*
|
|
* Test utilities. In general, these assume input parameters are valid
|
|
* (checking with assert_int_equal, thus aborting if not) and unlikely run time
|
|
* errors (such as memory allocation failure) won't happen. This helps keep
|
|
* the test code concise.
|
|
*/
|
|
|
|
/* Common setup: create trees of each type with a few keys */
|
|
static int
|
|
setup(void **state ISC_ATTR_UNUSED) {
|
|
dns_fixedname_t fn;
|
|
dns_name_t *name = dns_fixedname_name(&fn);
|
|
|
|
dns_nametree_create(mctx, DNS_NAMETREE_BOOL, "bool test", &booltree);
|
|
dns_nametree_create(mctx, DNS_NAMETREE_BITS, "bits test", &bitstree);
|
|
dns_nametree_create(mctx, DNS_NAMETREE_COUNT, "count test", &counttree);
|
|
|
|
/* Add a positive boolean node */
|
|
dns_test_namefromstring("example.com.", &fn);
|
|
assert_int_equal(dns_nametree_add(booltree, name, true), ISC_R_SUCCESS);
|
|
|
|
/* Add assorted bits to a bitfield node */
|
|
assert_int_equal(dns_nametree_add(bitstree, name, 1), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_add(bitstree, name, 9), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_add(bitstree, name, 53), ISC_R_SUCCESS);
|
|
|
|
/* Add negative boolean nodes with and without parents */
|
|
dns_test_namefromstring("negative.example.com.", &fn);
|
|
assert_int_equal(dns_nametree_add(booltree, name, false),
|
|
ISC_R_SUCCESS);
|
|
dns_test_namefromstring("negative.example.org.", &fn);
|
|
assert_int_equal(dns_nametree_add(booltree, name, false),
|
|
ISC_R_SUCCESS);
|
|
|
|
/* Add a bitfield node under a parent */
|
|
dns_test_namefromstring("sub.example.com.", &fn);
|
|
assert_int_equal(dns_nametree_add(bitstree, name, 2), ISC_R_SUCCESS);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
teardown(void **state ISC_ATTR_UNUSED) {
|
|
dns_nametree_detach(&booltree);
|
|
dns_nametree_detach(&bitstree);
|
|
dns_nametree_detach(&counttree);
|
|
rcu_barrier();
|
|
return 0;
|
|
}
|
|
|
|
ISC_RUN_TEST_IMPL(add_bool) {
|
|
dns_ntnode_t *node = NULL;
|
|
dns_fixedname_t fn;
|
|
dns_name_t *name = dns_fixedname_name(&fn);
|
|
|
|
/*
|
|
* Getting the node for example.com should succeed.
|
|
*/
|
|
dns_test_namefromstring("example.com.", &fn);
|
|
assert_int_equal(dns_nametree_find(booltree, name, &node),
|
|
ISC_R_SUCCESS);
|
|
dns_ntnode_detach(&node);
|
|
|
|
/*
|
|
* Try to add the same name. This should fail.
|
|
*/
|
|
assert_int_equal(dns_nametree_add(booltree, name, false), ISC_R_EXISTS);
|
|
assert_int_equal(dns_nametree_find(booltree, name, &node),
|
|
ISC_R_SUCCESS);
|
|
dns_ntnode_detach(&node);
|
|
|
|
/*
|
|
* Try to add a new name.
|
|
*/
|
|
dns_test_namefromstring("newname.com.", &fn);
|
|
assert_int_equal(dns_nametree_add(booltree, name, true), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_find(booltree, name, &node),
|
|
ISC_R_SUCCESS);
|
|
dns_ntnode_detach(&node);
|
|
}
|
|
|
|
ISC_RUN_TEST_IMPL(add_bits) {
|
|
dns_ntnode_t *node = NULL;
|
|
dns_fixedname_t fn;
|
|
dns_name_t *name = dns_fixedname_name(&fn);
|
|
|
|
/*
|
|
* Getting the node for example.com should succeed.
|
|
*/
|
|
dns_test_namefromstring("example.com.", &fn);
|
|
assert_int_equal(dns_nametree_find(booltree, name, &node),
|
|
ISC_R_SUCCESS);
|
|
dns_ntnode_detach(&node);
|
|
|
|
/*
|
|
* Try to add the same name. This should succeed.
|
|
*/
|
|
assert_int_equal(dns_nametree_add(bitstree, name, 1), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_add(bitstree, name, 2), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_add(bitstree, name, 3), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_find(booltree, name, &node),
|
|
ISC_R_SUCCESS);
|
|
dns_ntnode_detach(&node);
|
|
|
|
/*
|
|
* Try to add a new name.
|
|
*/
|
|
dns_test_namefromstring("newname.com.", &fn);
|
|
assert_int_equal(dns_nametree_add(booltree, name, true), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_find(booltree, name, &node),
|
|
ISC_R_SUCCESS);
|
|
dns_ntnode_detach(&node);
|
|
}
|
|
|
|
ISC_RUN_TEST_IMPL(add_count) {
|
|
dns_fixedname_t fn;
|
|
dns_name_t *name = dns_fixedname_name(&fn);
|
|
|
|
/* add a counter node five times */
|
|
dns_test_namefromstring("example.com.", &fn);
|
|
assert_int_equal(dns_nametree_add(counttree, name, 0), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_add(counttree, name, 0), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_add(counttree, name, 0), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_add(counttree, name, 0), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_add(counttree, name, 0), ISC_R_SUCCESS);
|
|
|
|
/* delete it five times, checking coverage each time */
|
|
assert_true(dns_nametree_covered(counttree, name, NULL, 0));
|
|
assert_int_equal(dns_nametree_delete(counttree, name), ISC_R_SUCCESS);
|
|
|
|
assert_true(dns_nametree_covered(counttree, name, NULL, 0));
|
|
assert_int_equal(dns_nametree_delete(counttree, name), ISC_R_SUCCESS);
|
|
|
|
assert_true(dns_nametree_covered(counttree, name, NULL, 0));
|
|
assert_int_equal(dns_nametree_delete(counttree, name), ISC_R_SUCCESS);
|
|
|
|
assert_true(dns_nametree_covered(counttree, name, NULL, 0));
|
|
assert_int_equal(dns_nametree_delete(counttree, name), ISC_R_SUCCESS);
|
|
|
|
assert_true(dns_nametree_covered(counttree, name, NULL, 0));
|
|
assert_int_equal(dns_nametree_delete(counttree, name), ISC_R_SUCCESS);
|
|
|
|
assert_false(dns_nametree_covered(counttree, name, NULL, 0));
|
|
assert_int_equal(dns_nametree_delete(counttree, name), ISC_R_NOTFOUND);
|
|
}
|
|
|
|
ISC_RUN_TEST_IMPL(covered_bool) {
|
|
dns_fixedname_t fn, fn2;
|
|
dns_name_t *name = dns_fixedname_initname(&fn);
|
|
dns_name_t *found = dns_fixedname_initname(&fn2);
|
|
char buf[DNS_NAME_FORMATSIZE];
|
|
const char *yesnames[] = { "example.com.", "sub.example.com.", NULL };
|
|
const char *nonames[] = { "whatever.com.", "negative.example.com.",
|
|
"example.org.", "negative.example.org.",
|
|
NULL };
|
|
|
|
for (const char **n = yesnames; *n != NULL; n++) {
|
|
dns_test_namefromstring(*n, &fn);
|
|
assert_true(dns_nametree_covered(booltree, name, NULL, 0));
|
|
}
|
|
for (const char **n = nonames; *n != NULL; n++) {
|
|
dns_test_namefromstring(*n, &fn);
|
|
assert_false(dns_nametree_covered(booltree, name, NULL, 0));
|
|
}
|
|
|
|
/* Check that the found name is as expected */
|
|
dns_test_namefromstring("other.example.com.", &fn);
|
|
assert_true(dns_nametree_covered(booltree, name, found, 0));
|
|
dns_name_format(found, buf, sizeof(buf));
|
|
assert_string_equal(buf, "example.com");
|
|
}
|
|
|
|
ISC_RUN_TEST_IMPL(covered_bits) {
|
|
dns_fixedname_t fn;
|
|
dns_name_t *name = dns_fixedname_name(&fn);
|
|
|
|
/* check existing bit values */
|
|
dns_test_namefromstring("example.com.", &fn);
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 0));
|
|
assert_true(dns_nametree_covered(bitstree, name, NULL, 1));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 2));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 3));
|
|
assert_true(dns_nametree_covered(bitstree, name, NULL, 9));
|
|
assert_true(dns_nametree_covered(bitstree, name, NULL, 53));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 288));
|
|
|
|
/* add a small bit value, test again */
|
|
assert_int_equal(dns_nametree_add(bitstree, name, 3), ISC_R_SUCCESS);
|
|
assert_true(dns_nametree_covered(bitstree, name, NULL, 3));
|
|
|
|
/* add a large bit value, test again */
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 615));
|
|
assert_int_equal(dns_nametree_add(bitstree, name, 615), ISC_R_SUCCESS);
|
|
assert_true(dns_nametree_covered(bitstree, name, NULL, 615));
|
|
assert_int_equal(dns_nametree_add(bitstree, name, 999), ISC_R_SUCCESS);
|
|
assert_true(dns_nametree_covered(bitstree, name, NULL, 999));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 998));
|
|
|
|
/* check existing bit values for subdomain */
|
|
dns_test_namefromstring("sub.example.com.", &fn);
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 0));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 1));
|
|
assert_true(dns_nametree_covered(bitstree, name, NULL, 2));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 3));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 9));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 53));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 288));
|
|
|
|
/* check nonexistent subdomain is all false */
|
|
dns_test_namefromstring("other.example.com", &fn);
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 0));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 1));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 2));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 3));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 9));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 53));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 288));
|
|
|
|
/* check nonexistent domain is all false */
|
|
dns_test_namefromstring("anyname.", &fn);
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 0));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 1));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 2));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 3));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 9));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 53));
|
|
assert_false(dns_nametree_covered(bitstree, name, NULL, 288));
|
|
}
|
|
|
|
ISC_RUN_TEST_IMPL(delete) {
|
|
dns_fixedname_t fn;
|
|
dns_name_t *name = dns_fixedname_name(&fn);
|
|
|
|
/* name doesn't match */
|
|
dns_test_namefromstring("example.org.", &fn);
|
|
assert_int_equal(dns_nametree_delete(booltree, name), ISC_R_NOTFOUND);
|
|
|
|
/* subdomain match is the same as no match */
|
|
dns_test_namefromstring("sub.example.org.", &fn);
|
|
assert_int_equal(dns_nametree_delete(booltree, name), ISC_R_NOTFOUND);
|
|
|
|
/*
|
|
* delete requires exact match: this should return SUCCESS on
|
|
* the first try, then NOTFOUND on the second even though an
|
|
* ancestor does exist.
|
|
*/
|
|
dns_test_namefromstring("negative.example.com.", &fn);
|
|
assert_int_equal(dns_nametree_delete(booltree, name), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_delete(booltree, name), ISC_R_NOTFOUND);
|
|
|
|
dns_test_namefromstring("negative.example.org.", &fn);
|
|
assert_int_equal(dns_nametree_delete(booltree, name), ISC_R_SUCCESS);
|
|
assert_int_equal(dns_nametree_delete(booltree, name), ISC_R_NOTFOUND);
|
|
}
|
|
|
|
ISC_RUN_TEST_IMPL(find) {
|
|
dns_ntnode_t *node = NULL;
|
|
dns_fixedname_t fn;
|
|
dns_name_t *name = dns_fixedname_name(&fn);
|
|
|
|
/*
|
|
* dns_nametree_find() requires exact name match. It matches node
|
|
* that has a null key, too.
|
|
*/
|
|
dns_test_namefromstring("example.org.", &fn);
|
|
assert_int_equal(dns_nametree_find(booltree, name, &node),
|
|
ISC_R_NOTFOUND);
|
|
dns_test_namefromstring("sub.example.com.", &fn);
|
|
assert_int_equal(dns_nametree_find(booltree, name, &node),
|
|
ISC_R_NOTFOUND);
|
|
dns_test_namefromstring("example.com.", &fn);
|
|
assert_int_equal(dns_nametree_find(booltree, name, &node),
|
|
ISC_R_SUCCESS);
|
|
dns_ntnode_detach(&node);
|
|
}
|
|
|
|
ISC_TEST_LIST_START
|
|
ISC_TEST_ENTRY_CUSTOM(add_bool, setup, teardown)
|
|
ISC_TEST_ENTRY_CUSTOM(add_bits, setup, teardown)
|
|
ISC_TEST_ENTRY_CUSTOM(add_count, setup, teardown)
|
|
ISC_TEST_ENTRY_CUSTOM(covered_bool, setup, teardown)
|
|
ISC_TEST_ENTRY_CUSTOM(covered_bits, setup, teardown)
|
|
ISC_TEST_ENTRY_CUSTOM(delete, setup, teardown)
|
|
ISC_TEST_ENTRY_CUSTOM(find, setup, teardown)
|
|
ISC_TEST_LIST_END
|
|
|
|
ISC_TEST_MAIN
|