mirror of
https://gitlab.nic.cz/knot/knot-dns.git
synced 2026-02-03 18:49:28 -05:00
1099 lines
34 KiB
C
1099 lines
34 KiB
C
/* Copyright (C) CZ.NIC, z.s.p.o. and contributors
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
* For more information, see <https://www.knot-dns.cz/>
|
|
*/
|
|
|
|
#include <tap/basic.h>
|
|
|
|
#include "test_conf.h"
|
|
#include "knot/conf/confio.h"
|
|
#include "knot/conf/tools.h"
|
|
#include "libknot/yparser/yptrafo.h"
|
|
#include "contrib/string.h"
|
|
#include "contrib/openbsd/strlcat.h"
|
|
|
|
#define SKIP_OPENBSD skip("Nested transactions are not supported on OpenBSD");
|
|
#define OUT_LEN 1024
|
|
#define ZONE1 "zone1"
|
|
#define ZONE2 "zone2"
|
|
#define ZONE3 "zone3"
|
|
|
|
char *format_key(conf_io_t *io)
|
|
{
|
|
knot_dname_txt_storage_t id;
|
|
size_t id_len = sizeof(id);
|
|
|
|
// Get the textual item id.
|
|
if (io->id_len > 0 && !io->id_as_data) {
|
|
if (yp_item_to_txt(io->key0->var.g.id, io->id, io->id_len, id,
|
|
&id_len, YP_SNOQUOTE) != KNOT_EOK) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
// Get the item prefix.
|
|
const char *prefix = "";
|
|
switch (io->type) {
|
|
case NEW: prefix = "+"; break;
|
|
case OLD: prefix = "-"; break;
|
|
default: break;
|
|
}
|
|
|
|
// Format the item key.
|
|
return sprintf_alloc(
|
|
"%s%.*s%s%.*s%s%s%.*s",
|
|
prefix, (int)io->key0->name[0], io->key0->name + 1,
|
|
(io->id_len > 0 && !io->id_as_data ? "[" : ""),
|
|
(io->id_len > 0 && !io->id_as_data ? (int)id_len : 0), id,
|
|
(io->id_len > 0 && !io->id_as_data ? "]" : ""),
|
|
(io->key1 != NULL ? "." : ""),
|
|
(io->key1 != NULL ? (int)io->key1->name[0] : 0),
|
|
(io->key1 != NULL ? io->key1->name + 1 : ""));
|
|
}
|
|
|
|
static int append_data(const yp_item_t *item, const uint8_t *bin, size_t bin_len,
|
|
char *out, size_t out_len)
|
|
{
|
|
char buf[YP_MAX_TXT_DATA_LEN + 1] = "\0";
|
|
size_t buf_len = sizeof(buf);
|
|
|
|
int ret = yp_item_to_txt(item, bin, bin_len, buf, &buf_len, YP_SNONE);
|
|
if (ret != KNOT_EOK) {
|
|
return ret;
|
|
}
|
|
|
|
if (strlcat(out, buf, out_len) >= out_len) {
|
|
return KNOT_ESPACE;
|
|
}
|
|
|
|
return KNOT_EOK;
|
|
}
|
|
|
|
char *format_data(conf_io_t *io)
|
|
{
|
|
char out[YP_MAX_TXT_DATA_LEN + 1] = "\0";
|
|
|
|
// Return the item identifier as the item data.
|
|
if (io->id_as_data) {
|
|
if (append_data(io->key0->var.g.id, io->id, io->id_len, out,
|
|
sizeof(out)) != KNOT_EOK) {
|
|
return NULL;
|
|
}
|
|
|
|
return strdup(out);
|
|
}
|
|
|
|
// Check for no data.
|
|
if (io->data.val == NULL && io->data.bin == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
const yp_item_t *item = (io->key1 != NULL) ? io->key1 : io->key0;
|
|
|
|
// Format explicit binary data value.
|
|
if (io->data.bin != NULL) {
|
|
if (append_data(item, io->data.bin, io->data.bin_len, out,
|
|
sizeof(out)) != KNOT_EOK) {
|
|
return NULL;
|
|
}
|
|
// Format multivalued item data.
|
|
} else if (item->flags & YP_FMULTI) {
|
|
size_t values = conf_val_count(io->data.val);
|
|
for (size_t i = 0; i < values; i++) {
|
|
// Skip other values if known index (counted from 1).
|
|
if (io->data.index > 0 &&
|
|
io->data.index != i + 1) {
|
|
conf_val_next(io->data.val);
|
|
continue;
|
|
}
|
|
|
|
if (i > 0) {
|
|
if (strlcat(out, " ", sizeof(out)) >= sizeof(out)) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
conf_val(io->data.val);
|
|
if (append_data(item, io->data.val->data, io->data.val->len,
|
|
out, sizeof(out)) != KNOT_EOK) {
|
|
return NULL;
|
|
}
|
|
|
|
conf_val_next(io->data.val);
|
|
}
|
|
// Format singlevalued item data.
|
|
} else {
|
|
conf_val(io->data.val);
|
|
if (append_data(item, io->data.val->data, io->data.val->len, out,
|
|
sizeof(out)) != KNOT_EOK) {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return strdup(out);
|
|
}
|
|
|
|
static int format_item(conf_io_t *io)
|
|
{
|
|
char *out = (char *)io->misc;
|
|
|
|
// Get the item key and data strings.
|
|
char *key = format_key(io);
|
|
char *data = format_data(io);
|
|
|
|
// Format the item.
|
|
char *item = sprintf_alloc(
|
|
"%s%s%s%s",
|
|
(*out != '\0' ? "\n" : ""),
|
|
(key != NULL ? key : ""),
|
|
(data != NULL ? " = " : ""),
|
|
(data != NULL ? data : ""));
|
|
free(key);
|
|
free(data);
|
|
if (item == NULL) {
|
|
return KNOT_ENOMEM;
|
|
}
|
|
|
|
// Append the item.
|
|
if (strlcat(out, item, OUT_LEN) >= OUT_LEN) {
|
|
free(item);
|
|
return KNOT_ESPACE;
|
|
}
|
|
|
|
free(item);
|
|
|
|
return KNOT_EOK;
|
|
}
|
|
|
|
static void test_conf_io_begin(void)
|
|
{
|
|
ok(conf_io_begin(true) == KNOT_TXN_ENOTEXISTS, "begin child txn with no parent");
|
|
ok(conf()->io.txn == NULL, "check txn depth");
|
|
|
|
#if defined(__OpenBSD__)
|
|
SKIP_OPENBSD
|
|
#else
|
|
ok(conf_io_begin(false) == KNOT_EOK, "begin parent txn");
|
|
ok(conf()->io.txn == &(conf()->io.txn_stack[0]), "check txn depth");
|
|
|
|
ok(conf_io_begin(false) == KNOT_TXN_EEXISTS, "begin another parent txn");
|
|
ok(conf()->io.txn == &(conf()->io.txn_stack[0]), "check txn depth");
|
|
|
|
for (int i = 1; i < CONF_MAX_TXN_DEPTH; i++) {
|
|
ok(conf_io_begin(true) == KNOT_EOK, "begin child txn");
|
|
ok(conf()->io.txn == &(conf()->io.txn_stack[i]), "check txn depth");
|
|
}
|
|
ok(conf_io_begin(true) == KNOT_TXN_EEXISTS, "begin another child txn");
|
|
ok(conf()->io.txn == &(conf()->io.txn_stack[CONF_MAX_TXN_DEPTH - 1]),
|
|
"check txn depth");
|
|
|
|
conf_io_abort(false);
|
|
ok(conf()->io.txn == NULL, "check txn depth");
|
|
#endif
|
|
}
|
|
|
|
static void test_conf_io_abort(void)
|
|
{
|
|
#if defined(__OpenBSD__)
|
|
SKIP_OPENBSD
|
|
#else
|
|
// Test child persistence after subchild abort.
|
|
{
|
|
char idx[2] = { '0' };
|
|
ok(conf_io_begin(false) == KNOT_EOK, "begin parent txn");
|
|
ok(conf_io_set("server", "version", NULL, idx) ==
|
|
KNOT_EOK, "set single value '%s'", idx);
|
|
}
|
|
|
|
for (int i = 1; i < CONF_MAX_TXN_DEPTH; i++) {
|
|
char idx[2] = { '0' + i };
|
|
ok(conf_io_begin(true) == KNOT_EOK, "begin child txn %s", idx);
|
|
ok(conf_io_set("server", "version", NULL, idx) ==
|
|
KNOT_EOK, "set single value '%s'", idx);
|
|
}
|
|
|
|
for (int i = CONF_MAX_TXN_DEPTH - 1; i > 0; i--) {
|
|
char idx[2] = { '0' + i };
|
|
conf_io_abort(true);
|
|
conf_val_t val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
const char *data = conf_str(&val);
|
|
ok(*data == (idx[0] - 1), "compare txn data '%s'", data);
|
|
}
|
|
|
|
conf_io_abort(false);
|
|
ok(conf()->io.txn == NULL, "check txn depth");
|
|
|
|
// Test child abort with committed subchild.
|
|
ok(conf_io_begin(false) == KNOT_EOK, "begin new parent txn");
|
|
ok(conf_io_begin(true) == KNOT_EOK, "begin child txn");
|
|
ok(conf_io_begin(true) == KNOT_EOK, "begin subchild txn");
|
|
ok(conf_io_set("server", "version", NULL, "text") ==
|
|
KNOT_EOK, "set single value");
|
|
ok(conf_io_commit(true) == KNOT_EOK, "commit subchild txn");
|
|
conf_val_t val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
const char *data = conf_str(&val);
|
|
ok(strcmp(data, "text") == 0, "compare subchild txn data '%s'", data);
|
|
conf_io_abort(true);
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_ENOENT, "check entry");
|
|
conf_io_abort(false);
|
|
|
|
// Test unchanged read_txn.
|
|
val = conf_get_txn(conf(), &conf()->read_txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_ENOENT, "check entry");
|
|
#endif
|
|
}
|
|
|
|
static void test_conf_io_commit(void)
|
|
{
|
|
ok(conf_io_commit(false) == KNOT_TXN_ENOTEXISTS, "commit no txt txn");
|
|
ok(conf_io_commit(true) == KNOT_TXN_ENOTEXISTS, "commit no txt txn");
|
|
|
|
#if defined(__OpenBSD__)
|
|
SKIP_OPENBSD
|
|
#else
|
|
// Test subchild persistence after commit.
|
|
{
|
|
char idx[2] = { '0' };
|
|
ok(conf_io_begin(false) == KNOT_EOK, "begin parent txn");
|
|
ok(conf_io_set("server", "version", NULL, idx) ==
|
|
KNOT_EOK, "set single value '%s'", idx);
|
|
}
|
|
|
|
for (int i = 1; i < CONF_MAX_TXN_DEPTH; i++) {
|
|
char idx[2] = { '0' + i };
|
|
ok(conf_io_begin(true) == KNOT_EOK, "begin child txn %s", idx);
|
|
ok(conf_io_set("server", "version", NULL, idx) ==
|
|
KNOT_EOK, "set single value '%s'", idx);
|
|
}
|
|
|
|
for (int i = CONF_MAX_TXN_DEPTH - 1; i > 0; i--) {
|
|
char idx[2] = { '0' + i };
|
|
ok(conf_io_commit(true) == KNOT_EOK, "commit child txn %s", idx);
|
|
conf_val_t val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
const char *data = conf_str(&val);
|
|
ok(*data == ('0' + CONF_MAX_TXN_DEPTH - 1), "compare txn data '%s'", data);
|
|
}
|
|
|
|
ok(conf_io_commit(false) == KNOT_EOK, "commit parent txn");
|
|
ok(conf()->io.txn == NULL, "check txn depth");
|
|
|
|
// Test child persistence after parent commit.
|
|
ok(conf_io_begin(false) == KNOT_EOK, "begin new parent txn");
|
|
conf_val_t val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
char idx[2] = { '0' + CONF_MAX_TXN_DEPTH - 1 };
|
|
const char *data = conf_str(&val);
|
|
ok(strcmp(data, idx) == 0, "compare final data '%s'", data);
|
|
conf_io_abort(false);
|
|
|
|
// Test unchanged read_txn.
|
|
val = conf_get_txn(conf(), &conf()->read_txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_ENOENT, "check entry");
|
|
#endif
|
|
}
|
|
|
|
static void test_conf_io_check(void)
|
|
{
|
|
conf_io_t io = { NULL };
|
|
|
|
// ERR no txn.
|
|
ok(conf_io_check(&io) ==
|
|
KNOT_TXN_ENOTEXISTS, "check without active txn");
|
|
|
|
ok(conf_io_begin(false) == KNOT_EOK, "begin txn");
|
|
|
|
// Section check.
|
|
ok(conf_io_set("remote", "id", NULL, "remote1") ==
|
|
KNOT_EOK, "set remote id");
|
|
ok(conf_io_check(&io) ==
|
|
KNOT_EINVAL, "check missing remote address");
|
|
ok(io.error.code == KNOT_EINVAL, "compare error code");
|
|
|
|
ok(conf_io_set("remote", "address", "remote1", "1.1.1.1") ==
|
|
KNOT_EOK, "set remote address");
|
|
ok(conf_io_check(&io) ==
|
|
KNOT_EOK, "check remote address");
|
|
ok(io.error.code == KNOT_EOK, "compare error code");
|
|
|
|
// Item check.
|
|
ok(conf_io_set("zone", "domain", NULL, ZONE1) ==
|
|
KNOT_EOK, "set zone domain "ZONE1);
|
|
ok(conf_io_set("zone", "master", ZONE1, "remote1") ==
|
|
KNOT_EOK, "set zone master");
|
|
|
|
ok(conf_io_check(&io) ==
|
|
KNOT_EOK, "check all");
|
|
|
|
ok(conf_io_unset("remote", NULL, NULL, NULL) ==
|
|
KNOT_EOK, "unset remotes");
|
|
|
|
ok(conf_io_check(&io) ==
|
|
KNOT_ENOENT, "check missing master remote");
|
|
ok(io.error.code == KNOT_ENOENT, "compare error code");
|
|
|
|
conf_io_abort(false);
|
|
}
|
|
|
|
static void test_conf_io_set(void)
|
|
{
|
|
// ERR no txn.
|
|
ok(conf_io_set("server", "version", NULL, "text") ==
|
|
KNOT_TXN_ENOTEXISTS, "set without active txn");
|
|
|
|
ok(conf_io_begin(false) == KNOT_EOK, "begin txn");
|
|
|
|
// ERR.
|
|
ok(conf_io_set(NULL, NULL, NULL, NULL) ==
|
|
KNOT_EINVAL, "set NULL key0");
|
|
ok(conf_io_set("", NULL, NULL, NULL) ==
|
|
KNOT_YP_EINVAL_ITEM, "set empty key0");
|
|
ok(conf_io_set("unknown", NULL, NULL, NULL) ==
|
|
KNOT_YP_EINVAL_ITEM, "set unknown key0");
|
|
ok(conf_io_set("server", "unknown", NULL, NULL) ==
|
|
KNOT_YP_EINVAL_ITEM, "set unknown key1");
|
|
ok(conf_io_set("include", NULL, NULL, NULL) ==
|
|
KNOT_YP_ENODATA, "set non-group without data");
|
|
ok(conf_io_set("server", "background-workers", NULL, "x") ==
|
|
KNOT_EINVAL, "set invalid data");
|
|
|
|
// ERR callback
|
|
ok(conf_io_set("include", NULL, NULL, "invalid") ==
|
|
KNOT_EFILE, "set invalid callback value");
|
|
|
|
// Single group, no item, no value.
|
|
ok(conf_io_set("server", NULL, NULL, NULL) ==
|
|
KNOT_ENOTSUP, "set group no value");
|
|
// Single group, no item, value.
|
|
ok(conf_io_set("server", NULL, NULL, "text") ==
|
|
KNOT_YP_ENOTSUP_DATA, "set group value");
|
|
// Single group, item, no value.
|
|
ok(conf_io_set("server", "version", NULL, NULL) ==
|
|
KNOT_YP_ENODATA, "set group item no value");
|
|
|
|
// Single group, single value.
|
|
ok(conf_io_set("server", "version", NULL, "text") ==
|
|
KNOT_EOK, "set single value");
|
|
conf_val_t val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
ok(strcmp(conf_str(&val), "text") == 0, "check entry value");
|
|
|
|
// Single group, multi value.
|
|
ok(conf_io_set("server", "listen", NULL, "1.1.1.1") ==
|
|
KNOT_EOK, "set multivalue 1");
|
|
ok(conf_io_set("server", "listen", NULL, "1.1.1.2") ==
|
|
KNOT_EOK, "set multivalue 2");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_LISTEN);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
ok(conf_val_count(&val) == 2, "check entry value count");
|
|
|
|
// Prepare dnames.
|
|
knot_dname_t *zone1 = knot_dname_from_str_alloc(ZONE1);
|
|
ok(zone1 != NULL, "create dname "ZONE1);
|
|
knot_dname_t *zone2 = knot_dname_from_str_alloc(ZONE2);
|
|
ok(zone2 != NULL, "create dname "ZONE2);
|
|
knot_dname_t *zone3 = knot_dname_from_str_alloc(ZONE3);
|
|
ok(zone3 != NULL, "create dname "ZONE3);
|
|
|
|
// Multi group no id.
|
|
ok(conf_io_set("zone", "domain", NULL, NULL) ==
|
|
KNOT_YP_ENOID, "set zone empty domain");
|
|
|
|
// Multi group ids.
|
|
ok(conf_io_set("zone", "domain", NULL, ZONE1) ==
|
|
KNOT_EOK, "set zone domain "ZONE1);
|
|
ok(conf_io_set("zone", NULL, ZONE2, NULL) ==
|
|
KNOT_EOK, "set zone domain "ZONE2);
|
|
|
|
// Multi group, single value.
|
|
ok(conf_io_set("zone", "file", ZONE1, "name") ==
|
|
KNOT_EOK, "set zone file");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_FILE, zone1);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
ok(strcmp(conf_str(&val), "name") == 0, "check entry value");
|
|
|
|
// Multi group, single value, bad id.
|
|
ok(conf_io_set("zone", "file", ZONE3, "name") ==
|
|
KNOT_YP_EINVAL_ID, "set zone file");
|
|
|
|
// Multi group, single value, all ids.
|
|
ok(conf_io_set("zone", "comment", NULL, "abc") ==
|
|
KNOT_EOK, "set zones comment");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone1);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
ok(strcmp(conf_str(&val), "abc") == 0, "check entry value");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone2);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
ok(strcmp(conf_str(&val), "abc") == 0, "check entry value");
|
|
|
|
// Prepare different comment.
|
|
ok(conf_io_set("zone", "domain", NULL, ZONE3) ==
|
|
KNOT_EOK, "set zone domain "ZONE3);
|
|
ok(conf_io_set("zone", "comment", ZONE3, "xyz") ==
|
|
KNOT_EOK, "set zone comment");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone3);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
ok(strcmp(conf_str(&val), "xyz") == 0, "check entry value");
|
|
|
|
knot_dname_free(zone1, NULL);
|
|
knot_dname_free(zone2, NULL);
|
|
knot_dname_free(zone3, NULL);
|
|
|
|
ok(conf_io_commit(false) == KNOT_EOK, "commit txn");
|
|
|
|
// Update read-only transaction.
|
|
ok(conf_refresh_txn(conf()) == KNOT_EOK, "update read-only txn");
|
|
}
|
|
|
|
static void test_conf_io_unset(void)
|
|
{
|
|
// ERR no txn.
|
|
ok(conf_io_unset("server", "version", NULL, "text") ==
|
|
KNOT_TXN_ENOTEXISTS, "unset without active txn");
|
|
|
|
ok(conf_io_begin(false) == KNOT_EOK, "begin txn");
|
|
|
|
// ERR.
|
|
ok(conf_io_unset("", NULL, NULL, NULL) ==
|
|
KNOT_YP_EINVAL_ITEM, "unset unknown key0");
|
|
ok(conf_io_unset("unknown", NULL, NULL, NULL) ==
|
|
KNOT_YP_EINVAL_ITEM, "unset unknown key0");
|
|
ok(conf_io_unset("server", "unknown", NULL, NULL) ==
|
|
KNOT_YP_EINVAL_ITEM, "unset unknown key1");
|
|
ok(conf_io_unset("include", NULL, NULL, "file") ==
|
|
KNOT_ENOTSUP, "unset non-group item");
|
|
ok(conf_io_unset("server", "background-workers", NULL, "x") ==
|
|
KNOT_EINVAL, "unset invalid data");
|
|
|
|
// Single group, single value.
|
|
ok(conf_io_unset("server", "version", NULL, "") ==
|
|
KNOT_ENOENT, "unset zero length text value");
|
|
conf_val_t val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
|
|
ok(conf_io_unset("server", "version", NULL, "bad text") ==
|
|
KNOT_ENOENT, "unset bad value");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
|
|
ok(conf_io_unset("server", "version", NULL, "text") ==
|
|
KNOT_EOK, "unset explicit value");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_ENOENT, "check entry");
|
|
|
|
// Restart transaction.
|
|
conf_io_abort(false);
|
|
ok(conf_io_begin(false) == KNOT_EOK, "restart txn");
|
|
|
|
ok(conf_io_unset("server", "version", NULL, NULL) ==
|
|
KNOT_EOK, "unset value");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_ENOENT, "check entry");
|
|
|
|
// Single group, multi value.
|
|
ok(conf_io_unset("server", "listen", NULL, "9.9.9.9") ==
|
|
KNOT_ENOENT, "unset bad value");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_LISTEN);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
|
|
ok(conf_io_unset("server", "listen", NULL, "1.1.1.1") ==
|
|
KNOT_EOK, "unset explicit value");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_LISTEN);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
ok(conf_val_count(&val) == 1, "check entry value count");
|
|
|
|
ok(conf_io_unset("server", "listen", NULL, NULL) ==
|
|
KNOT_EOK, "unset value");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_LISTEN);
|
|
ok(val.code == KNOT_ENOENT, "check entry");
|
|
|
|
// Restart transaction.
|
|
conf_io_abort(false);
|
|
ok(conf_io_begin(false) == KNOT_EOK, "restart txn");
|
|
|
|
// Whole section items.
|
|
ok(conf_io_unset("server", NULL, NULL, NULL) ==
|
|
KNOT_EOK, "unset section");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_ENOENT, "check entry");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_LISTEN);
|
|
ok(val.code == KNOT_ENOENT, "check entry");
|
|
|
|
// Restart transaction.
|
|
conf_io_abort(false);
|
|
ok(conf_io_begin(false) == KNOT_EOK, "restart txn");
|
|
|
|
// Prepare dnames.
|
|
knot_dname_t *zone1 = knot_dname_from_str_alloc(ZONE1);
|
|
ok(zone1 != NULL, "create dname "ZONE1);
|
|
knot_dname_t *zone2 = knot_dname_from_str_alloc(ZONE2);
|
|
ok(zone2 != NULL, "create dname "ZONE2);
|
|
knot_dname_t *zone3 = knot_dname_from_str_alloc(ZONE3);
|
|
ok(zone3 != NULL, "create dname "ZONE3);
|
|
|
|
// Multi group, single value.
|
|
ok(conf_io_unset("zone", "file", ZONE1, "name") ==
|
|
KNOT_EOK, "unset zone file");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_FILE, zone1);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
|
|
// Multi group, single bad value, all ids.
|
|
ok(conf_io_unset("zone", "comment", NULL, "other") ==
|
|
KNOT_EOK, "unset zones comment");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone1);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone2);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone3);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
|
|
// Restart transaction.
|
|
conf_io_abort(false);
|
|
ok(conf_io_begin(false) == KNOT_EOK, "restart txn");
|
|
|
|
// Multi group, single value (not all match), all ids.
|
|
ok(conf_io_unset("zone", "comment", NULL, "abc") ==
|
|
KNOT_EOK, "unset some zones comment");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone1);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone2);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone3);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
|
|
// Restart transaction.
|
|
conf_io_abort(false);
|
|
ok(conf_io_begin(false) == KNOT_EOK, "restart txn");
|
|
|
|
// Multi group, single value (all match), all ids.
|
|
ok(conf_io_unset("zone", "comment", NULL, NULL) ==
|
|
KNOT_EOK, "unset all zones comment");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone1);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone2);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone3);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
|
|
// Restart transaction.
|
|
conf_io_abort(false);
|
|
ok(conf_io_begin(false) == KNOT_EOK, "restart txn");
|
|
|
|
// Multi group, all items, specific id.
|
|
ok(conf_io_unset("zone", NULL, ZONE1, NULL) ==
|
|
KNOT_EOK, "unset zone items");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_FILE, zone1);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone1);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone2);
|
|
ok(val.code == KNOT_EOK, "check entry");
|
|
|
|
// Restart transaction.
|
|
conf_io_abort(false);
|
|
ok(conf_io_begin(false) == KNOT_EOK, "restart txn");
|
|
|
|
// Multi group, all items, all ids.
|
|
ok(conf_io_unset("zone", NULL, NULL, NULL) ==
|
|
KNOT_EOK, "unset zone items");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_FILE, zone1);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone1);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone2);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
|
|
// Restart transaction.
|
|
conf_io_abort(false);
|
|
ok(conf_io_begin(false) == KNOT_EOK, "restart txn");
|
|
|
|
// All groups.
|
|
ok(conf_io_unset(NULL, NULL, NULL, NULL) ==
|
|
KNOT_EOK, "unset all");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_VERSION);
|
|
ok(val.code == KNOT_ENOENT, "check entry");
|
|
val = conf_get_txn(conf(), conf()->io.txn, C_SERVER, C_LISTEN);
|
|
ok(val.code == KNOT_ENOENT, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_FILE, zone1);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone1);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
val = conf_zone_get_txn(conf(), conf()->io.txn, C_COMMENT, zone2);
|
|
ok(val.code == KNOT_YP_EINVAL_ID, "check entry");
|
|
|
|
knot_dname_free(zone1, NULL);
|
|
knot_dname_free(zone2, NULL);
|
|
knot_dname_free(zone3, NULL);
|
|
|
|
conf_io_abort(false);
|
|
}
|
|
|
|
static void test_conf_io_get(void)
|
|
{
|
|
const char *ref;
|
|
char out[OUT_LEN];
|
|
|
|
conf_io_t io = {
|
|
.fcn = format_item,
|
|
.misc = out
|
|
};
|
|
|
|
// ERR no txn.
|
|
ok(conf_io_get("server", "version", NULL, false, &io) ==
|
|
KNOT_TXN_ENOTEXISTS, "get without active txn");
|
|
|
|
// Get current, no active txn.
|
|
*out = '\0';
|
|
ok(conf_io_get("server", "version", NULL, true, &io) ==
|
|
KNOT_EOK, "get current without active txn");
|
|
ref = "server.version = \"text\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
ok(conf_io_begin(false) == KNOT_EOK, "begin txn");
|
|
|
|
// ERR.
|
|
ok(conf_io_get("", NULL, NULL, true, &io) ==
|
|
KNOT_YP_EINVAL_ITEM, "get empty key0");
|
|
ok(conf_io_get("unknown", NULL, NULL, true, &io) ==
|
|
KNOT_YP_EINVAL_ITEM, "get unknown key0");
|
|
ok(conf_io_get("server", "unknown", NULL, true, &io) ==
|
|
KNOT_YP_EINVAL_ITEM, "get unknown key1");
|
|
ok(conf_io_get("include", NULL, NULL, true, &io) ==
|
|
KNOT_ENOTSUP, "get non-group item");
|
|
|
|
// Update item in the active txn.
|
|
ok(conf_io_set("server", "version", NULL, "new text") ==
|
|
KNOT_EOK, "set single value");
|
|
|
|
// Get new, active txn.
|
|
*out = '\0';
|
|
ok(conf_io_get("server", "version", NULL, false, &io) ==
|
|
KNOT_EOK, "get with active txn");
|
|
ref = "server.version = \"new text\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Get current, active txn.
|
|
*out = '\0';
|
|
ok(conf_io_get("server", "version", NULL, true, &io) ==
|
|
KNOT_EOK, "get with active txn");
|
|
ref = "server.version = \"text\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Multi value.
|
|
*out = '\0';
|
|
ok(conf_io_get("server", "listen", NULL, true, &io) ==
|
|
KNOT_EOK, "get with active txn");
|
|
ref = "server.listen = \"1.1.1.1\" \"1.1.1.2\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Single group.
|
|
*out = '\0';
|
|
ok(conf_io_get("server", NULL, NULL, true, &io) ==
|
|
KNOT_EOK, "get with active txn");
|
|
ref = "server.version = \"text\"\n"
|
|
"server.listen = \"1.1.1.1\" \"1.1.1.2\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Prepare dnames.
|
|
knot_dname_t *zone1 = knot_dname_from_str_alloc(ZONE1);
|
|
ok(zone1 != NULL, "create dname "ZONE1);
|
|
|
|
// Multi group, all values, all ids.
|
|
*out = '\0';
|
|
ok(conf_io_get("zone", NULL, NULL, true, &io) ==
|
|
KNOT_EOK, "get with active txn");
|
|
ref = "zone.domain = \"zone1.\"\n"
|
|
"zone[zone1.].file = \"name\"\n"
|
|
"zone[zone1.].comment = \"abc\"\n"
|
|
"zone.domain = \"zone2.\"\n"
|
|
"zone[zone2.].comment = \"abc\"\n"
|
|
"zone.domain = \"zone3.\"\n"
|
|
"zone[zone3.].comment = \"xyz\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Multi group ids.
|
|
*out = '\0';
|
|
ok(conf_io_get("zone", "domain", NULL, true, &io) ==
|
|
KNOT_EOK, "get with active txn");
|
|
ref = "zone.domain = \"zone1.\"\n"
|
|
"zone.domain = \"zone2.\"\n"
|
|
"zone.domain = \"zone3.\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Multi group, all values, single id.
|
|
*out = '\0';
|
|
ok(conf_io_get("zone", NULL, ZONE1, true, &io) ==
|
|
KNOT_EOK, "get with active txn");
|
|
ref = "zone.domain = \"zone1.\"\n"
|
|
"zone[zone1.].file = \"name\"\n"
|
|
"zone[zone1.].comment = \"abc\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Multi group, single value, single id.
|
|
*out = '\0';
|
|
ok(conf_io_get("zone", "file", ZONE1, true, &io) ==
|
|
KNOT_EOK, "get with active txn");
|
|
ref = "zone[zone1.].file = \"name\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// All groups.
|
|
*out = '\0';
|
|
ok(conf_io_get(NULL, NULL, NULL, true, &io) ==
|
|
KNOT_EOK, "get with active txn");
|
|
ref = "server.version = \"text\"\n"
|
|
"server.listen = \"1.1.1.1\" \"1.1.1.2\"\n"
|
|
"zone.domain = \"zone1.\"\n"
|
|
"zone[zone1.].file = \"name\"\n"
|
|
"zone[zone1.].comment = \"abc\"\n"
|
|
"zone.domain = \"zone2.\"\n"
|
|
"zone[zone2.].comment = \"abc\"\n"
|
|
"zone.domain = \"zone3.\"\n"
|
|
"zone[zone3.].comment = \"xyz\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
knot_dname_free(zone1, NULL);
|
|
|
|
conf_io_abort(false);
|
|
}
|
|
|
|
static void test_conf_io_diff(void)
|
|
{
|
|
const char *ref;
|
|
char out[OUT_LEN];
|
|
|
|
conf_io_t io = {
|
|
.fcn = format_item,
|
|
.misc = out
|
|
};
|
|
|
|
// ERR no txn.
|
|
ok(conf_io_diff("server", "version", NULL, &io) ==
|
|
KNOT_TXN_ENOTEXISTS, "diff without active txn");
|
|
|
|
ok(conf_io_begin(false) == KNOT_EOK, "begin txn");
|
|
|
|
// ERR.
|
|
ok(conf_io_diff("", NULL, NULL, &io) ==
|
|
KNOT_YP_EINVAL_ITEM, "diff empty key0");
|
|
ok(conf_io_diff("unknown", NULL, NULL, &io) ==
|
|
KNOT_YP_EINVAL_ITEM, "diff unknown key0");
|
|
ok(conf_io_diff("server", "unknown", NULL, &io) ==
|
|
KNOT_YP_EINVAL_ITEM, "diff unknown key1");
|
|
ok(conf_io_diff("include", NULL, NULL, &io) ==
|
|
KNOT_ENOTSUP, "diff non-group item");
|
|
|
|
*out = '\0';
|
|
ok(conf_io_diff(NULL, NULL, NULL, &io) == KNOT_EOK, "diff no change");
|
|
ref = "";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Update singlevalued item.
|
|
ok(conf_io_set("server", "version", NULL, "new text") ==
|
|
KNOT_EOK, "set single value");
|
|
|
|
*out = '\0';
|
|
ok(conf_io_diff("server", "version", NULL, &io) == KNOT_EOK, "diff single item");
|
|
ref = "-server.version = \"text\"\n"
|
|
"+server.version = \"new text\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Update multivalued item.
|
|
ok(conf_io_unset("server", "listen", NULL, "1.1.1.1") ==
|
|
KNOT_EOK, "unset multivalue");
|
|
ok(conf_io_set("server", "listen", NULL, "1.1.1.3") ==
|
|
KNOT_EOK, "set multivalue");
|
|
|
|
*out = '\0';
|
|
ok(conf_io_diff("server", "listen", NULL, &io) == KNOT_EOK, "diff multi item");
|
|
ref = "-server.listen = \"1.1.1.1\" \"1.1.1.2\"\n"
|
|
"+server.listen = \"1.1.1.2\" \"1.1.1.3\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Unset single item.
|
|
ok(conf_io_unset("zone", "comment", ZONE3, NULL) ==
|
|
KNOT_EOK, "unset multivalue");
|
|
|
|
*out = '\0';
|
|
ok(conf_io_diff("zone", NULL, ZONE3, &io) == KNOT_EOK, "diff section");
|
|
ref = "-zone[zone3.].comment = \"xyz\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Unset id.
|
|
ok(conf_io_unset("zone", NULL, ZONE1, NULL) ==
|
|
KNOT_EOK, "unset id");
|
|
ok(conf_io_unset("zone", NULL, ZONE2, NULL) ==
|
|
KNOT_EOK, "unset id");
|
|
|
|
*out = '\0';
|
|
ok(conf_io_diff("zone", NULL, ZONE2, &io) == KNOT_EOK, "diff id section");
|
|
ref = "-zone.domain = \"zone2.\"\n"
|
|
"-zone[zone2.].comment = \"abc\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
*out = '\0';
|
|
ok(conf_io_diff("zone", "domain", NULL, &io) == KNOT_EOK, "diff id");
|
|
ref = "-zone.domain = \"zone1.\"\n"
|
|
"-zone.domain = \"zone2.\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
*out = '\0';
|
|
ok(conf_io_diff(NULL, NULL, NULL, &io) == KNOT_EOK, "diff whole change");
|
|
ref = "-server.version = \"text\"\n"
|
|
"+server.version = \"new text\"\n"
|
|
"-server.listen = \"1.1.1.1\" \"1.1.1.2\"\n"
|
|
"+server.listen = \"1.1.1.2\" \"1.1.1.3\"\n"
|
|
"-zone.domain = \"zone1.\"\n"
|
|
"-zone[zone1.].file = \"name\"\n"
|
|
"-zone[zone1.].comment = \"abc\"\n"
|
|
"-zone.domain = \"zone2.\"\n"
|
|
"-zone[zone2.].comment = \"abc\"\n"
|
|
"-zone[zone3.].comment = \"xyz\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
conf_io_abort(false);
|
|
}
|
|
|
|
static void test_conf_io_list(void)
|
|
{
|
|
const char *ref;
|
|
char out[OUT_LEN];
|
|
|
|
conf_io_t io = {
|
|
.fcn = format_item,
|
|
.misc = out
|
|
};
|
|
|
|
// ERR.
|
|
ok(conf_io_list("", NULL, NULL, false, true, &io) ==
|
|
KNOT_YP_EINVAL_ITEM, "list empty key0");
|
|
ok(conf_io_list("unknown", NULL, NULL, false, true, &io) ==
|
|
KNOT_YP_EINVAL_ITEM, "list unknown key0");
|
|
ok(conf_io_list("include", NULL, NULL, false, true, &io) ==
|
|
KNOT_EOK, "list non-group item");
|
|
ok(conf_io_list("template", NULL, NULL, false, false, &io) ==
|
|
KNOT_TXN_ENOTEXISTS, "no active txn");
|
|
|
|
// Desc schema.
|
|
*out = '\0';
|
|
ok(conf_io_list(NULL, NULL, NULL, true, true, &io) ==
|
|
KNOT_EOK, "list schema");
|
|
ref = "server\n"
|
|
"xdp\n"
|
|
"control\n"
|
|
"database\n"
|
|
"remote\n"
|
|
"template\n"
|
|
"zone\n"
|
|
"include";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// Desc group.
|
|
*out = '\0';
|
|
ok(conf_io_list("server", NULL, NULL, true, true, &io) ==
|
|
KNOT_EOK, "list group");
|
|
ref = "server.version\n"
|
|
"server.listen\n"
|
|
"server.tcp-idle-timeout\n"
|
|
"server.tcp-io-timeout\n"
|
|
"server.tcp-remote-io-timeout\n"
|
|
"server.tcp-max-clients\n"
|
|
"server.tcp-reuseport\n"
|
|
"server.quic-max-clients\n"
|
|
"server.quic-idle-close-timeout\n"
|
|
"server.quic-outbuf-max-size\n"
|
|
"server.socket-affinity\n"
|
|
"server.udp-workers\n"
|
|
"server.tcp-workers\n"
|
|
"server.background-workers\n"
|
|
"server.udp-max-payload\n"
|
|
"server.udp-max-payload-ipv4\n"
|
|
"server.udp-max-payload-ipv6\n"
|
|
"server.edns-client-subnet\n"
|
|
"server.answer-rotation\n"
|
|
"server.automatic-acl\n"
|
|
"server.dbus-event";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// List item options.
|
|
*out = '\0';
|
|
ok(conf_io_list("zone", "zonefile-load", NULL, true, true, &io) ==
|
|
KNOT_EOK, "list item options");
|
|
ref = "zone.zonefile-load = \"opt1\"\n"
|
|
"zone.zonefile-load = \"opt2\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// List zone identifiers 1.
|
|
*out = '\0';
|
|
ok(conf_io_list("zone", NULL, NULL, false, true, &io) ==
|
|
KNOT_EOK, "list zone identifiers 1");
|
|
ref = "zone[zone1.]\n"
|
|
"zone[zone2.]\n"
|
|
"zone[zone3.]";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// List zone identifiers 2.
|
|
*out = '\0';
|
|
ok(conf_io_list("zone", "domain", NULL, false, true, &io) ==
|
|
KNOT_EOK, "list zone identifiers 2");
|
|
ref = "zone = \"zone1.\"\n"
|
|
"zone = \"zone2.\"\n"
|
|
"zone = \"zone3.\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// List item values.
|
|
*out = '\0';
|
|
ok(conf_io_list("server", "listen", NULL, false, true, &io) ==
|
|
KNOT_EOK, "list item values");
|
|
ref = "server.listen = \"1.1.1.1\" \"1.1.1.2\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
|
|
// List multi-group item values.
|
|
*out = '\0';
|
|
ok(conf_io_list("zone", "file", "zone1", false, true, &io) ==
|
|
KNOT_EOK, "list multi-group item values");
|
|
ref = "zone[zone1.].file = \"name\"";
|
|
ok(strcmp(ref, out) == 0, "compare result");
|
|
}
|
|
|
|
static const yp_item_t desc_server[] = {
|
|
{ C_VERSION, YP_TSTR, YP_VNONE },
|
|
{ C_LISTEN, YP_TADDR, YP_VNONE, YP_FMULTI },
|
|
// Required config cache items - assert fix.
|
|
{ C_TCP_IDLE_TIMEOUT, YP_TINT, YP_VNONE },
|
|
{ C_TCP_IO_TIMEOUT, YP_TINT, YP_VNONE },
|
|
{ C_TCP_RMT_IO_TIMEOUT, YP_TINT, YP_VNONE },
|
|
{ C_TCP_MAX_CLIENTS, YP_TINT, YP_VNONE },
|
|
{ C_TCP_REUSEPORT, YP_TBOOL, YP_VNONE },
|
|
{ C_QUIC_MAX_CLIENTS, YP_TINT, YP_VNONE },
|
|
{ C_QUIC_IDLE_CLOSE, YP_TINT, YP_VNONE },
|
|
{ C_QUIC_OUTBUF_MAX_SIZE, YP_TINT, YP_VNONE },
|
|
{ C_SOCKET_AFFINITY, YP_TBOOL, YP_VNONE },
|
|
{ C_UDP_WORKERS, YP_TINT, YP_VNONE },
|
|
{ C_TCP_WORKERS, YP_TINT, YP_VNONE },
|
|
{ C_BG_WORKERS, YP_TINT, YP_VNONE },
|
|
{ C_UDP_MAX_PAYLOAD, YP_TINT, YP_VNONE },
|
|
{ C_UDP_MAX_PAYLOAD_IPV4, YP_TINT, YP_VNONE },
|
|
{ C_UDP_MAX_PAYLOAD_IPV6, YP_TINT, YP_VNONE },
|
|
{ C_ECS, YP_TBOOL, YP_VNONE },
|
|
{ C_ANS_ROTATION, YP_TBOOL, YP_VNONE },
|
|
{ C_AUTO_ACL, YP_TBOOL, YP_VNONE },
|
|
{ C_DBUS_EVENT, YP_TOPT, YP_VNONE },
|
|
{ NULL }
|
|
};
|
|
|
|
static const yp_item_t desc_xdp[] = {
|
|
{ C_UDP, YP_TBOOL, YP_VNONE },
|
|
{ C_TCP, YP_TBOOL, YP_VNONE },
|
|
{ C_QUIC, YP_TBOOL, YP_VNONE },
|
|
{ C_TCP_MAX_CLIENTS, YP_TINT, YP_VNONE },
|
|
{ C_TCP_INBUF_MAX_SIZE, YP_TINT, YP_VNONE },
|
|
{ C_TCP_OUTBUF_MAX_SIZE,YP_TINT, YP_VNONE },
|
|
{ C_TCP_IDLE_CLOSE, YP_TINT, YP_VNONE },
|
|
{ C_TCP_IDLE_RESET, YP_TINT, YP_VNONE },
|
|
{ C_TCP_RESEND, YP_TINT, YP_VNONE },
|
|
{ C_ROUTE_CHECK, YP_TBOOL, YP_VNONE },
|
|
{ C_RING_SIZE, YP_TINT, YP_VNONE },
|
|
{ C_BUSYPOLL_BUDGET, YP_TINT, YP_VNONE },
|
|
{ C_BUSYPOLL_TIMEOUT, YP_TINT, YP_VNONE },
|
|
{ NULL }
|
|
};
|
|
|
|
static const yp_item_t desc_control[] = {
|
|
{ C_TIMEOUT, YP_TINT, YP_VNONE },
|
|
{ NULL }
|
|
};
|
|
|
|
static const yp_item_t desc_remote[] = {
|
|
{ C_ID, YP_TSTR, YP_VNONE },
|
|
{ C_ADDR, YP_TADDR, YP_VNONE, YP_FMULTI },
|
|
{ NULL }
|
|
};
|
|
|
|
static const yp_item_t desc_database[] = {
|
|
{ C_TIMER_DB_SYNC, YP_TOPTINT, YP_VNONE },
|
|
{ NULL }
|
|
};
|
|
|
|
static const knot_lookup_t opts[] = {
|
|
{ 1, "opt1" },
|
|
{ 2, "opt2" },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
#define ZONE_ITEMS \
|
|
{ C_FILE, YP_TSTR, YP_VNONE }, \
|
|
{ C_MASTER, YP_TREF, YP_VREF = { C_RMT }, YP_FMULTI, { check_ref } }, \
|
|
{ C_ZONEFILE_LOAD, YP_TOPT, YP_VOPT = { opts, 0 } }, \
|
|
{ C_JOURNAL_CONTENT, YP_TOPT, YP_VOPT = { opts, 0 } }, \
|
|
{ C_DNSSEC_SIGNING, YP_TBOOL, YP_VNONE }, \
|
|
{ C_DNSSEC_VALIDATION, YP_TBOOL, YP_VNONE }, \
|
|
{ C_SERIAL_MODULO, YP_TSTR, YP_VSTR = { "0/1" } }, \
|
|
{ C_ZONEMD_VERIFY, YP_TBOOL, YP_VNONE }, \
|
|
{ C_CATALOG_ROLE, YP_TOPT, YP_VOPT = { opts, 0 } }, \
|
|
{ C_CATALOG_TPL, YP_TREF, YP_VREF = { C_RMT } }, \
|
|
{ C_COMMENT, YP_TSTR, YP_VNONE },
|
|
|
|
static const yp_item_t desc_template[] = {
|
|
{ C_ID, YP_TSTR, YP_VNONE },
|
|
ZONE_ITEMS
|
|
{ NULL }
|
|
};
|
|
|
|
static const yp_item_t desc_zone[] = {
|
|
{ C_DOMAIN, YP_TDNAME, YP_VNONE },
|
|
ZONE_ITEMS
|
|
{ NULL }
|
|
};
|
|
|
|
const yp_item_t test_schema[] = {
|
|
{ C_SRV, YP_TGRP, YP_VGRP = { desc_server } },
|
|
{ C_XDP, YP_TGRP, YP_VGRP = { desc_xdp } },
|
|
{ C_CTL, YP_TGRP, YP_VGRP = { desc_control } },
|
|
{ C_DB, YP_TGRP, YP_VGRP = { desc_database } },
|
|
{ C_RMT, YP_TGRP, YP_VGRP = { desc_remote }, YP_FMULTI, { check_remote } },
|
|
{ C_TPL, YP_TGRP, YP_VGRP = { desc_template }, YP_FMULTI, { check_template } },
|
|
{ C_ZONE, YP_TGRP, YP_VGRP = { desc_zone }, YP_FMULTI, { check_zone } },
|
|
{ C_INCL, YP_TSTR, YP_VNONE, YP_FNONE, { include_file } },
|
|
{ NULL }
|
|
};
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
plan_lazy();
|
|
|
|
ok(test_conf("", test_schema) == KNOT_EOK, "Prepare configuration");
|
|
|
|
diag("conf_io_begin");
|
|
test_conf_io_begin();
|
|
|
|
diag("conf_io_abort");
|
|
test_conf_io_abort();
|
|
|
|
diag("conf_io_commit");
|
|
test_conf_io_commit();
|
|
|
|
diag("conf_io_check");
|
|
test_conf_io_check();
|
|
|
|
diag("conf_io_set");
|
|
test_conf_io_set();
|
|
|
|
diag("conf_io_unset");
|
|
test_conf_io_unset();
|
|
|
|
diag("conf_io_get");
|
|
test_conf_io_get();
|
|
|
|
diag("conf_io_diff");
|
|
test_conf_io_diff();
|
|
|
|
diag("conf_io_list");
|
|
test_conf_io_list();
|
|
|
|
conf_free(conf());
|
|
|
|
return 0;
|
|
}
|