diff options
Diffstat (limited to 'tests/utests/types/string.c')
-rw-r--r-- | tests/utests/types/string.c | 1410 |
1 files changed, 1410 insertions, 0 deletions
diff --git a/tests/utests/types/string.c b/tests/utests/types/string.c new file mode 100644 index 0000000..d232e9d --- /dev/null +++ b/tests/utests/types/string.c @@ -0,0 +1,1410 @@ +/** + * @file string.c + * @author Radek Iša <isa@cesnet.cz> + * @brief test for string values + * + * Copyright (c) 2021 CESNET, z.s.p.o. + * + * This source code is licensed under BSD 3-Clause License (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + */ + +#define _UTEST_MAIN_ +#include "../utests.h" + +/* GLOBAL INCLUDE HEADERS */ +#include <ctype.h> + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" +#include "path.h" +#include "plugins_internal.h" + +#define MODULE_CREATE_YIN(MOD_NAME, NODES) \ + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" \ + "<module name=\"" MOD_NAME "\"\n" \ + " xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"\n" \ + " xmlns:pref=\"urn:tests:" MOD_NAME "\">\n" \ + " <yang-version value=\"1.1\"/>\n" \ + " <namespace uri=\"urn:tests:" MOD_NAME "\"/>\n" \ + " <prefix value=\"pref\"/>\n" \ + NODES \ + "</module>\n" + +#define MODULE_CREATE_YANG(MOD_NAME, NODES) \ + "module " MOD_NAME " {\n" \ + " yang-version 1.1;\n" \ + " namespace \"urn:tests:" MOD_NAME "\";\n" \ + " prefix pref;\n" \ + NODES \ + "}\n" + +#define TEST_SUCCESS_XML(MOD_NAME, DATA, TYPE, ...)\ + {\ + struct lyd_node *tree;\ + const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>";\ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);\ + CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0);\ + CHECK_LYD_NODE_TERM((struct lyd_node_term *) tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__);\ + lyd_free_all(tree);\ + } + +#define TEST_SUCCESS_JSON(MOD_NAME, DATA, TYPE, ...)\ + {\ + struct lyd_node *tree;\ + const char *data = "{\"" MOD_NAME ":port\":\"" DATA "\"}";\ + CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);\ + CHECK_LYSC_NODE(tree->schema, NULL, 0, 0x5, 1, "port", 0, LYS_LEAF, 0, 0, 0, 0);\ + CHECK_LYD_NODE_TERM((struct lyd_node_term *) tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__);\ + lyd_free_all(tree);\ + } + +#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME, DATA) \ + { \ + struct lyd_node *tree_1; \ + struct lyd_node *tree_2; \ + char *xml_out, *data; \ + data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, LY_SUCCESS, tree_1); \ + assert_int_equal(lyd_print_mem(&xml_out, tree_1, LYD_LYB, LYD_PRINT_WITHSIBLINGS), 0); \ + assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, xml_out, LYD_LYB, LYD_PARSE_ONLY | LYD_PARSE_STRICT, 0, &tree_2)); \ + assert_non_null(tree_2); \ + CHECK_LYD(tree_1, tree_2); \ + free(xml_out); \ + lyd_free_all(tree_1); \ + lyd_free_all(tree_2); \ + } + +#define TEST_ERROR_XML(MOD_NAME, DATA)\ + {\ + struct lyd_node *tree;\ + const char *data = "<port xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</port>";\ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);\ + assert_null(tree);\ + } + +#define TEST_ERROR_JSON(MOD_NAME, DATA)\ + {\ + struct lyd_node *tree;\ + const char *data = "{\"" MOD_NAME ":port\":\"" DATA "\"}";\ + CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);\ + assert_null(tree);\ + } + +static void +test_schema_yang(void **state) +{ + const char *schema; + struct lys_module *mod; + struct lysc_node_leaf *lysc_leaf; + struct lysp_node_leaf *lysp_leaf; + struct lysc_pattern *pattern; + struct lysc_range *range; + + /* TEST BASE STRING */ + schema = MODULE_CREATE_YANG("base", "leaf port {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_STRING, 0, 0); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "string", 0, 0, 1, 0, 0, 0); + + /* TEST MODULE T0 */ + schema = MODULE_CREATE_YANG("T0", "leaf port {type string" + "{length \"10 .. max\";}" + "}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 0); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_u64, 10); + assert_true(range->parts[0].max_u64 == 18446744073709551615ull); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x10, 0, 1, "string", 0, 0, 1, 0, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.length, "10 .. max", NULL, NULL, NULL, 0, NULL); + + /* TEST MODULE T1 */ + schema = MODULE_CREATE_YANG("T1", "leaf port {type string" + "{length \"min .. 20 | 50\";}" + "}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 0); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_u64, 0); + assert_int_equal(range->parts[0].max_u64, 20); + assert_int_equal(range->parts[1].min_u64, 50); + assert_int_equal(range->parts[1].max_u64, 50); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x10, 0, 1, "string", 0, 0, 1, 0, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.length, "min .. 20 | 50", NULL, NULL, NULL, 0, NULL); + + /* TEST MODULE T2 */ + schema = MODULE_CREATE_YANG("T2", "leaf port {type string" + "{length \"10 .. 20 | 50 .. 100 | 255\";}" + "}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 0); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 3, NULL); + assert_int_equal(range->parts[0].min_u64, 10); + assert_int_equal(range->parts[0].max_u64, 20); + assert_int_equal(range->parts[1].min_u64, 50); + assert_int_equal(range->parts[1].max_u64, 100); + assert_int_equal(range->parts[2].min_u64, 255); + assert_int_equal(range->parts[2].max_u64, 255); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x10, 0, 1, "string", 0, 0, 1, 0, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.length, "10 .. 20 | 50 .. 100 | 255", NULL, NULL, NULL, 0, NULL); + + /* SUBTYPE MODULE T2 */ + schema = MODULE_CREATE_YANG("TS0", + "typedef my_type {" + " type string {length \"10 .. 20 | 50 .. 100 | 255\";}" + "}" + "leaf port {type my_type {length \"min .. 15 | max\";}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 0); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_u64, 10); + assert_int_equal(range->parts[0].max_u64, 15); + assert_int_equal(range->parts[1].min_u64, 255); + assert_int_equal(range->parts[1].max_u64, 255); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x10, 0, 1, "my_type", 0, 0, 1, 0, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.length, "min .. 15 | max", NULL, NULL, NULL, 0, NULL); + + /* ERROR TESTS NEGATIVE VALUE */ + schema = MODULE_CREATE_YANG("ERR0", "leaf port {type string {length \"-1 .. 20\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED); + CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "/ERR0:port"); + + schema = MODULE_CREATE_YANG("ERR1", "leaf port {type string {length \"100 .. 18446744073709551616\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid length restriction - invalid value \"18446744073709551616\".", "/ERR1:port"); + + schema = MODULE_CREATE_YANG("ERR2", "leaf port {type string {length \"10 .. 20 | 20 .. 30\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EEXIST); + CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (20).", "/ERR2:port"); + + schema = MODULE_CREATE_YANG("ERR3", + "typedef my_type {" + " type string;" + "}" + "leaf port {type my_type {length \"-1 .. 15\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED); + CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "/ERR3:port"); + + /* + * PATTERN + */ + schema = MODULE_CREATE_YANG("TPATTERN_0", "leaf port {type string" + "{pattern '[a-zA-Z_][a-zA-Z0-9\\-_.]*';}" + "}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 1); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[a-zA-Z_][a-zA-Z0-9\\-_.]*", 0, 0, NULL); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "string", 0, 1, 1, 0, 0, 0); + CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[a-zA-Z_][a-zA-Z0-9\\-_.]*", NULL, NULL, NULL, 0, NULL); + + schema = MODULE_CREATE_YANG("TPATTERN_1", "leaf port {type string{" + " pattern '[a-zA-Z_][a-zA-Z0-9\\-_.]*' ;" + " pattern 'abc.*' {modifier invert-match;}" + "}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 2); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[a-zA-Z_][a-zA-Z0-9\\-_.]*", 0, 0, NULL); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "abc.*", 0, 0x1, NULL); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "string", 0, 2, 1, 0, 0, 0); + CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[a-zA-Z_][a-zA-Z0-9\\-_.]*", NULL, NULL, NULL, 0, NULL); + CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[1]), "\x15" "abc.*", NULL, NULL, NULL, 0, NULL); + + schema = MODULE_CREATE_YANG("TPATTERN_2", + "typedef my_type {" + " type string{" + " pattern '[a-zA-Z_][a-zA-Z0-9\\-_.]*' ;" + " pattern 'abc.*' {modifier invert-match;}" + "}}" + "leaf port {type my_type {pattern 'bcd.*';}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 3); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[a-zA-Z_][a-zA-Z0-9\\-_.]*", 0, 0, NULL); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "abc.*", 0, 0x1, NULL); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[2]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "bcd.*", 0, 0x0, NULL); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0); + CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "bcd.*", NULL, NULL, NULL, 0, NULL); + + /* + * TEST pattern error + */ + schema = MODULE_CREATE_YANG("TPATTERN_ERR_0", "leaf port {type string {" + "pattern '[a-zA-Z_[a-zA-Z0-9\\-_.*';" + "}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Regular expression \"[a-zA-Z_[a-zA-Z0-9\\-_.*\" is not valid (\"\": missing terminating ] for character class).", + "/TPATTERN_ERR_0:port"); + + schema = MODULE_CREATE_YANG("TDEFAULT_0", + "typedef my_type {" + " type string{" + " pattern \"[a-zA-Z_][a-zA-Z0-9\\\\-_.]*\";" + " length \"2 .. 5 | 10\";" + " }" + " default \"a1i-j\";" + "}" + "leaf port {type my_type;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, "a1i-j"); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 1); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[a-zA-Z_][a-zA-Z0-9\\-_.]*", 0, 0, NULL); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_u64, 2); + assert_int_equal(range->parts[0].max_u64, 5); + assert_int_equal(range->parts[1].min_u64, 10); + assert_int_equal(range->parts[1].max_u64, 10); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0); + + /* TEST pattern backslash + * The '[' character is escaped, thus character group is broken. + */ + + schema = MODULE_CREATE_YANG("TPATTERN_BC_ERR_1", "leaf port {type string {" + "pattern '\\[a]b';" /* pattern '\[a]b'; */ + "}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Regular expression \"\\[a]b\" is not valid (\"]b\": character group doesn't begin with '[').", + "/TPATTERN_BC_ERR_1:port"); + + schema = MODULE_CREATE_YANG("TPATTERN_BC_ERR_2", "leaf port {type string {" + "pattern \"\\\\[a]b\";" /* pattern "\\[a]b"; */ + "}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Regular expression \"\\[a]b\" is not valid (\"]b\": character group doesn't begin with '[').", + "/TPATTERN_BC_ERR_2:port"); + + /* PATTERN AND LENGTH */ + schema = MODULE_CREATE_YANG("TPL_0", + "typedef my_type {" + " type string{" + " length \"2 .. 10\";" + " }" + "}" + "leaf port {type my_type{ pattern \"[a-zA-Z_][a-zA-Z0-9\\\\-_.]*\";}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 1); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[a-zA-Z_][a-zA-Z0-9\\-_.]*", 0, 0, NULL); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_u64, 2); + assert_int_equal(range->parts[0].max_u64, 10); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0); + CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[a-zA-Z_][a-zA-Z0-9\\-_.]*", + NULL, NULL, NULL, 0, NULL); +} + +static void +test_schema_yin(void **state) +{ + const char *schema; + struct lys_module *mod; + struct lysc_node_leaf *lysc_leaf; + struct lysp_node_leaf *lysp_leaf; + struct lysc_pattern *pattern; + struct lysc_range *range; + + /* TEST BASE STRING */ + schema = MODULE_CREATE_YIN("base", "<leaf name=\"port\"> <type name=\"string\"/> </leaf>"); + UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_STRING, 0, 0); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "string", 0, 0, 1, 0, 0, 0); + + /* TEST MODULE T0 */ + schema = MODULE_CREATE_YIN("T0", "<leaf name=\"port\"> <type name=\"string\">" + "<length value=\"10 .. max\"/>" + "</type> </leaf>"); + UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 0); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_u64, 10); + assert_true(range->parts[0].max_u64 == 18446744073709551615ull); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x10, 0, 1, "string", 0, 0, 1, 0, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.length, "10 .. max", NULL, NULL, NULL, 0, NULL); + + /* TEST MODULE T1 */ + schema = MODULE_CREATE_YIN("T1", "<leaf name=\"port\"> <type name=\"string\">" + " <length value=\"min .. 20 | 50\"/>" + "</type></leaf>"); + UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 0); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_u64, 0); + assert_int_equal(range->parts[0].max_u64, 20); + assert_int_equal(range->parts[1].min_u64, 50); + assert_int_equal(range->parts[1].max_u64, 50); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x10, 0, 1, "string", 0, 0, 1, 0, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.length, "min .. 20 | 50", NULL, NULL, NULL, 0, NULL); + + /* TEST MODULE T2 */ + schema = MODULE_CREATE_YIN("T2", "<leaf name=\"port\"> <type name=\"string\">" + "<length value=\"10 .. 20 | 50 .. 100 | 255\"/>" + "</type></leaf>"); + UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 0); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 3, NULL); + assert_int_equal(range->parts[0].min_u64, 10); + assert_int_equal(range->parts[0].max_u64, 20); + assert_int_equal(range->parts[1].min_u64, 50); + assert_int_equal(range->parts[1].max_u64, 100); + assert_int_equal(range->parts[2].min_u64, 255); + assert_int_equal(range->parts[2].max_u64, 255); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x10, 0, 1, "string", 0, 0, 1, 0, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.length, "10 .. 20 | 50 .. 100 | 255", NULL, NULL, NULL, 0, NULL); + + /* SUBTYPE MODULE T2 */ + schema = MODULE_CREATE_YIN("TS0", + "<typedef name=\"my_type\">" + " <type name=\"string\"> <length value=\"10 .. 20 | 50 .. 100 | 255\"/> </type>" + "</typedef>" + "<leaf name=\"port\"> <type name=\"my_type\">" + " <length value=\"min .. 15 | max\"/>" + "</type> </leaf>"); + UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 0); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_u64, 10); + assert_int_equal(range->parts[0].max_u64, 15); + assert_int_equal(range->parts[1].min_u64, 255); + assert_int_equal(range->parts[1].max_u64, 255); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x10, 0, 1, "my_type", 0, 0, 1, 0, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.length, "min .. 15 | max", NULL, NULL, NULL, 0, NULL); + + /* ERROR TESTS NEGATIVE VALUE */ + schema = MODULE_CREATE_YIN("ERR0", "<leaf name=\"port\"> <type name=\"string\">" + "<length value =\"-1 .. 20\"/> </type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EDENIED); + CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "/ERR0:port"); + + schema = MODULE_CREATE_YIN("ERR1", "<leaf name=\"port\"> <type name=\"string\">" + "<length value=\"100 .. 18446744073709551616\"/>" + "</type> </leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid length restriction - invalid value \"18446744073709551616\".", "/ERR1:port"); + + schema = MODULE_CREATE_YIN("ERR2", "<leaf name=\"port\">" + "<type name=\"string\"> <length value=\"10 .. 20 | 20 .. 30\"/>" + "</type> </leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EEXIST); + CHECK_LOG_CTX("Invalid length restriction - values are not in ascending order (20).", "/ERR2:port"); + + schema = MODULE_CREATE_YIN("ERR3", + "<typedef name=\"my_type\"> <type name=\"string\"/> </typedef>" + "<leaf name=\"port\"> <type name=\"my_type\"> <length value=\"-1 .. 15\"/>" + "</type> </leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EDENIED); + CHECK_LOG_CTX("Invalid length restriction - value \"-1\" does not fit the type limitations.", "/ERR3:port"); + + /* + * PATTERN + */ + schema = MODULE_CREATE_YIN("TPATTERN_0", "<leaf name=\"port\"> <type name=\"string\">" + "<pattern value=\"[a-zA-Z_][a-zA-Z0-9\\-_.]*\"/>" + "</type> </leaf>"); + UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 1); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[a-zA-Z_][a-zA-Z0-9\\-_.]*", 0, 0, NULL); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "string", 0, 1, 1, 0, 0, 0); + CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[a-zA-Z_][a-zA-Z0-9\\-_.]*", NULL, NULL, NULL, 0, NULL); + + schema = MODULE_CREATE_YIN("TPATTERN_1", "<leaf name=\"port\"> <type name=\"string\">" + " <pattern value=\"[a-zA-Z_][a-zA-Z0-9\\-_.]*\"/>" + " <pattern value=\"abc.*\"> <modifier value=\"invert-match\"/> </pattern>" + "</type> </leaf>"); + UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 2); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[a-zA-Z_][a-zA-Z0-9\\-_.]*", 0, 0, NULL); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "abc.*", 0, 0x1, NULL); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "string", 0, 2, 1, 0, 0, 0); + CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "[a-zA-Z_][a-zA-Z0-9\\-_.]*", NULL, NULL, NULL, 0, NULL); + CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[1]), "\x15" "abc.*", NULL, NULL, NULL, 0, NULL); + + schema = MODULE_CREATE_YIN("TPATTERN_2", + "<typedef name=\"my_type\">" + " <type name=\"string\">" + " <pattern value=\"[a-zA-Z_][a-zA-Z0-9\\-_.]*\"/>" + " <pattern value=\"abc.*\"> <modifier value=\"invert-match\"/> </pattern>" + "</type> </typedef>" + "<leaf name=\"port\"><type name=\"my_type\"> <pattern value=\"bcd.*\"/> </type></leaf>"); + UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 3); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[a-zA-Z_][a-zA-Z0-9\\-_.]*", 0, 0, NULL); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[1]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "abc.*", 0, 0x1, NULL); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[2]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "bcd.*", 0, 0x0, NULL); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x40, 0, 0, "my_type", 0, 1, 1, 0, 0, 0); + CHECK_LYSP_RESTR(&(lysp_leaf->type.patterns[0]), "\x6" "bcd.*", NULL, NULL, NULL, 0, NULL); + + /* + * TEST pattern error + * */ + schema = MODULE_CREATE_YIN("TPATTERN_ERR_0", + "<leaf name=\"port\"> <type name=\"string\">" + " <pattern value=\"[a-zA-Z_][a-zA-Z0-9\\-_.*\"/>" + "</type> </leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Regular expression \"[a-zA-Z_][a-zA-Z0-9\\-_.*\" is not valid (\"\": missing terminating ] for character class).", + "/TPATTERN_ERR_0:port"); + + /* + * DEFAUT VALUE + */ + schema = MODULE_CREATE_YIN("TDEFAULT_0", + "<typedef name=\"my_type\">" + " <type name=\"string\">" + " <pattern value=\"[a-zA-Z_][a-zA-Z0-9\\-_.]*\"/>" + " <length value=\"2 .. 5 | 10\"/>" + " </type>" + " <default value=\"a1i-j\"/>" + "</typedef>" + "<leaf name=\"port\"> <type name=\"my_type\"/> </leaf>"); + UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, "a1i-j"); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 1, 1); + pattern = ((struct lysc_type_str *)lysc_leaf->type)->patterns[0]; + CHECK_LYSC_PATTERN(pattern, NULL, NULL, NULL, "[a-zA-Z_][a-zA-Z0-9\\-_.]*", 0, 0, NULL); + range = ((struct lysc_type_str *)lysc_leaf->type)->length; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_u64, 2); + assert_int_equal(range->parts[0].max_u64, 5); + assert_int_equal(range->parts[1].min_u64, 10); + assert_int_equal(range->parts[1].max_u64, 10); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0); + + schema = MODULE_CREATE_YIN("TDEFAULT_1", + "<typedef name=\"my_type\">" + " <type name=\"string\">" + " </type>" + " <default value=\"a1i-j<\"/>" + "</typedef>" + "<leaf name=\"port\"> <type name=\"my_type\"/> </leaf>"); + UTEST_ADD_MODULE(schema, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + lysc_leaf = (void *) mod->compiled->data; + CHECK_LYSC_NODE_LEAF(lysc_leaf, NULL, 0, 0x5, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, "a1i-j<"); + CHECK_LYSC_TYPE_STR((struct lysc_type_str *)lysc_leaf->type, 0, 0, 0); + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_u64, 2); + assert_int_equal(range->parts[0].max_u64, 5); + assert_int_equal(range->parts[1].min_u64, 10); + assert_int_equal(range->parts[1].max_u64, 10); + lysp_leaf = (void *) mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0); + + schema = MODULE_CREATE_YIN("TDEFAULT_2", + "<typedef name=\"my_type\">" + " <type name=\"string\">" + " <length value=\"2\"/>" + " </type>" + " <default value=\"a1i-j<\"/>" + "</typedef>" + "<leaf name=\"port\"> <type name=\"my_type\"/> </leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + + schema = MODULE_CREATE_YIN("TDEFAULT_2", + "<typedef name=\"my_type\">" + " <type name=\"string\">" + " <length value=\"2\"/>" + " </type>" + " <default value=\"a1i-j<\"/>" + "</typedef>" + "<leaf name=\"port\"> <type name=\"my_type\"/> </leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + + schema = MODULE_CREATE_YIN("TDEFAULT_3", + "<typedef name=\"my_type\">" + " <default value=\"a1i-j<\"/>" + " <type name=\"string\">" + "</type> </typedef>" + "<leaf name=\"port\"><type name=\"my_type\"> <pattern value=\"bcd.*\"/> </type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + +} + +static void +test_schema_print(void **state) +{ + const char *schema_yang, *schema_yin; + char *printed; + struct lys_module *mod; + + /* test print yang to yin */ + schema_yang = MODULE_CREATE_YANG("PRINT0", + "leaf port {type string {" + "length \"min .. 20 | 50\";" + "pattern \"p.*\\\\\\\\\";" + "pattern 'p4.*' {modifier invert-match;}" + "}default \"p\\\"<\\\\\";}"); + schema_yin = MODULE_CREATE_YIN("PRINT0", + " <leaf name=\"port\">\n" + " <type name=\"string\">\n" + " <length value=\"min .. 20 | 50\"/>\n" + " <pattern value=\"p.*\\\\\"/>\n" + " <pattern value=\"p4.*\">\n" + " <modifier value=\"invert-match\"/>\n" + " </pattern>\n" + " </type>\n" + " <default value=\"p"<\\\"/>\n" + " </leaf>\n"); + + UTEST_ADD_MODULE(schema_yang, LYS_IN_YANG, NULL, &mod); + assert_non_null(mod); + assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YIN, 0)); + assert_string_equal(printed, schema_yin); + free(printed); + + /* test print yin to yang */ + schema_yang = MODULE_CREATE_YANG("PRINT1", + "\n" + " leaf port {\n" + " type string {\n" + " length \"min .. 20 | 50\";\n" + " pattern \"p.*\\\\\\\\\";\n" + " pattern \"p4.*\" {\n" + " modifier invert-match;\n" + " }\n" + " }\n" + " default \"p\\\"<\\\\\";\n" + " }\n"); + schema_yin = MODULE_CREATE_YIN("PRINT1", + " <leaf name=\"port\">\n" + " <type name=\"string\">\n" + " <length value=\"min .. 20 | 50\"/>\n" + " <pattern value=\"p.*\\\\\"/>\n" + " <pattern value=\"p4.*\">\n" + " <modifier value=\"invert-match\"/>\n" + " </pattern>\n" + " </type>\n" + " <default value=\"p"<\\\"/>\n" + " </leaf>\n"); + + UTEST_ADD_MODULE(schema_yin, LYS_IN_YIN, NULL, &mod); + assert_non_null(mod); + assert_int_equal(LY_SUCCESS, lys_print_mem(&printed, mod, LYS_OUT_YANG, 0)); + assert_string_equal(printed, schema_yang); + free(printed); +} + +static void +test_data_xml(void **state) +{ + const char *schema; + struct lyd_node *tree; + const char *data; + struct lysc_node_container *lysc_root; + struct lyd_node_inner *lyd_root; + + /* NO RESTRICTION TESTS */ + schema = MODULE_CREATE_YANG("T0", "leaf port {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + /* space on start and new line */ + TEST_SUCCESS_XML("T0", " 50 \n\t 64", STRING, " 50 \n\t 64"); + /* nuber as string */ + TEST_SUCCESS_XML("T0", "50", STRING, "50"); + TEST_SUCCESS_XML("T0", "+250", STRING, "+250"); + /* references */ + TEST_SUCCESS_XML("T0", """, STRING, "\""); + TEST_SUCCESS_XML("T0", "|&|", STRING, "|&|"); + TEST_SUCCESS_XML("T0", "'", STRING, "'"); + TEST_SUCCESS_XML("T0", "<", STRING, "<"); + TEST_SUCCESS_XML("T0", ">", STRING, ">"); + TEST_SUCCESS_XML("T0", "ЯЯ", STRING, "ЯЯ"); + /* special characters */ + TEST_SUCCESS_XML("T0", "\"", STRING, "\""); + TEST_SUCCESS_XML("T0", "'", STRING, "'"); + TEST_SUCCESS_XML("T0", ">", STRING, ">"); + TEST_SUCCESS_XML("T0", "", STRING, ""); + TEST_SUCCESS_XML("T0", "&<lt;", STRING, "&<lt;"); + /* CDATA IS NOT SUPPORTED + * TEST_SUCCESS_XML("T2", "<![CDATA[<greeting>Hello, world! & Wecome</greeting>]]>", STRING, + * "<greeting>Hello, world! & Wecome</greeting>"); + * COMMENT IN MIDDLE OF TEXT IS NOT SUPPORTED + * TEST_SUCCESS_XML("T2", "this isn't <!--' this is comment '-->comment", + * STRING, "this isn't comment"); + */ + + /* error */ + TEST_ERROR_XML("T0", "< df"); + CHECK_LOG_CTX("Child element \"df\" inside a terminal node \"port\" found.", + "Data location \"/T0:port\", line number 1."); + TEST_ERROR_XML("T0", "&text;"); + CHECK_LOG_CTX("Entity reference \"&text;</po\" not supported, only predefined references allowed.", "Line number 1."); + TEST_ERROR_XML("T0", "\"\""); + CHECK_LOG_CTX("Invalid character reference \"\"</port\" (0x00000008).", "Line number 1."); + + /* TEST INVERTED PATTERN ADN LENGTH */ + schema = MODULE_CREATE_YANG("T1", "leaf port {type string {" + " length \"5 .. 10 | 20\";" + " pattern '[a-zA-Z_][a-zA-Z0-9\\-_.<]*' ;" + " pattern 'p4.*' {modifier invert-match;" + " error-app-tag \"pattern-violation\"; error-message \"invalid pattern of value\";}" + "}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + /* inverted value */ + TEST_SUCCESS_XML("T1", "abcde", STRING, "abcde"); + TEST_SUCCESS_XML("T1", "abcde<", STRING, "abcde<"); + TEST_ERROR_XML("T1", "p4abc"); + CHECK_LOG_CTX_APPTAG("invalid pattern of value", "Schema location \"/T1:port\", line number 1.", "pattern-violation"); + /* size 20 */ + TEST_SUCCESS_XML("T1", "ahojahojahojahojahoj", STRING, "ahojahojahojahojahoj"); + TEST_SUCCESS_XML("T1", "abc-de", STRING, "abc-de"); + /* ERROR LENGTH */ + TEST_ERROR_XML("T1", "p4a<"); + CHECK_LOG_CTX("Unsatisfied length - string \"p4a<\" length is not allowed.", + "Schema location \"/T1:port\", line number 1."); + + /* TEST DEFAULT VALUE */ + schema = MODULE_CREATE_YANG("T2", + "container cont {\n" + " leaf port {type string {length \"0 .. 50 | 105\";} default \"test\";}" + "}"); + /* using default value */ + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + data = "<cont xmlns=\"urn:tests:" "T2" "\">" "</cont>"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lysc_root = (void *)tree->schema; + CHECK_LYSC_NODE(lysc_root->child, NULL, 0, 0x205, 1, "port", 0, LYS_LEAF, 1, 0, 0, 0); + lyd_root = ((struct lyd_node_inner *) tree); + CHECK_LYD_NODE_TERM((struct lyd_node_term *) lyd_root->child, 1, 0, 0, 1, 1, + STRING, "test");\ + lyd_free_all(tree); + + /* rewriting default value */ + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + data = "<cont xmlns=\"urn:tests:T2\">" "<port> 52 </port>" "</cont>"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lysc_root = (void *)tree->schema; + CHECK_LYSC_NODE(lysc_root->child, NULL, 0, 0x205, 1, "port", 0, LYS_LEAF, 1, 0, 0, 0); + lyd_root = ((struct lyd_node_inner *) tree); + CHECK_LYD_NODE_TERM((struct lyd_node_term *) lyd_root->child, 0, 0, 0, 1, 1, + STRING, " 52 "); + lyd_free_all(tree); + + /* WHIT STRING TEST */ + schema = MODULE_CREATE_YANG("T_WHITE", "leaf port {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_XML("T_WHITE", " \n\t", STRING, " \n\t"); + TEST_SUCCESS_XML("T_WHITE", " \n<\t", STRING, " \n<\t"); + + /* UTF-8 length and pattern*/ + schema = MODULE_CREATE_YANG("T_UTF8", "leaf port {type string {" + " length \"5 .. 10\";" + " pattern '[€]{5,7}' ;" + "}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_XML("T_UTF8", "€€€€€", STRING, "€€€€€"); + TEST_ERROR_XML("T_UTF8", "€€€"); + CHECK_LOG_CTX("Unsatisfied length - string \"€€€\" length is not allowed.", + "Schema location \"/T_UTF8:port\", line number 1."); + TEST_ERROR_XML("T_UTF8", "€€€€€€€€"); + CHECK_LOG_CTX("Unsatisfied pattern - \"€€€€€€€€\" does not conform to \"[€]{5,7}\".", + "Schema location \"/T_UTF8:port\", line number 1."); + + /* ANCHOR TEST ^$ is implicit */ + schema = MODULE_CREATE_YANG("T_ANCHOR", "leaf port {type string {" + " pattern 'a.*b' ;" + "}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_ERROR_XML("T_ANCHOR", "abc"); + CHECK_LOG_CTX("Unsatisfied pattern - \"abc\" does not conform to \"a.*b\".", + "Schema location \"/T_ANCHOR:port\", line number 1."); + TEST_ERROR_XML("T_ANCHOR", "cab"); + CHECK_LOG_CTX("Unsatisfied pattern - \"cab\" does not conform to \"a.*b\".", + "Schema location \"/T_ANCHOR:port\", line number 1."); +} + +static void +test_data_json(void **state) +{ + const char *schema; + struct lyd_node *tree; + const char *data; + struct lysc_node_container *lysc_root; + struct lyd_node_inner *lyd_root; + + /* NO RESTRICTION TESTS */ + schema = MODULE_CREATE_YANG("T0", "leaf port {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_JSON("T0", "this is text", STRING, "this is text"); + /* space on start and new line */ + TEST_SUCCESS_JSON("T0", " 50 \\n\\t 64", STRING, " 50 \n\t 64"); + /* nuber as string */ + TEST_SUCCESS_JSON("T0", "50", STRING, "50"); + TEST_SUCCESS_JSON("T0", "+250", STRING, "+250"); + /* references */ + TEST_SUCCESS_JSON("T0", "\\\"", STRING, "\""); + TEST_SUCCESS_JSON("T0", "|&|", STRING, "|&|"); + TEST_SUCCESS_JSON("T0", "<", STRING, "<"); + TEST_SUCCESS_JSON("T0", ">", STRING, ">"); + TEST_SUCCESS_JSON("T0", "\\u042F", STRING, "Я"); + TEST_SUCCESS_JSON("T0", "\\u042FFF", STRING, "ЯFF"); + /* special characters */ + TEST_SUCCESS_JSON("T0", "'", STRING, "'"); + TEST_SUCCESS_JSON("T0", ">", STRING, ">"); + TEST_SUCCESS_JSON("T0", "", STRING, ""); + TEST_SUCCESS_JSON("T0", "\\\" \\\\ \\r \\/ \\n \\t \\u20ac", STRING, "\" \\ \r / \n \t €"); + + /* ERROR invalid json string */ + TEST_ERROR_JSON("T0", "\n"); + CHECK_LOG_CTX("Invalid character in JSON string \"\n\" (0x0000000a).", + "Line number 1."); + /* backspace and form feed are valid JSON escape sequences, but the control characters they represents are not allowed values for YANG string type */ + TEST_ERROR_JSON("T0", "\\b"); + CHECK_LOG_CTX("Invalid character reference \"\\b\" (0x00000008).", "Line number 1."); + + TEST_ERROR_JSON("T0", "\\f"); + CHECK_LOG_CTX("Invalid character reference \"\\f\" (0x0000000c).", "Line number 1."); + + TEST_ERROR_JSON("T0", "\""); + CHECK_LOG_CTX("Unexpected character \"\"\" after JSON string.", "Line number 1."); + + TEST_ERROR_JSON("T0", "aabb \\x"); + CHECK_LOG_CTX("Invalid character escape sequence \\x.", "Line number 1."); + + /* TEST INVERTED PATTERN ADN LENGTH */ + schema = MODULE_CREATE_YANG("T1", "leaf port {type string {" + " length \"5 .. 10 | 20\";" + " pattern '[a-zA-Z_][a-zA-Z0-9\\-_.<]*\\n[a-zA-Z0-9\\-_.<]*' ;" + " pattern 'p4.*\\n' {modifier invert-match;}" + "}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + /* inverted value */ + TEST_SUCCESS_JSON("T1", "a\\nbcde", STRING, "a\nbcde"); + TEST_ERROR_JSON("T1", "p4abc\\n"); + CHECK_LOG_CTX("Unsatisfied pattern - \"p4abc\n\" does not conform to inverted \"p4.*\\n\".", + "Schema location \"/T1:port\", line number 1."); + /* size 20 */ + TEST_SUCCESS_JSON("T1", "ahojahojaho\\njahojaho", STRING, "ahojahojaho\njahojaho"); + TEST_SUCCESS_JSON("T1", "abc\\n-de", STRING, "abc\n-de"); + /* ERROR LENGTH */ + TEST_ERROR_JSON("T1", "p4a\u042F"); + CHECK_LOG_CTX("Unsatisfied length - string \"p4aЯ\" length is not allowed.", + "Schema location \"/T1:port\", line number 1."); + + /* TEST DEFAULT VALUE */ + schema = MODULE_CREATE_YANG("T_DEFAULT2", + "container cont {\n" + " leaf port {type string {length \"0 .. 50 | 105\";} default \"test\";}" + "}"); + /* using default value */ + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + data = "{\"T_DEFAULT2:cont\":{}}"; + CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lysc_root = (void *)tree->schema; + CHECK_LYSC_NODE(lysc_root->child, NULL, 0, 0x205, 1, "port", 0, LYS_LEAF, 1, 0, 0, 0); + lyd_root = ((struct lyd_node_inner *) tree); + CHECK_LYD_NODE_TERM((struct lyd_node_term *) lyd_root->child, 1, 0, 0, 1, 1, + STRING, "test");\ + lyd_free_all(tree); + + /* rewriting default value */ + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + data = "{\"T_DEFAULT2:cont\":{\":port\": \" 52 \"}}";\ + CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lysc_root = (void *)tree->schema; + CHECK_LYSC_NODE(lysc_root->child, NULL, 0, 0x205, 1, "port", 0, LYS_LEAF, 1, 0, 0, 0); + lyd_root = ((struct lyd_node_inner *) tree); + CHECK_LYD_NODE_TERM((struct lyd_node_term *) lyd_root->child, 0, 0, 0, 1, 1, + STRING, " 52 "); + lyd_free_all(tree); + + /* UTF-8 length and pattern*/ + schema = MODULE_CREATE_YANG("T_UTF8", "leaf port {type string {" + " length \"5 .. 10\";" + " pattern '[€]{5,7}' ;" + "}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_JSON("T_UTF8", "€€€€€", STRING, "€€€€€"); + TEST_ERROR_JSON("T_UTF8", "€€€"); + CHECK_LOG_CTX("Unsatisfied length - string \"€€€\" length is not allowed.", + "Schema location \"/T_UTF8:port\", line number 1."); + TEST_ERROR_JSON("T_UTF8", "€€€€€€€€"); + CHECK_LOG_CTX("Unsatisfied pattern - \"€€€€€€€€\" does not conform to \"[€]{5,7}\".", + "Schema location \"/T_UTF8:port\", line number 1."); + + /* ANCHOR TEST ^$ is implicit */ + schema = MODULE_CREATE_YANG("T_ANCHOR", "leaf port {type string {" + " pattern 'a.*b' ;" + "}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_ERROR_JSON("T_ANCHOR", "abc"); + CHECK_LOG_CTX("Unsatisfied pattern - \"abc\" does not conform to \"a.*b\".", + "Schema location \"/T_ANCHOR:port\", line number 1."); + TEST_ERROR_JSON("T_ANCHOR", "cb"); + CHECK_LOG_CTX("Unsatisfied pattern - \"cb\" does not conform to \"a.*b\".", + "Schema location \"/T_ANCHOR:port\", line number 1."); +} + +static void +test_data_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", "leaf port {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "port", ""); + TEST_SUCCESS_LYB("lyb", "port", "a"); + TEST_SUCCESS_LYB("lyb", "port", "abcdefghijklmnopqrstuvwxyz"); +} + +static void +test_diff(void **state) +{ + (void) state; + const char *schema; + + schema = MODULE_CREATE_YANG("T_DIFF", "leaf port {type string {length \"6 .. 50 | 120\";}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + struct lyd_node *model_1, *model_2; + struct lyd_node *diff; + const char *data_1 = "<port xmlns=\"urn:tests:T_DIFF\"> text abc < </port>"; + const char *data_2 = "<port xmlns=\"urn:tests:T_DIFF\"> text abc > </port>"; + const char *diff_expected = "<port xmlns=\"urn:tests:T_DIFF\"" + " xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\"" + " yang:operation=\"replace\" yang:orig-default=\"false\"" + " yang:orig-value=\" text abc < \"> text abc > </port>"; + + CHECK_PARSE_LYD_PARAM(data_1, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, model_1); + CHECK_PARSE_LYD_PARAM(data_2, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, model_2); + assert_int_equal(LY_SUCCESS, lyd_diff_siblings(model_1, model_2, 0, &diff)); + assert_non_null(diff); + CHECK_LYD_STRING_PARAM(diff, diff_expected, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + assert_int_equal(LY_SUCCESS, lyd_diff_apply_all(&model_1, diff)); + CHECK_LYD(model_1, model_2); + lyd_free_all(model_1); + lyd_free_all(model_2); + lyd_free_all(diff); + + /* create data from diff */ + diff_expected = "<port xmlns=\"urn:tests:T_DIFF\"" + " xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\"" + " yang:operation=\"replace\" yang:orig-default=\"false\"" + " yang:orig-value=\" 10^20 \">jjjjjjj</port>"; + + CHECK_PARSE_LYD_PARAM(diff_expected, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, diff); + data_1 = "<port xmlns=\"urn:tests:T_DIFF\"> 10^20 </port>"; + CHECK_PARSE_LYD_PARAM(data_1, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, model_1); + assert_int_equal(LY_SUCCESS, lyd_diff_apply_all(&model_1, diff)); + const char *expected = "<port xmlns=\"urn:tests:T_DIFF\">jjjjjjj</port>"; + + CHECK_LYD_STRING_PARAM(model_1, expected, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + lyd_free_all(model_1); + lyd_free_all(diff); + + /* check creating data breaking restrictions */ + diff_expected = "<port xmlns=\"urn:tests:T_DIFF\" " + "xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" " + "yang:operation=\"replace\" yang:orig-default=\"false\" yang:orig-value=\" 555 555\">" + "121</port>"; + CHECK_PARSE_LYD_PARAM(diff_expected, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, model_1); + CHECK_LOG_CTX("Unsatisfied length - string \"121\" length is not allowed.", + "Schema location \"/T_DIFF:port\", line number 1."); + + /* diff from default value */ + data_1 = "<cont xmlns=\"urn:tests:T_DIFF1\"></cont>"; + data_2 = "<cont xmlns=\"urn:tests:T_DIFF1\"> <port> 6 </port> </cont>"; + diff_expected = "<cont xmlns=\"urn:tests:T_DIFF1\"" + " xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\"" + " yang:operation=\"create\"><port> 6 </port></cont>"; + + schema = MODULE_CREATE_YANG("T_DIFF1", + "container cont {\n" + " leaf port {type string; default \" 20\n30 \";}" + "}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + CHECK_PARSE_LYD_PARAM(data_1, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, model_1); + CHECK_PARSE_LYD_PARAM(data_2, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, model_2); + assert_int_equal(LY_SUCCESS, lyd_diff_siblings(model_1, model_2, 0, &diff)); + assert_non_null(diff); + CHECK_LYD_STRING_PARAM(diff, diff_expected, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + assert_int_equal(LY_SUCCESS, lyd_diff_apply_all(&model_1, diff)); + CHECK_LYD(model_1, model_2); + lyd_free_all(diff); + + lyd_free_all(model_1); + lyd_free_all(model_2); +} + +static void +test_print(void **state) +{ + (void) state; + const char *schema; + + schema = MODULE_CREATE_YANG("T_PRINT", "leaf port {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + struct lyd_node *model_1; + const char *data_1 = "<port xmlns=\"urn:tests:T_PRINT\"> < hello > </port>"; + + CHECK_PARSE_LYD_PARAM(data_1, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, model_1); + + /* XML */ + const char *expected_xml = "<port xmlns=\"urn:tests:T_PRINT\"> < hello > </port>"; + + CHECK_LYD_STRING_PARAM(model_1, expected_xml, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + + /* JSON */ + const char *expected_json = "{\"T_PRINT:port\":\" < hello > \"}"; + + CHECK_LYD_STRING_PARAM(model_1, expected_json, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + + lyd_free_all(model_1); +} + +static void +test_plugin_store(void **state) +{ + (void) state; + + const char *val_text = NULL; + struct ly_err_item *err = NULL; + struct lys_module *mod; + struct lyd_value value = {0}; + struct lyplg_type *type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_STRING]); + struct lysc_type *lysc_type; + char *alloc_text; + unsigned int alloc_text_size; + LY_ERR ly_ret; + const char *schema; + + schema = MODULE_CREATE_YANG("T0", "leaf port {type string {length \"0 .. 10\";" + "pattern '[0-9\\n<>\\\"\\|]*' ;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *) mod->compiled->data)->type; + + /* check proper type */ + assert_string_equal("libyang 2 - string, version 1", type->id); + + /* check store */ + val_text = "20"; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, STRING, "20"); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "150\n"; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, STRING, "150\n"); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "<\"150>\n"; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, STRING, "<\"150>\n"); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "<\"150>\n|hi how are you"; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val_text, 8, + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, STRING, "<\"150>\n|"); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = ""; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, STRING, ""); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + /* + * minor tests + * dynamic alocated input text + */ + val_text = "<250>"; + alloc_text_size = strlen(val_text); + alloc_text = (char *) malloc(alloc_text_size + 1); + memcpy(alloc_text, val_text, alloc_text_size + 1); + + ly_ret = type->store(UTEST_LYCTX, lysc_type, alloc_text, alloc_text_size, + LYPLG_TYPE_STORE_DYNAMIC, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err); + alloc_text = NULL; + assert_int_equal(LY_SUCCESS, ly_ret); + CHECK_LYD_VALUE(value, STRING, "<250>"); + type->free(UTEST_LYCTX, &value); + + /* wrong lysc_type of value */ + struct lysc_type lysc_type_test = *lysc_type; + + lysc_type_test.basetype = LY_TYPE_UINT8; + val_text = "20"; + ly_ret = type->store(UTEST_LYCTX, &lysc_type_test, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err); + assert_int_equal(LY_EINVAL, ly_ret); + ly_err_free(err); + + /* TEST pattern backslash */ + + schema = MODULE_CREATE_YANG("TPATTERN_BC_1", "leaf port {type string {" + "pattern '\\\\[a]b';" /* pattern '\\[a]b'; */ + "}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type; + val_text = "\\ab"; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, STRING, "\\ab"); + type->free(UTEST_LYCTX, &value); + + schema = MODULE_CREATE_YANG("TPATTERN_BC_2", "leaf port {type string {" + "pattern \"\\\\\\\\[a]b\";" /* pattern "\\\\[a]b"; */ + "}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type; + val_text = "\\ab"; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, STRING, "\\ab"); + type->free(UTEST_LYCTX, &value); + + /* ERROR TESTS */ + + val_text = "10 \"| bcdei"; + err = NULL; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err); + assert_int_equal(LY_EVALID, ly_ret); + ly_err_free(err); + + val_text = "012345678901"; + err = NULL; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err); + assert_int_equal(LY_EVALID, ly_ret); + ly_err_free(err); + + val_text = "10"; + err = NULL; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_DECNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_EVALID, ly_ret); + ly_err_free(err); + +} + +static void +test_plugin_compare(void **state) +{ + struct ly_err_item *err = NULL; + struct lys_module *mod; + struct lyd_value values[10]; + struct lyplg_type *type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_STRING]); + struct lysc_type *lysc_type; + LY_ERR ly_ret; + const char *schema; + + /* different type */ + const char *diff_type_text = "20"; + struct lyd_value diff_type_val; + struct lysc_type *diff_type; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("T0", "typedef my_int_type {type string; }" + "leaf p1 {type my_int_type;}" + "leaf p2 {type my_int_type;}" + "leaf p3 {type string;}" + "leaf p4 {type uint8;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *) mod->compiled->data)->type; + + /* CREATE VALUES */ + const char *val_init[] = {"hi", "hello", "hi", "hello", "hell", "hh"}; + + for (int unsigned it = 0; it < sizeof(val_init) / sizeof(val_init[0]); it++) { + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_init[it], strlen(val_init[it]), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &(values[it]), NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + } + + /* BASIC TEST; */ + assert_int_equal(LY_SUCCESS, type->compare(&(values[0]), &(values[0]))); + assert_int_equal(LY_SUCCESS, type->compare(&(values[0]), &(values[2]))); + assert_int_equal(LY_ENOT, type->compare(&(values[0]), &(values[1]))); + assert_int_equal(LY_ENOT, type->compare(&(values[1]), &(values[0]))); + assert_int_equal(LY_ENOT, type->compare(&(values[1]), &(values[2]))); + assert_int_equal(LY_SUCCESS, type->compare(&(values[1]), &(values[3]))); + + /* SAME TYPE but different node */ + diff_type_text = "hi"; + diff_type = ((struct lysc_node_leaf *) mod->compiled->data->next)->type; + ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &diff_type_val, NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + assert_int_equal(LY_SUCCESS, type->compare(&diff_type_val, &(values[0]))); + assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[1]))); + type->free(UTEST_LYCTX, &(diff_type_val)); + + /* original type */ + diff_type_text = "hi"; + diff_type = ((struct lysc_node_leaf *) mod->compiled->data->next->next)->type; + ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &diff_type_val, NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[0]))); + assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[1]))); + type->free(UTEST_LYCTX, &(diff_type_val)); + + /* different type (UINT8) */ + diff_type_text = "20"; + diff_type = ((struct lysc_node_leaf *) mod->compiled->data->next->next->next)->type; + ly_ret = diff_type->plugin->store(UTEST_LYCTX, diff_type, diff_type_text, strlen(diff_type_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_DECNUM, NULL, &diff_type_val, NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[0]))); + assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[1]))); + type->free(UTEST_LYCTX, &(diff_type_val)); + + /* delete values */ + for (int unsigned it = 0; it < sizeof(val_init) / sizeof(val_init[0]); it++) { + type->free(UTEST_LYCTX, &(values[it])); + } +} + +static void +test_plugin_print(void **state) +{ + struct ly_err_item *err = NULL; + struct lys_module *mod; + struct lyd_value values[10]; + struct lyplg_type *type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_STRING]); + struct lysc_type *lysc_type; + LY_ERR ly_ret; + + /* create schema. Prepare common used variables */ + const char *schema = MODULE_CREATE_YANG("defs", "leaf port {type string;}"); + + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *) mod->compiled->data)->type; + + /* CREATE VALUES */ + const char *val_init[] = {"20", "0x4A", "<|>", "\""}; + + for (int unsigned it = 0; it < sizeof(val_init) / sizeof(val_init[0]); it++) { + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_init[it], strlen(val_init[it]), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &(values[it]), NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + } + + /* print value */ + ly_bool dynamic = 0; + + assert_string_equal("20", type->print(UTEST_LYCTX, &(values[0]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("0x4A", type->print(UTEST_LYCTX, &(values[1]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("<|>", type->print(UTEST_LYCTX, &(values[2]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("\"", type->print(UTEST_LYCTX, &(values[3]), LY_VALUE_XML, NULL, &dynamic, NULL)); + + for (int unsigned it = 0; it < sizeof(val_init) / sizeof(val_init[0]); it++) { + type->free(UTEST_LYCTX, &(values[it])); + } +} + +static void +test_plugin_dup(void **state) +{ + + struct ly_err_item *err = NULL; + struct lys_module *mod; + struct lyd_value values[10]; + struct lyplg_type *type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_STRING]); + struct lysc_type *lysc_type[2]; + const char *schema; + LY_ERR ly_ret; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("T0", "leaf port {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type[0] = ((struct lysc_node_leaf *) mod->compiled->data)->type; + + schema = MODULE_CREATE_YANG("T1", + "typedef my_int_type {" + " type string {length \"1 .. 100\";} default 20;" + "}" + "leaf port {type my_int_type; }"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type[1] = ((struct lysc_node_leaf *) mod->compiled->data)->type; + + /* CREATE VALUES */ + const char *val_init[] = {"20", "0x4A", "<\">", "0x4A"}; + + for (int unsigned it = 0; it < sizeof(val_init) / sizeof(val_init[0]); it++) { + ly_ret = type->store(UTEST_LYCTX, lysc_type[it % 2], val_init[it], strlen(val_init[it]), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &(values[it]), NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + } + + /* print duplicate value */ + struct lyd_value dup_value; + + assert_int_equal(LY_SUCCESS, type->duplicate(UTEST_LYCTX, &(values[0]), &dup_value)); + CHECK_LYD_VALUE(dup_value, STRING, "20"); + assert_ptr_equal(dup_value.realtype, values[0].realtype); + type->free(UTEST_LYCTX, &dup_value); + + assert_int_equal(LY_SUCCESS, type->duplicate(UTEST_LYCTX, &(values[1]), &dup_value)); + CHECK_LYD_VALUE(dup_value, STRING, "0x4A"); + assert_ptr_equal(dup_value.realtype, values[1].realtype); + type->free(UTEST_LYCTX, &dup_value); + + assert_int_equal(LY_SUCCESS, type->duplicate(UTEST_LYCTX, &(values[2]), &dup_value)); + CHECK_LYD_VALUE(dup_value, STRING, "<\">"); + assert_ptr_equal(dup_value.realtype, values[2].realtype); + type->free(UTEST_LYCTX, &dup_value); + + assert_int_equal(LY_SUCCESS, type->duplicate(UTEST_LYCTX, &(values[3]), &dup_value)); + CHECK_LYD_VALUE(dup_value, STRING, "0x4A"); + assert_ptr_equal(dup_value.realtype, values[3].realtype); + type->free(UTEST_LYCTX, &dup_value); + + /* error tests */ + assert_int_equal(LY_EINVAL, type->duplicate(NULL, &(values[0]), &dup_value)); + + for (int unsigned it = 0; it < sizeof(val_init) / sizeof(val_init[0]); it++) { + type->free(UTEST_LYCTX, &(values[it])); + } +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_schema_yang), + UTEST(test_schema_yin), + UTEST(test_schema_print), + UTEST(test_data_xml), + UTEST(test_data_json), + UTEST(test_data_lyb), + UTEST(test_diff), + UTEST(test_print), + + UTEST(test_plugin_store), + UTEST(test_plugin_compare), + UTEST(test_plugin_print), + UTEST(test_plugin_dup), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} |