diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:59:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 15:59:48 +0000 |
commit | 3b9b6d0b8e7f798023c9d109c490449d528fde80 (patch) | |
tree | 2e1c188dd7b8d7475cd163de9ae02c428343669b /tests/dns/zt_test.c | |
parent | Initial commit. (diff) | |
download | bind9-upstream.tar.xz bind9-upstream.zip |
Adding upstream version 1:9.18.19.upstream/1%9.18.19upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/dns/zt_test.c')
-rw-r--r-- | tests/dns/zt_test.c | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/tests/dns/zt_test.c b/tests/dns/zt_test.c new file mode 100644 index 0000000..c38e601 --- /dev/null +++ b/tests/dns/zt_test.c @@ -0,0 +1,352 @@ +/* + * 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 <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define UNIT_TESTING +#include <cmocka.h> + +#include <isc/app.h> +#include <isc/atomic.h> +#include <isc/buffer.h> +#include <isc/print.h> +#include <isc/task.h> +#include <isc/timer.h> +#include <isc/util.h> + +#include <dns/db.h> +#include <dns/name.h> +#include <dns/view.h> +#include <dns/zone.h> +#include <dns/zt.h> + +#include <tests/dns.h> + +static int +_setup(void **state) { + isc_app_start(); + setup_managers(state); + + return (0); +} + +static int +_teardown(void **state) { + teardown_managers(state); + isc_app_finish(); + + return (0); +} + +struct args { + void *arg1; + void *arg2; + bool arg3; +}; + +static isc_result_t +count_zone(dns_zone_t *zone, void *uap) { + int *nzones = (int *)uap; + + UNUSED(zone); + + *nzones += 1; + return (ISC_R_SUCCESS); +} + +static isc_result_t +load_done(dns_zt_t *zt, dns_zone_t *zone, isc_task_t *task) { + /* We treat zt as a pointer to a boolean for testing purposes */ + atomic_bool *done = (atomic_bool *)zt; + + UNUSED(zone); + UNUSED(task); + + atomic_store(done, true); + isc_app_shutdown(); + return (ISC_R_SUCCESS); +} + +static isc_result_t +all_done(void *arg) { + atomic_bool *done = (atomic_bool *)arg; + + atomic_store(done, true); + isc_app_shutdown(); + return (ISC_R_SUCCESS); +} + +static void +start_zt_asyncload(isc_task_t *task, isc_event_t *event) { + struct args *args = (struct args *)(event->ev_arg); + + UNUSED(task); + + dns_zt_asyncload(args->arg1, false, all_done, args->arg2); + + isc_event_free(&event); +} + +static void +start_zone_asyncload(isc_task_t *task, isc_event_t *event) { + struct args *args = (struct args *)(event->ev_arg); + + UNUSED(task); + + dns_zone_asyncload(args->arg1, args->arg3, load_done, args->arg2); + isc_event_free(&event); +} + +/* apply a function to a zone table */ +ISC_RUN_TEST_IMPL(dns_zt_apply) { + isc_result_t result; + dns_zone_t *zone = NULL; + dns_view_t *view = NULL; + int nzones = 0; + + UNUSED(state); + + result = dns_test_makezone("foo", &zone, NULL, true); + assert_int_equal(result, ISC_R_SUCCESS); + + view = dns_zone_getview(zone); + assert_non_null(view->zonetable); + + assert_int_equal(nzones, 0); + result = dns_zt_apply(view->zonetable, isc_rwlocktype_read, false, NULL, + count_zone, &nzones); + assert_int_equal(result, ISC_R_SUCCESS); + assert_int_equal(nzones, 1); + + /* These steps are necessary so the zone can be detached properly */ + result = dns_test_setupzonemgr(); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone); + assert_int_equal(result, ISC_R_SUCCESS); + dns_test_releasezone(zone); + dns_test_closezonemgr(); + + /* The view was left attached in dns_test_makezone() */ + dns_view_detach(&view); + dns_zone_detach(&zone); +} + +/* asynchronous zone load */ +ISC_RUN_TEST_IMPL(dns_zt_asyncload_zone) { + isc_result_t result; + int n; + dns_zone_t *zone = NULL; + dns_view_t *view = NULL; + dns_db_t *db = NULL; + FILE *zonefile, *origfile; + char buf[4096]; + atomic_bool done; + int i = 0; + struct args args; + + UNUSED(state); + + atomic_init(&done, false); + + result = dns_test_makezone("foo", &zone, NULL, true); + assert_int_equal(result, ISC_R_SUCCESS); + + result = dns_test_setupzonemgr(); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone); + assert_int_equal(result, ISC_R_SUCCESS); + + view = dns_zone_getview(zone); + assert_non_null(view->zonetable); + + assert_false(dns__zone_loadpending(zone)); + assert_false(atomic_load(&done)); + zonefile = fopen("./zone.data", "wb"); + assert_non_null(zonefile); + origfile = fopen(TESTS_DIR "/testdata/zt/zone1.db", "r+b"); + assert_non_null(origfile); + n = fread(buf, 1, 4096, origfile); + fclose(origfile); + fwrite(buf, 1, n, zonefile); + fflush(zonefile); + + dns_zone_setfile(zone, "./zone.data", dns_masterformat_text, + &dns_master_style_default); + + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = false; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + while (dns__zone_loadpending(zone) && i++ < 5000) { + dns_test_nap(1000); + } + assert_true(atomic_load(&done)); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + assert_int_equal(result, ISC_R_SUCCESS); + dns_db_detach(&db); + /* + * Add something to zone file, reload zone with newonly - it should + * not be reloaded. + */ + fprintf(zonefile, "\nb in b 1.2.3.4\n"); + fflush(zonefile); + fclose(zonefile); + + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = true; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + + while (dns__zone_loadpending(zone) && i++ < 5000) { + dns_test_nap(1000); + } + assert_true(atomic_load(&done)); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + assert_int_equal(result, ISC_R_SUCCESS); + dns_db_detach(&db); + + /* Now reload it without newonly - it should be reloaded */ + args.arg1 = zone; + args.arg2 = &done; + args.arg3 = false; + isc_app_onrun(mctx, maintask, start_zone_asyncload, &args); + + isc_app_run(); + + while (dns__zone_loadpending(zone) && i++ < 5000) { + dns_test_nap(1000); + } + assert_true(atomic_load(&done)); + /* The zone should now be loaded; test it */ + result = dns_zone_getdb(zone, &db); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_non_null(db); + if (db != NULL) { + dns_db_detach(&db); + } + + dns_test_releasezone(zone); + dns_test_closezonemgr(); + + dns_zone_detach(&zone); + dns_view_detach(&view); +} + +/* asynchronous zone table load */ +ISC_RUN_TEST_IMPL(dns_zt_asyncload_zt) { + isc_result_t result; + dns_zone_t *zone1 = NULL, *zone2 = NULL, *zone3 = NULL; + dns_view_t *view; + dns_zt_t *zt = NULL; + dns_db_t *db = NULL; + atomic_bool done; + int i = 0; + struct args args; + + UNUSED(state); + + atomic_init(&done, false); + + result = dns_test_makezone("foo", &zone1, NULL, true); + assert_int_equal(result, ISC_R_SUCCESS); + dns_zone_setfile(zone1, TESTS_DIR "/testdata/zt/zone1.db", + dns_masterformat_text, &dns_master_style_default); + view = dns_zone_getview(zone1); + + result = dns_test_makezone("bar", &zone2, view, false); + assert_int_equal(result, ISC_R_SUCCESS); + dns_zone_setfile(zone2, TESTS_DIR "/testdata/zt/zone1.db", + dns_masterformat_text, &dns_master_style_default); + + /* This one will fail to load */ + result = dns_test_makezone("fake", &zone3, view, false); + assert_int_equal(result, ISC_R_SUCCESS); + dns_zone_setfile(zone3, TESTS_DIR "/testdata/zt/nonexistent.db", + dns_masterformat_text, &dns_master_style_default); + + zt = view->zonetable; + assert_non_null(zt); + + result = dns_test_setupzonemgr(); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone1); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone2); + assert_int_equal(result, ISC_R_SUCCESS); + result = dns_test_managezone(zone3); + assert_int_equal(result, ISC_R_SUCCESS); + + assert_false(dns__zone_loadpending(zone1)); + assert_false(dns__zone_loadpending(zone2)); + assert_false(atomic_load(&done)); + + args.arg1 = zt; + args.arg2 = &done; + isc_app_onrun(mctx, maintask, start_zt_asyncload, &args); + + isc_app_run(); + while (!atomic_load(&done) && i++ < 5000) { + dns_test_nap(1000); + } + assert_true(atomic_load(&done)); + + /* Both zones should now be loaded; test them */ + result = dns_zone_getdb(zone1, &db); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(db); + if (db != NULL) { + dns_db_detach(&db); + } + + result = dns_zone_getdb(zone2, &db); + assert_int_equal(result, ISC_R_SUCCESS); + assert_non_null(db); + if (db != NULL) { + dns_db_detach(&db); + } + + dns_test_releasezone(zone3); + dns_test_releasezone(zone2); + dns_test_releasezone(zone1); + dns_test_closezonemgr(); + + dns_zone_detach(&zone1); + dns_zone_detach(&zone2); + dns_zone_detach(&zone3); + dns_view_detach(&view); +} + +ISC_TEST_LIST_START + +ISC_TEST_ENTRY_CUSTOM(dns_zt_apply, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dns_zt_asyncload_zone, _setup, _teardown) +ISC_TEST_ENTRY_CUSTOM(dns_zt_asyncload_zt, _setup, _teardown) + +ISC_TEST_LIST_END + +ISC_TEST_MAIN |