summaryrefslogtreecommitdiffstats
path: root/tests/libknot/test_ypschema.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/libknot/test_ypschema.c')
-rw-r--r--tests/libknot/test_ypschema.c417
1 files changed, 417 insertions, 0 deletions
diff --git a/tests/libknot/test_ypschema.c b/tests/libknot/test_ypschema.c
new file mode 100644
index 0000000..728a847
--- /dev/null
+++ b/tests/libknot/test_ypschema.c
@@ -0,0 +1,417 @@
+/* Copyright (C) 2019 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <tap/basic.h>
+
+#include "libknot/yparser/ypschema.h"
+#include "libknot/yparser/yptrafo.h"
+#include "libknot/libknot.h"
+
+#define C_ID "\x02""id"
+#define C_INT "\x07""integer"
+#define C_BOOL "\x04""bool"
+#define C_OPT "\x06""option"
+#define C_STR "\x06""string"
+#define C_ADDR "\x07""address"
+#define C_DNAME "\x05""dname"
+#define C_HEX "\x03""hex"
+#define C_BASE64 "\x06""base64"
+#define C_DATA "\x04""data"
+#define C_REF "\x09""reference"
+#define C_GRP "\x05""group"
+#define C_MULTIGRP "\x0B""multi-group"
+
+static const yp_item_t group[] = {
+ { C_INT, YP_TINT, YP_VINT = { 0, 100, YP_NIL } },
+ { C_STR, YP_TSTR, YP_VNONE, YP_FMULTI },
+ { NULL }
+};
+
+static const yp_item_t multi_group[] = {
+ { C_ID, YP_TSTR, YP_VNONE },
+ { C_HEX, YP_THEX, YP_VNONE },
+ { C_BASE64, YP_TB64, YP_VNONE },
+ { NULL }
+};
+
+static const knot_lookup_t opts[] = {
+ { 1, "one" },
+ { 10, "ten" },
+ { 0, NULL }
+ };
+
+static const yp_item_t static_schema[] = {
+ { C_OPT, YP_TOPT, YP_VOPT = { opts } },
+ { C_BOOL, YP_TBOOL, YP_VNONE },
+ { C_DNAME, YP_TDNAME, YP_VNONE },
+ { C_GRP, YP_TGRP, YP_VGRP = { group } },
+ { C_MULTIGRP, YP_TGRP, YP_VGRP = { multi_group }, YP_FMULTI },
+ { C_REF, YP_TREF, YP_VREF = { C_MULTIGRP } },
+ { C_DATA, YP_TDATA, YP_VNONE },
+ { NULL }
+};
+
+static void schema_find_test(void)
+{
+ yp_item_t *schema = NULL;
+
+ int ret = yp_schema_copy(&schema, static_schema);
+ is_int(KNOT_EOK, ret, "schema copy");
+
+ const yp_item_t *i = yp_schema_find(C_OPT, NULL, schema);
+ ok(i != NULL, "schema find");
+ if (i == NULL) {
+ goto error_schema;
+ }
+ ok(strcmp(&i->name[1], &C_OPT[1]) == 0, "name check");
+
+ i = yp_schema_find(C_STR, C_GRP, schema);
+ ok(i != NULL, "schema find with parent");
+ if (i == NULL) {
+ goto error_schema;
+ }
+ ok(strcmp(&i->name[1], &C_STR[1]) == 0, "name check");
+
+ i = yp_schema_find(C_ADDR, NULL, schema);
+ ok(i == NULL, "schema not find");
+
+ i = yp_schema_find(C_ADDR, C_GRP, schema);
+ ok(i == NULL, "schema not find with parent");
+
+error_schema:
+ yp_schema_free(schema);
+}
+
+static void schema_merge_test(void)
+{
+ static const yp_item_t items1[] = {
+ { "\x01""1", YP_TSTR, YP_VNONE },
+ { "\x01""2", YP_TSTR, YP_VNONE },
+ { NULL }
+ };
+
+ static const yp_item_t items2[] = {
+ { "\x01""3", YP_TSTR, YP_VNONE },
+ { "\x01""4", YP_TSTR, YP_VNONE },
+ { NULL }
+ };
+
+ yp_item_t *schema = NULL;
+ yp_item_t *tmp = NULL;
+
+ int ret = yp_schema_copy(&tmp, items1);
+ is_int(KNOT_EOK, ret, "schema copy");
+
+ ret = yp_schema_merge(&schema, items1, items2);
+ is_int(KNOT_EOK, ret, "schema merge");
+
+ yp_schema_free(tmp);
+
+ for (uint8_t i = 0; i < 4; i++) {
+ yp_name_t name[3] = { '\x01', '1' + i };
+ const yp_item_t *item = yp_schema_find(name, NULL, schema);
+ ok(item != NULL, "schema find");
+ }
+
+ yp_schema_free(schema);
+}
+
+#define SET_INPUT_STR(str) \
+ ret = yp_set_input_string(yp, str, strlen(str)); \
+ is_int(KNOT_EOK, ret, "set input string");
+
+#define PARSER_CHECK(depth) \
+ ret = yp_parse(yp); \
+ is_int(KNOT_EOK, ret, "parse"); \
+ ret = yp_schema_check_parser(ctx, yp); \
+ is_int(KNOT_EOK, ret, "check parser"); \
+ node = &ctx->nodes[ctx->current]; \
+ parent = node->parent; \
+ ok(ctx->current == depth, "depth check");
+
+#define PARSER_RET_CHECK(code) \
+ ret = yp_parse(yp); \
+ is_int(KNOT_EOK, ret, "parse"); \
+ ret = yp_schema_check_parser(ctx, yp); \
+ ok(ret == code, "return check parser");
+
+static void parser_test(void)
+{
+ yp_parser_t yparser;
+ yp_parser_t *yp = &yparser;
+ yp_item_t *schema = NULL;
+ yp_check_ctx_t *ctx = NULL;
+
+ yp_init(yp);
+
+ int ret = yp_schema_copy(&schema, static_schema);
+ is_int(KNOT_EOK, ret, "schema copy");
+ if (ret != KNOT_EOK) {
+ goto error_parser;
+ }
+
+ ctx = yp_schema_check_init(&schema);
+ ok(ctx != NULL, "create check ctx");
+ if (ctx == NULL) {
+ goto error_parser;
+ }
+
+ yp_node_t *node;
+ yp_node_t *parent;
+ const yp_item_t *id;
+
+ diag("parser key0 test");
+ SET_INPUT_STR("option: one");
+ PARSER_CHECK(0);
+ ok(strcmp(node->item->name + 1, "option") == 0, "name check");
+ ok(node->item->type == YP_TOPT, "type check");
+ ok(yp_opt(node->data) == 1, "value check");
+
+ diag("parser group test");
+ SET_INPUT_STR("group:\n integer: 20\n string: [short, \"long string\"]");
+ PARSER_CHECK(0);
+ ok(strcmp(node->item->name + 1, "group") == 0, "name check");
+ ok(node->item->type == YP_TGRP, "type check");
+ ok(node->data_len == 0, "value length check");
+ PARSER_CHECK(1);
+ ok(strcmp(node->item->name + 1, "integer") == 0, "name check");
+ ok(node->item->type == YP_TINT, "type check");
+ ok(yp_int(node->data) == 20, "value check");
+ PARSER_CHECK(1);
+ ok(strcmp(node->item->name + 1, "string") == 0, "name check");
+ ok(node->item->type == YP_TSTR, "type check");
+ ok(strcmp(yp_str(node->data), "short") == 0, "value check");
+ PARSER_CHECK(1);
+ ok(strcmp(node->item->name + 1, "string") == 0, "name check");
+ ok(node->item->type == YP_TSTR, "type check");
+ ok(strcmp(yp_str(node->data), "long string") == 0, "value check");
+
+ diag("parser multi-group test");
+ SET_INPUT_STR("multi-group:\n - id: foo\n base64: Zm9vYmFy\nreference: foo");
+ PARSER_CHECK(0);
+ ok(strcmp(node->item->name + 1, "multi-group") == 0, "name check");
+ ok(node->item->type == YP_TGRP, "type check");
+ ok(node->data_len == 0, "value length check");
+ PARSER_CHECK(0);
+ ok(node->id_len > 0, "id check");
+ ok(strcmp(node->item->name + 1, "multi-group") == 0, "name check");
+ ok(node->item->type == YP_TGRP, "type check");
+ ok(node->data_len == 0, "value length check");
+ id = node->item->var.g.id;
+ ok(strcmp(id->name + 1, "id") == 0, "name check");
+ ok(id->type == YP_TSTR, "type check");
+ ok(strcmp(yp_str(node->id), "foo") == 0, "value check");
+ PARSER_CHECK(1);
+ id = parent->item->var.g.id;
+ ok(strcmp(parent->item->name + 1, "multi-group") == 0, "name check");
+ ok(parent->item->type == YP_TGRP, "type check");
+ ok(parent->data_len == 0, "value length check");
+ ok(strcmp(yp_str(parent->id), "foo") == 0, "value check");
+ ok(strcmp(id->name + 1, "id") == 0, "name check");
+ ok(id->type == YP_TSTR, "type check");
+ ok(strcmp(node->item->name + 1, "base64") == 0, "name check");
+ ok(node->item->type == YP_TB64, "type check");
+ ok(memcmp(yp_bin(node->data), "foobar", yp_bin_len(node->data)) == 0,
+ "value check");
+ ok(node->id_len == 0, "id length check");
+ PARSER_CHECK(0);
+ ok(strcmp(node->item->name + 1, "reference") == 0, "name check");
+ ok(node->item->type == YP_TREF, "type check");
+ ok(strcmp(yp_str(node->data), "foo") == 0, "value check");
+
+ diag("parser check return");
+ SET_INPUT_STR("unknown:");
+ PARSER_RET_CHECK(KNOT_YP_EINVAL_ITEM);
+
+ SET_INPUT_STR("group:\n unknown:");
+ PARSER_RET_CHECK(KNOT_EOK);
+ PARSER_RET_CHECK(KNOT_YP_EINVAL_ITEM);
+
+ SET_INPUT_STR("group:\n - unknown: data");
+ PARSER_RET_CHECK(KNOT_EOK);
+ PARSER_RET_CHECK(KNOT_YP_EINVAL_ITEM);
+
+ SET_INPUT_STR("group:\n - hex: data");
+ PARSER_RET_CHECK(KNOT_EOK);
+ PARSER_RET_CHECK(KNOT_YP_EINVAL_ITEM);
+
+ SET_INPUT_STR("dname:");
+ PARSER_RET_CHECK(KNOT_EINVAL);
+
+ SET_INPUT_STR("group: data");
+ PARSER_RET_CHECK(KNOT_YP_ENOTSUP_DATA);
+
+ SET_INPUT_STR("group:\n integer:");
+ PARSER_RET_CHECK(KNOT_EOK);
+ PARSER_RET_CHECK(KNOT_EINVAL);
+
+ SET_INPUT_STR("multi-group:\n id:");
+ PARSER_RET_CHECK(KNOT_EOK);
+ PARSER_RET_CHECK(KNOT_YP_ENODATA);
+
+ SET_INPUT_STR("multi-group:\n hex:");
+ PARSER_RET_CHECK(KNOT_EOK);
+ PARSER_RET_CHECK(KNOT_YP_ENOID);
+
+error_parser:
+ yp_schema_check_deinit(ctx);
+ yp_schema_free(schema);
+ yp_deinit(yp);
+}
+
+#define STR_CHECK(depth, key0, key1, id, data) \
+ ret = yp_schema_check_str(ctx, key0, key1, id, data); \
+ is_int(KNOT_EOK, ret, "check str"); \
+ ok(ctx->current == depth, "depth check"); \
+ node = &ctx->nodes[ctx->current]; \
+ parent = node->parent;
+
+#define STR_RET_CHECK(code, key0, key1, id, data) \
+ ret = yp_schema_check_str(ctx, key0, key1, id, data); \
+ ok(ret == code, "return check str");
+
+static void str_test(void)
+{
+ yp_item_t *schema;
+ yp_check_ctx_t *ctx = NULL;
+
+ int ret = yp_schema_copy(&schema, static_schema);
+ is_int(KNOT_EOK, ret, "schema copy");
+ if (ret != KNOT_EOK) {
+ goto error_str;
+ }
+
+ ctx = yp_schema_check_init(&schema);
+ ok(ctx != NULL, "create check ctx");
+ if (ctx == NULL) {
+ goto error_str;
+ }
+
+ yp_node_t *node;
+ yp_node_t *parent;
+ const yp_item_t *id;
+
+ diag("str key0 test");
+ STR_CHECK(0, "option", NULL, NULL, "one");
+ ok(strcmp(node->item->name + 1, "option") == 0, "name check");
+ ok(node->item->type == YP_TOPT, "type check");
+ ok(yp_opt(node->data) == 1, "value check");
+
+ diag("str group test");
+ STR_CHECK(0, "group", NULL, NULL, NULL);
+ ok(strcmp(node->item->name + 1, "group") == 0, "name check");
+ ok(node->item->type == YP_TGRP, "type check");
+ ok(node->data_len == 0, "value length check");
+ STR_CHECK(1, "group", "integer", NULL, "20");
+ ok(strcmp(node->item->name + 1, "integer") == 0, "name check");
+ ok(node->item->type == YP_TINT, "type check");
+ ok(yp_int(node->data) == 20, "value check");
+ STR_CHECK(1, "group", "string", NULL, "short");
+ ok(strcmp(node->item->name + 1, "string") == 0, "name check");
+ ok(node->item->type == YP_TSTR, "type check");
+ ok(strcmp(yp_str(node->data), "short") == 0, "value check");
+ STR_CHECK(1, "group", "string", NULL, "long string");
+ ok(strcmp(node->item->name + 1, "string") == 0, "name check");
+ ok(node->item->type == YP_TSTR, "type check");
+ ok(strcmp(yp_str(node->data), "long string") == 0, "value check");
+
+ diag("str multi-group test");
+ STR_CHECK(0, "multi-group", NULL, NULL, NULL);
+ ok(strcmp(node->item->name + 1, "multi-group") == 0, "name check");
+ ok(node->item->type == YP_TGRP, "type check");
+ ok(node->data_len == 0, "value length check");
+ STR_CHECK(0, "multi-group", NULL, "foo", NULL);
+ ok(node->id_len > 0, "id check");
+ ok(strcmp(node->item->name + 1, "multi-group") == 0, "name check");
+ ok(node->item->type == YP_TGRP, "type check");
+ ok(node->data_len == 0, "value length check");
+ id = node->item->var.g.id;
+ ok(strcmp(id->name + 1, "id") == 0, "name check");
+ ok(id->type == YP_TSTR, "type check");
+ ok(strcmp(yp_str(node->id), "foo") == 0, "value check");
+ STR_CHECK(1, "multi-group", "base64", "foo", "Zm9vYmFy");
+ id = parent->item->var.g.id;
+ ok(strcmp(parent->item->name + 1, "multi-group") == 0, "name check");
+ ok(parent->item->type == YP_TGRP, "type check");
+ ok(parent->data_len == 0, "value length check");
+ ok(strcmp(yp_str(parent->id), "foo") == 0, "value check");
+ ok(strcmp(id->name + 1, "id") == 0, "name check");
+ ok(id->type == YP_TSTR, "type check");
+ ok(strcmp(node->item->name + 1, "base64") == 0, "name check");
+ ok(node->item->type == YP_TB64, "type check");
+ ok(memcmp(yp_bin(node->data), "foobar", yp_bin_len(node->data)) == 0,
+ "value check");
+ ok(node->id_len == 0, "id length check");
+ STR_CHECK(0, "reference", NULL, NULL, "foo");
+ ok(strcmp(node->item->name + 1, "reference") == 0, "name check");
+ ok(node->item->type == YP_TREF, "type check");
+ ok(strcmp(yp_str(node->data), "foo") == 0, "value check");
+
+ diag("str check return");
+ STR_RET_CHECK(KNOT_YP_EINVAL_ITEM, "", "", "", "");
+ STR_RET_CHECK(KNOT_YP_EINVAL_ITEM, NULL, NULL, NULL, NULL);
+ STR_RET_CHECK(KNOT_YP_EINVAL_ITEM, "unknown", NULL, NULL, NULL);
+ STR_RET_CHECK(KNOT_YP_EINVAL_ITEM, NULL, "unknown", NULL, NULL);
+ STR_RET_CHECK(KNOT_EINVAL, "dname", "", "", "");
+ STR_RET_CHECK(KNOT_EOK, "dname", NULL, NULL, NULL);
+ STR_RET_CHECK(KNOT_EOK, "dname", NULL, NULL, ".");
+ STR_RET_CHECK(KNOT_EINVAL, "dname", NULL, NULL, "..");
+ STR_RET_CHECK(KNOT_YP_ENOTSUP_ID, "dname", NULL, "id", NULL);
+ STR_RET_CHECK(KNOT_YP_EINVAL_ITEM, "dname", "unknown", NULL, NULL);
+
+ STR_RET_CHECK(KNOT_EOK, "group", "", "", "");
+ STR_RET_CHECK(KNOT_EOK, "group", NULL, NULL, NULL);
+ STR_RET_CHECK(KNOT_YP_ENOTSUP_DATA, "group", "", "", "data");
+ STR_RET_CHECK(KNOT_YP_EINVAL_ITEM, "group", "unknown", NULL, NULL);
+ STR_RET_CHECK(KNOT_EOK, "group", "string", NULL, NULL);
+ STR_RET_CHECK(KNOT_EOK, "group", "string", NULL, "data");
+ STR_RET_CHECK(KNOT_EOK, "group", "string", NULL, "");
+ STR_RET_CHECK(KNOT_YP_ENOTSUP_ID, "group", "", "id", NULL);
+ STR_RET_CHECK(KNOT_YP_ENOTSUP_ID, "group", "string", "id", NULL);
+
+ STR_RET_CHECK(KNOT_EOK, "multi-group", "", "", "");
+ STR_RET_CHECK(KNOT_EOK, "multi-group", NULL, NULL, NULL);
+ STR_RET_CHECK(KNOT_YP_ENOTSUP_DATA, "multi-group", NULL, NULL, "data");
+ STR_RET_CHECK(KNOT_EOK, "multi-group", NULL, "idval", NULL);
+ STR_RET_CHECK(KNOT_YP_ENOTSUP_DATA, "multi-group", NULL, "idval", "data");
+ STR_RET_CHECK(KNOT_EOK, "multi-group", "hex", "idval", NULL);
+ STR_RET_CHECK(KNOT_EOK, "multi-group", "hex", "idval", "data");
+ STR_RET_CHECK(KNOT_EOK, "multi-group", "hex", NULL, NULL);
+ STR_RET_CHECK(KNOT_EOK, "multi-group", "hex", NULL, "data");
+ STR_RET_CHECK(KNOT_EOK, "multi-group", "id", "", NULL);
+ STR_RET_CHECK(KNOT_EOK, "multi-group", "id", NULL, "idval");
+ STR_RET_CHECK(KNOT_EOK, "multi-group", "id", "idval", NULL);
+ STR_RET_CHECK(KNOT_YP_ENOTSUP_DATA, "multi-group", "id", "idval", "data");
+
+error_str:
+ yp_schema_check_deinit(ctx);
+ yp_schema_free(schema);
+}
+
+int main(int argc, char *argv[])
+{
+ plan_lazy();
+
+ schema_find_test();
+ schema_merge_test();
+ parser_test();
+ str_test();
+
+ return 0;
+}