diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:55:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:55:11 +0000 |
commit | cd07912073c951b4bbb871ed2653af1be2cfc714 (patch) | |
tree | 1073c2308492e6aea4c66cb7436ee92db2abfd42 /tests/utests/types | |
parent | Initial commit. (diff) | |
download | libyang2-upstream.tar.xz libyang2-upstream.zip |
Adding upstream version 2.1.30.upstream/2.1.30upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'tests/utests/types')
-rw-r--r-- | tests/utests/types/binary.c | 269 | ||||
-rw-r--r-- | tests/utests/types/bits.c | 1117 | ||||
-rw-r--r-- | tests/utests/types/boolean.c | 111 | ||||
-rw-r--r-- | tests/utests/types/decimal64.c | 125 | ||||
-rw-r--r-- | tests/utests/types/empty.c | 108 | ||||
-rw-r--r-- | tests/utests/types/enumeration.c | 114 | ||||
-rw-r--r-- | tests/utests/types/identityref.c | 123 | ||||
-rw-r--r-- | tests/utests/types/inet_types.c | 149 | ||||
-rw-r--r-- | tests/utests/types/instanceid.c | 292 | ||||
-rw-r--r-- | tests/utests/types/instanceid_keys.c | 77 | ||||
-rw-r--r-- | tests/utests/types/int16.c | 75 | ||||
-rw-r--r-- | tests/utests/types/int32.c | 75 | ||||
-rw-r--r-- | tests/utests/types/int64.c | 83 | ||||
-rw-r--r-- | tests/utests/types/int8.c | 1765 | ||||
-rw-r--r-- | tests/utests/types/leafref.c | 222 | ||||
-rw-r--r-- | tests/utests/types/string.c | 1410 | ||||
-rw-r--r-- | tests/utests/types/uint16.c | 75 | ||||
-rw-r--r-- | tests/utests/types/uint32.c | 75 | ||||
-rw-r--r-- | tests/utests/types/uint64.c | 83 | ||||
-rw-r--r-- | tests/utests/types/uint8.c | 77 | ||||
-rw-r--r-- | tests/utests/types/union.c | 136 | ||||
-rw-r--r-- | tests/utests/types/yang_types.c | 223 |
22 files changed, 6784 insertions, 0 deletions
diff --git a/tests/utests/types/binary.c b/tests/utests/types/binary.c new file mode 100644 index 0000000..05b6b97 --- /dev/null +++ b/tests/utests/types/binary.c @@ -0,0 +1,269 @@ +/** + * @file binary.c + * @author Michal Vaško <mvasko@cesnet.cz> + * @brief test for built-in binary type + * + * 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" + +#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_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); \ + } + +static void +test_plugin_store(void **state) +{ + const char *val, *dec_val; + unsigned char bin_val[2]; + 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_BINARY]); + struct lysc_type *lysc_type; + LY_ERR ly_ret; + const char *schema; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("a", "leaf l {type binary;}"); + 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 - binary, version 1", type->id); + + /* check store XML double pad */ + val = "YWhveQ=="; + dec_val = "ahoy"; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val)); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, dec_val, strlen(dec_val), + 0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val)); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + /* single pad */ + val = "YWhveWo="; + dec_val = "ahoyj"; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val)); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, dec_val, strlen(dec_val), + 0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val)); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + /* no pad */ + val = "YWhveWoy"; + dec_val = "ahoyj2"; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val)); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, dec_val, strlen(dec_val), + 0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val)); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + /* binary data */ + val = "q80="; + bin_val[0] = 0xab; + bin_val[1] = 0xcd; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, val, bin_val, 2); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, bin_val, 2, + 0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, val, bin_val, 2); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + /* newlines after every 64 chars */ + val = "MIIEAzCCAuugAwIBAgIURc4sipHvJSlNrQIhRhZilBvV4RowDQYJKoZIhvcNAQEL\n" + "BQAwgZAxCzAJBgNVBAYTAkNaMRYwFAYDVQQIDA1Tb3V0aCBNb3JhdmlhMQ0wCwYD\n" + "VQQHDARCcm5vMRgwFgYDVQQKDA9DRVNORVQgei5zLnAuby4xDDAKBgNVBAsMA1RN\n" + "QzETMBEGA1UEAwwKZXhhbXBsZSBDQTEdMBsGCSqGSIb3DQEJARYOY2FAZXhhbXBs\n" + "ZS5vcmcwHhcNMjEwOTAzMTAyMTAxWhcNMzEwOTAxMTAyMTAxWjCBkDELMAkGA1UE\n" + "BhMCQ1oxFjAUBgNVBAgMDVNvdXRoIE1vcmF2aWExDTALBgNVBAcMBEJybm8xGDAW\n" + "BgNVBAoMD0NFU05FVCB6LnMucC5vLjEMMAoGA1UECwwDVE1DMRMwEQYDVQQDDApl\n" + "eGFtcGxlIENBMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLm9yZzCCASIwDQYJ\n" + "KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN4Ld3JDDocyy9KXNJhEUPeZpQW3UdUN\n" + "Xloeh5n/bxasgThkBuQ7oF/nKyVUe517U1CJA993ZIc0jhIWThAnqXkz70DX5EZ7\n" + "ancPd01MidA6T8k1RYYJWr+vyIRYYBYzK7LSnU6wMWqPTgzZB+KMWwb065ooLEB5\n" + "XwqAeTIMPLRqM1Galewl4ZSuRJnrXxRjfF3AWNyC9dZw6wIg8cppvoLdBGQiFJQf\n" + "9SgiVy+HyedAytFEixqKAAIgQUJwhCgbEd6jGFbeaL8HT4MFp1VmaaUBQMkZj/Gn\n" + "KBwCk5BEMu76EN1pzHc4Dd6DabQNGCnsqOPe31yhQGmNFy9R6zNnWZMCAwEAAaNT\n" + "MFEwHQYDVR0OBBYEFM7w/pO8vk5oowvWPoCKo0RW/JcnMB8GA1UdIwQYMBaAFM7w\n" + "/pO8vk5oowvWPoCKo0RW/JcnMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\n" + "BQADggEBAG/xfYuRKnCyiwYC/K7kAjHmCNnLCr1mx8P1ECsSJPme3OThDTNeGf8i\n" + "N2952tGmMFDa+DaAwPc6Gt3cWTb/NYMTLWlt2yj5rJAcLXxIU0SMafBf+F7E/R8A\n" + "b/HDDjs0pQaJ0EJhQJVkMdfj3Wq9l0dJT5iEBUrUQflDufiMdEJEIGKZh86MgzEL\n" + "bcn1QX8dlLc91M2OifWStqLzXPicG+jjuoPUceC0flMQDb2qx03sxvJKfYfS5ArA\n" + "CqvdWyXLoP7DI9THJrMI/vBHJKpl4Wtmsh2OLn9VHauFMzPSGke5GwjXCpbXGepj\n" + "9qWN8Gd/FWgSDH2OBvZ6aHdB1pPjN9k="; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + /* empty value */ + val = ""; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, "", "", 0); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + /* short value */ + val = "YQ=="; + dec_val = "a"; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val)); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, dec_val, strlen(dec_val), + 0, LY_VALUE_LYB, NULL, 0, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, BINARY, val, dec_val, strlen(dec_val)); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + /* + * ERROR TESTS + */ + val = "q80."; + err = NULL; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err); + assert_int_equal(LY_EVALID, ly_ret); + assert_string_equal(err->msg, "Invalid Base64 character '.'."); + ly_err_free(err); + + val = "q80"; + err = NULL; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err); + assert_int_equal(LY_EVALID, ly_ret); + assert_string_equal(err->msg, "Base64 encoded value length must be divisible by 4."); + ly_err_free(err); +} + +static void +test_plugin_print(void **state) +{ + const char *schema, *val; + struct lyd_value value = {0}; + struct lys_module *mod; + struct lysc_type *lysc_type; + struct lyplg_type *type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_BINARY]); + struct ly_err_item *err = NULL; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("a", "leaf l {type binary;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type; + + /* Testing empty value. */ + val = ""; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + assert_string_equal("", value.realtype->plugin->print(UTEST_LYCTX, &(value), LY_VALUE_CANON, NULL, NULL, NULL)); + type->free(UTEST_LYCTX, &value); +} + +static void +test_plugin_duplicate(void **state) +{ + const char *schema, *val; + struct lyd_value value = {0}, dup; + struct lys_module *mod; + struct lysc_type *lysc_type; + struct lyplg_type *type = lyplg_type_plugin_find("", NULL, ly_data_type2str[LY_TYPE_BINARY]); + struct ly_err_item *err = NULL; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("a", "leaf l {type binary;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type; + + /* Testing empty value. */ + val = ""; + assert_int_equal(LY_SUCCESS, type->store(UTEST_LYCTX, lysc_type, val, strlen(val), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err)); + assert_int_equal(LY_SUCCESS, type->duplicate(UTEST_LYCTX, &value, &dup)); + CHECK_LYD_VALUE(dup, BINARY, "", "", 0); + type->free(UTEST_LYCTX, &value); + type->free(UTEST_LYCTX, &dup); +} + +static void +test_data_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", "leaf port {type binary;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "port", ""); + TEST_SUCCESS_LYB("lyb", "port", "YWhveQ=="); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_plugin_store), + UTEST(test_plugin_print), + UTEST(test_plugin_duplicate), + UTEST(test_data_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/bits.c b/tests/utests/types/bits.c new file mode 100644 index 0000000..3d42ebc --- /dev/null +++ b/tests/utests/types/bits.c @@ -0,0 +1,1117 @@ +/** + * @file bits.c + * @author Radek Iša <isa@cesnet.cz> + * @brief test for int8 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* GLOBAL INCLUDE HEADERS */ +#include <ctype.h> + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" +#include "path.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_type_bits *lysc_type; + + schema = MODULE_CREATE_YANG("T0", "leaf port {type bits { bit zero;\nbit one;" + " bit ten{position 10;}\tbit \"eleven\"; bit last{position 4294967295; }}}"); + 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); + lysc_type = (struct lysc_type_bits *) lysc_leaf->type; + CHECK_LYSC_TYPE_BITS(lysc_type, 0, 5); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, 0, "zero", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, 0, "one", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 10, NULL, 0, 0, "ten", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 11, NULL, 0, 0, "eleven", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[4]), 4294967295, NULL, 0, 0, "last", 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, 5, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0); + + schema = MODULE_CREATE_YANG("T1", "leaf port {type bits { bit _ten {position 10;} bit _ten-one;" + " bit _two {position 2;} bit ten_end...;}}"); + 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); + lysc_type = (struct lysc_type_bits *) lysc_leaf->type; + CHECK_LYSC_TYPE_BITS(lysc_type, 0, 4); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "_two", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "_ten", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, 0, "_ten-one", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, 0, "ten_end...", 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, 4, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0); + + /* TEST MODULE SUBTYPE */ + schema = MODULE_CREATE_YANG("T2", "typedef my_type{type bits {" + " bit ten {position 10;} bit eleven; bit two {position 2;} bit twelve;}}" + "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, NULL); + lysc_type = (struct lysc_type_bits *) lysc_leaf->type; + CHECK_LYSC_TYPE_BITS(lysc_type, 0, 4); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "two", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "ten", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, 0, "eleven", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, 0, "twelve", 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, 0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0); + + schema = MODULE_CREATE_YANG("T3", "typedef my_type{type bits {" + " bit ten {position 10;} bit eleven; bit two {position 2;} bit twelve;}}" + "leaf port {type my_type {" + " bit ten {position 10;} bit two;}}"); + 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); + lysc_type = (struct lysc_type_bits *) lysc_leaf->type; + CHECK_LYSC_TYPE_BITS(lysc_type, 0, 2); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "two", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "ten", 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, 2, 0, 0, 0, 0x02, 0, 0, "my_type", 0, 0, 1, 0, 0, 0); + + /* + * TEST ERROR + */ + /* test change bit possition */ + schema = MODULE_CREATE_YANG("TERR_0", "typedef my_type{type bits {" + " bit ten {position 10;} bit eleven; bit two {position 2;} bit \"twelve\";}}" + "leaf port {type my_type {" + " bit ten {position 11;} bit two;}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid bits - position of the item \"ten\" has changed from 10 to 11 in the derived type.", "/TERR_0:port"); + + /* add new bit */ + schema = MODULE_CREATE_YANG("TERR_1", "typedef my_type{type bits {" + " bit ten {position 10;} bit eleven; bit two {position 2;} bit twelve;}}" + "leaf port {type my_type {" + " bit ten {position 10;} bit two; bit test;}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid bits - derived type adds new item \"test\".", "/TERR_1:port"); + + /* different max value => autoadd index */ + schema = MODULE_CREATE_YANG("TERR_2", "leaf port {type bits {" + " bit first {position -1;} bit second;" + "}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_2\" failed.", NULL, + "Invalid value \"-1\" of \"position\".", "Line number 5."); + + /* different max value => autoadd index */ + schema = MODULE_CREATE_YANG("TERR_3", "leaf port {type bits {" + " bit first {position 4294967295;} bit second;" + "}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid bits - it is not possible to auto-assign bit position for \"second\" since the highest value is already 4294967295.", + "/TERR_3:port"); + + schema = MODULE_CREATE_YANG("TERR_4", "leaf port {type bits {" + " bit first {position 10;} bit \"\";" + "}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_4\" failed.", NULL, + "Statement argument is required.", "Line number 5."); + + /* wrong character */ + schema = MODULE_CREATE_YANG("TERR_5", "leaf port {type bits {" + " bit first {position 10;} bit abcd^;" + "}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_5\" failed.", NULL, + "Invalid identifier character '^' (0x005e).", "Line number 5."); + + schema = MODULE_CREATE_YANG("TERR_6", "leaf port {type bits {" + " bit hi; bit hi;" + "}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_6\" failed.", NULL, + "Duplicate identifier \"hi\" of bit statement.", "Line number 5."); + + /* wrong character */ + schema = MODULE_CREATE_YANG("TERR_7", "leaf port {type bits {" + " bit first {position 10;} bit \"ab&cd\";" + "}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_7\" failed.", NULL, + "Invalid identifier character '&' (0x0026).", "Line number 5."); + + schema = MODULE_CREATE_YANG("TERR_8", "leaf port {type bits {" + " bit first {position 10;} bit \"4abcd\";" + "}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_8\" failed.", NULL, + "Invalid identifier first character '4' (0x0034).", "Line number 5."); + + schema = MODULE_CREATE_YANG("TERR_9", "leaf port {type bits;}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Missing bit substatement for bits type.", "/TERR_9:port"); + + /* new features of YANG 1.1 in YANG 1.0 */ + schema = "module TERR_10 {" + " namespace \"urn:tests:TERR_10\";" + " prefix pref;" + " feature f;" + " leaf l {type bits {" + " bit one {if-feature f;}" + " }}" + "}"; + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_10\" failed.", NULL, + "Invalid keyword \"if-feature\" as a child of \"bit\" - the statement is allowed only in YANG 1.1 modules.", + "Line number 1."); + + schema = "module TERR_11 {" + " namespace \"urn:tests:TERR_10\";" + " prefix pref;" + " typedef mytype {type bits {bit one;}}" + " leaf l {type mytype {bit one;}}" + "}"; + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Bits type can be subtyped only in YANG 1.1 modules.", "/TERR_11:l"); + + /* feature is not present */ + schema = MODULE_CREATE_YANG("IF_0", "feature f;" + "leaf port {type bits { bit zero;\nbit one;" + " bit ten{if-feature f; position 10;}\tbit eleven;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + assert_int_equal(LY_ENOT, lys_feature_value (mod, "f")); + 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); + lysc_type = (struct lysc_type_bits *) lysc_leaf->type; + CHECK_LYSC_TYPE_BITS(lysc_type, 0, 3); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, 0, "zero", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, 0, "one", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, 0, "eleven", 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, 4, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0); + + /* feature is present */ + schema = MODULE_CREATE_YANG("IF_1", "feature f;" + "leaf port {type bits { bit zero;\nbit one;" + " bit ten{position 10; if-feature f;}\tbit eleven;}}"); + const char *IF_1_FEATURES[] = {"f", NULL}; + + UTEST_ADD_MODULE(schema, LYS_IN_YANG, IF_1_FEATURES, &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); + lysc_type = (struct lysc_type_bits *) lysc_leaf->type; + CHECK_LYSC_TYPE_BITS(lysc_type, 0, 4); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, 0, "zero", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, 0, "one", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 10, NULL, 0, 0, "ten", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 11, NULL, 0, 0, "eleven", 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, 4, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0); +} + +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_type_bits *lysc_type; + + schema = MODULE_CREATE_YIN("T0", + "<leaf name=\"port\"> <type name=\"bits\">" + " <bit name=\"zero\"/> <bit name=\"one\"/>" + " <bit name=\"ten\"> <position value=\"10\"/> </bit>" + " <bit name=\"eleven\"/>" + " <bit name=\"last\"> <position value=\"4294967295\"/> </bit>" + "</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); + lysc_type = (struct lysc_type_bits *) lysc_leaf->type; + CHECK_LYSC_TYPE_BITS(lysc_type, 0, 5); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 0, NULL, 0, 0, "zero", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 1, NULL, 0, 0, "one", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 10, NULL, 0, 0, "ten", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 11, NULL, 0, 0, "eleven", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[4]), 4294967295, NULL, 0, 0, "last", 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, 5, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0); + + schema = MODULE_CREATE_YIN("T1", + "<leaf name=\"port\"> <type name=\"bits\">" + " <bit name=\"_ten\"> <position value=\"10\"/> </bit> <bit name=\"_ten-one\"/>" + " <bit name=\"_two\"> <position value=\"2\"/> </bit> <bit name=\"ten_end...\"/>" + "</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); + lysc_type = (struct lysc_type_bits *) lysc_leaf->type; + CHECK_LYSC_TYPE_BITS(lysc_type, 0, 4); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "_two", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "_ten", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, 0, "_ten-one", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, 0, "ten_end...", 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, 4, 0, 0, 0, 0x02, 0, 0, "bits", 0, 0, 1, 0, 0, 0); + + /* TEST MODULE SUBTYPE */ + schema = MODULE_CREATE_YIN("T2", + "<typedef name=\"my_type\"> <type name=\"bits\">" + " <bit name=\"ten\"> <position value=\"10\"/> </bit>" + " <bit name=\"eleven\"/> <bit name=\"two\"> <position value=\"2\"/> </bit>" + " <bit name=\"twelve\"/>" + "</type> </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, NULL); + lysc_type = (struct lysc_type_bits *) lysc_leaf->type; + CHECK_LYSC_TYPE_BITS(lysc_type, 0, 4); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "two", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "ten", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[2]), 11, NULL, 0, 0, "eleven", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[3]), 12, NULL, 0, 0, "twelve", 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, 0, 0, 0, "my_type", 0, 0, 1, 0, 0, 0); + + schema = MODULE_CREATE_YIN("T3", "<typedef name=\"my_type\"> <type name=\"bits\">" + " <bit name=\"ten\"> <position value=\"10\"/></bit>" + " <bit name=\"eleven\"/> <bit name=\"two\"> <position value=\"2\"/> </bit>" + " <bit name=\"twelve\"/>" + "</type></typedef>" + "<leaf name=\"port\"> <type name=\"my_type\">" + " <bit name=\"ten\"> <position value=\"10\"/> </bit>" + " <bit name=\"two\"/>" + "</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); + lysc_type = (struct lysc_type_bits *) lysc_leaf->type; + CHECK_LYSC_TYPE_BITS(lysc_type, 0, 2); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[0]), 2, NULL, 0, 0, "two", NULL); + CHECK_LYSC_TYPE_BITENUM_ITEM(&(lysc_type->bits[1]), 10, NULL, 0, 0, "ten", 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, 2, 0, 0, 0, 0x02, 0, 0, "my_type", 0, 0, 1, 0, 0, 0); + + /* + * TEST ERROR + */ + /* test change bit possition */ + schema = MODULE_CREATE_YIN("TERR_0", "<typedef name=\"my_type\"> <type name=\"bits\">" + " <bit name=\"ten\"> <position value=\"10\"/> </bit>" + " <bit name=\"eleven\"/>" + " <bit name=\"two\"> <position value=\"2\"/> </bit>" + " <bit name=\"twelve\"/>" + "</type></typedef>" + "<leaf name=\"port\"> <type name=\"my_type\">" + " <bit name=\"ten\"> <position value=\"11\"/> </bit> <bit name=\"two\"/>" + "</type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid bits - position of the item \"ten\" has changed from 10 to 11 in the derived type.", "/TERR_0:port"); + + /* add new bit */ + schema = MODULE_CREATE_YIN("TERR_1", + "<typedef name=\"my_type\"> <type name=\"bits\">" + " <bit name=\"ten\"> <position value=\"10\"/> </bit>" + " <bit name=\"eleven\"/>" + " <bit name=\"two\"> <position value=\"2\"/> </bit>" + " <bit name=\"twelve\"/>" + "</type></typedef>" + "<leaf name=\"port\"> <type name=\"my_type\">" + " <bit name=\"ten\"> <position value=\"10\"/> </bit>" + " <bit name=\"two\"/>" + " <bit name=\"test\"/>" + "</type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid bits - derived type adds new item \"test\".", "/TERR_1:port"); + + /* different max value => autoadd index */ + schema = MODULE_CREATE_YIN("TERR_2", + "<leaf name=\"port\"> <type name=\"bits\">" + " <bit name=\"first\"> <position value=\"-1\"> </bit>" + " <bit name=\"second\">" + "</type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_2\" failed.", NULL, + "Invalid value \"-1\" of \"value\" attribute in \"position\" element.", "Line number 8."); + + /* different max value => autoadd index */ + schema = MODULE_CREATE_YIN("TERR_3", + "<leaf name=\"port\"> <type name=\"bits\">" + " <bit name=\"first\"> <position value=\"4294967295\"/> </bit>" + " <bit name=\"second\"/>" + "</type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid bits - it is not possible to auto-assign bit position for \"second\" since the highest value is already 4294967295.", + "/TERR_3:port"); + + schema = MODULE_CREATE_YIN("TERR_4", + "<leaf name=\"port\"> <type name=\"bits\">" + " <bit name=\" ahoj \"> <position value=\"20\"/> </bit>" + " <bit name=\"second\"/>" + "</type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_4\" failed.", NULL, + "Invalid identifier first character ' ' (0x0020).", + "Line number 8."); + + schema = MODULE_CREATE_YIN("TERR_5", + "<leaf name=\"port\"> <type name=\"bits\">" + " <bit name=\"ah oj\"> <position value=\"20\"/> </bit>" + " <bit name=\"second\"/>" + "</type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_5\" failed.", NULL, + "Invalid identifier character ' ' (0x0020).", + "Line number 8."); + + schema = MODULE_CREATE_YIN("TERR_6", + "<leaf name=\"port\"> <type name=\"bits\">" + " <bit name=\"hi\"/> " + " <bit name=\"hi\"/>" + "</type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_6\" failed.", NULL, + "Duplicate identifier \"hi\" of bit statement.", + "Line number 8."); + + schema = MODULE_CREATE_YIN("TERR_7", + "<leaf name=\"port\"> <type name=\"bits\">" + " <bit name=\"4ahoj\"> <position value=\"20\"/> </bit>" + " <bit name=\"second\"/>" + "</type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_7\" failed.", NULL, + "Invalid identifier first character '4' (0x0034).", + "Line number 8."); + + /* TEST EMPTY NAME*/ + schema = MODULE_CREATE_YIN("TERR_8", + "<leaf name=\"port\"> <type name=\"bits\">" + " <bit name=\"\"> <position value=\"20\"/> </bit>" + " <bit name=\"second\"/>" + "</type></leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Parsing module \"TERR_8\" failed.", NULL, + "Empty identifier is not allowed.", + "Line number 8."); +} + +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", + "typedef my_type{type bits {" + " bit ten {position 10;} bit eleven; bit two {position 2;} bit twelve;}}" + "leaf port {type my_type {" + " bit ten {position 10;} bit two;}}"); + + schema_yin = MODULE_CREATE_YIN("PRINT0", + " <typedef name=\"my_type\">\n" + " <type name=\"bits\">\n" + " <bit name=\"ten\">\n" + " <position value=\"10\"/>\n" + " </bit>\n" + " <bit name=\"eleven\"/>\n" + " <bit name=\"two\">\n" + " <position value=\"2\"/>\n" + " </bit>\n" + " <bit name=\"twelve\"/>\n" + " </type>\n" + " </typedef>\n" + " <leaf name=\"port\">\n" + " <type name=\"my_type\">\n" + " <bit name=\"ten\">\n" + " <position value=\"10\"/>\n" + " </bit>\n" + " <bit name=\"two\"/>\n" + " </type>\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" + " typedef my_type {\n" + " type bits {\n" + " bit ten {\n" + " position 10;\n" + " }\n" + " bit eleven;\n" + " bit two {\n" + " position 2;\n" + " }\n" + " bit twelve;\n" + " }\n" + " }\n\n" + " leaf port {\n" + " type my_type {\n" + " bit ten {\n" + " position 10;\n" + " }\n" + " bit two;\n" + " }\n" + " }\n"); + + schema_yin = MODULE_CREATE_YIN("PRINT1", + " <typedef name=\"my_type\">\n" + " <type name=\"bits\">\n" + " <bit name=\"ten\">\n" + " <position value=\"10\"/>\n" + " </bit>\n" + " <bit name=\"eleven\"/>\n" + " <bit name=\"two\">\n" + " <position value=\"2\"/>\n" + " </bit>\n" + " <bit name=\"twelve\"/>\n" + " </type>\n" + " </typedef>\n" + " <leaf name=\"port\">\n" + " <type name=\"my_type\">\n" + " <bit name=\"ten\">\n" + " <position value=\"10\"/>\n" + " </bit>\n" + " <bit name=\"two\"/>\n" + " </type>\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; + + /* xml test */ + schema = MODULE_CREATE_YANG("T0", "typedef my_type{type bits {" + " bit ten {position 10;} bit eleven; bit two {position 2;} bit twelve;" + " bit _test-end...;}}" + "leaf port {type my_type;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML("T0", "ten two twelve", BITS, "two ten twelve", "two", "ten", "twelve"); + TEST_SUCCESS_XML("T0", "ten\ntwo\ttwelve", BITS, "two ten twelve", "two", "ten", "twelve"); + TEST_SUCCESS_XML("T0", "ten two", BITS, "two ten", "two", "ten"); + TEST_SUCCESS_XML("T0", "_test-end...", BITS, "_test-end...", "_test-end..."); + TEST_SUCCESS_XML("T0", "twelve\nten\ttwo \n eleven", BITS, "two ten eleven twelve", + "two", "ten", "eleven", "twelve"); + TEST_SUCCESS_XML("T0", "", BITS, ""); + TEST_SUCCESS_XML("T0", "\n\t", BITS, ""); + + TEST_ERROR_XML("T0", "twelvea"); + CHECK_LOG_CTX("Invalid bit \"twelvea\".", + "Schema location \"/T0:port\", line number 1."); + TEST_ERROR_XML("T0", "twelve t"); + CHECK_LOG_CTX("Invalid bit \"t\".", + "Schema location \"/T0:port\", line number 1."); + TEST_ERROR_XML("T0", "ELEVEN"); + CHECK_LOG_CTX("Invalid bit \"ELEVEN\".", + "Schema location \"/T0:port\", line number 1."); + + /* empty value */ + data = "<port xmlns=\"urn:tests:T0\"/>"; \ + 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, BITS, ""); + lyd_free_all(tree); + +} + +static void +test_data_json(void **state) +{ + const char *schema; + + /* variable for default value test */ + + /* xml test */ + schema = MODULE_CREATE_YANG("T0", "typedef my_type{type bits {" + " bit ten {position 10;} bit eleven; bit two {position 2;} bit twelve;" + " bit _test-end...;}}" + "leaf port {type my_type;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_JSON("T0", "ten two twelve", BITS, "two ten twelve", "two", "ten", "twelve"); + TEST_SUCCESS_JSON("T0", "ten\\ntwo\\ttwelve", BITS, "two ten twelve", "two", "ten", "twelve"); + TEST_SUCCESS_JSON("T0", "ten two", BITS, "two ten", "two", "ten"); + TEST_SUCCESS_JSON("T0", "_test-end...", BITS, "_test-end...", "_test-end..."); + TEST_SUCCESS_JSON("T0", "twelve\\nten\\ttwo \\n eleven", BITS, "two ten eleven twelve", + "two", "ten", "eleven", "twelve"); + TEST_SUCCESS_JSON("T0", "", BITS, ""); + TEST_SUCCESS_JSON("T0", "\\n\\t", BITS, ""); + + TEST_ERROR_JSON("T0", "twelvea"); + CHECK_LOG_CTX("Invalid character sequence \"twelvea}\", expected a JSON value.", + "Line number 1."); + TEST_ERROR_JSON("T0", "twelve t"); + CHECK_LOG_CTX("Invalid character sequence \"twelve t}\", expected a JSON value.", + "Line number 1."); + TEST_ERROR_JSON("T0", "ELEVEN"); + CHECK_LOG_CTX("Invalid character sequence \"ELEVEN}\", expected a JSON value.", + "Line number 1."); +} + +static void +test_data_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", "typedef my_type{type bits {" + " bit ten {position 10;} bit eleven; bit two {position 2;} bit twelve;" + " bit _test-end...;}}" + "leaf port {type my_type;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "port", "ten twelve"); + TEST_SUCCESS_LYB("lyb", "port", "two"); + TEST_SUCCESS_LYB("lyb", "port", ""); +} + +static void +test_diff(void **state) +{ + const char *schema; + struct lyd_node *model_1, *model_2; + struct lyd_node *diff; + const char *expected_string; + const char *data_1; + const char *data_2; + const char *diff_expected; + + schema = MODULE_CREATE_YANG("T0", "leaf port {type bits { bit zero; bit one;" + " bit two; bit three;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + data_1 = "<port xmlns=\"urn:tests:T0\"> two three </port>"; + data_2 = "<port xmlns=\"urn:tests:T0\"> one</port>"; + diff_expected = "<port xmlns=\"urn:tests:T0\"" + " xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"replace\"" + " yang:orig-default=\"false\" yang:orig-value=\"two three\">one</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:T0\"" + " xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"replace\"" + " yang:orig-default=\"false\" yang:orig-value=\"two three \"></port>"; + CHECK_PARSE_LYD_PARAM(diff_expected, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, diff) + data_1 = "<port xmlns=\"urn:tests:T0\"> two three </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)); + expected_string = "<port xmlns=\"urn:tests:T0\"/>"; + + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + lyd_free_all(model_1); + lyd_free_all(diff); + + /* create data from diff */ + diff_expected = "<port xmlns=\"urn:tests:T0\"" + " xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"replace\"" + " yang:orig-default=\"false\" yang:orig-value=\"two three\"> one </port>"; + CHECK_PARSE_LYD_PARAM(diff_expected, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, diff) + data_1 = "<port xmlns=\"urn:tests:T0\"> two three </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)); + expected_string = "<port xmlns=\"urn:tests:T0\">one</port>"; + + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + lyd_free_all(model_1); + lyd_free_all(diff); + +} + +static void +test_print(void **state) +{ + const char *schema; + const char *expected_string; + struct lyd_node *model_1; + const char *data; + + schema = MODULE_CREATE_YANG("T0", "leaf port {type bits { bit zero; bit one;" + " bit two; bit three;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + /* print zero bits */ + data = "<port xmlns=\"urn:tests:T0\"></port>"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, model_1) + /* XML */ + expected_string = "<port xmlns=\"urn:tests:T0\"/>"; + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + /* JSON */ + expected_string = "{\"T0:port\":\"\"}"; + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + /* free */ + lyd_free_all(model_1); + + /* print one bit */ + data = "<port xmlns=\"urn:tests:T0\"> two </port>"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, model_1) + /* XML */ + expected_string = "<port xmlns=\"urn:tests:T0\">two</port>"; + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + /* JSON */ + expected_string = "{\"T0:port\":\"two\"}"; + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + /* free */ + lyd_free_all(model_1); + + /* print two bits */ + data = "<port xmlns=\"urn:tests:T0\">three two </port>"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, model_1) + /* XML */ + expected_string = "<port xmlns=\"urn:tests:T0\">two three</port>"; + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + /* JSON */ + expected_string = "{\"T0:port\":\"two three\"}"; + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + /* free */ + lyd_free_all(model_1); +} + +static void +test_plugin_store(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_BITS]); + struct lysc_type *lysc_type; + struct lysc_type lysc_type_test; + LY_ERR ly_ret; + char *alloc; + const char *schema; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("T0", "leaf port {type bits { bit zero; bit one;" + " bit two; bit three;}}"); + 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 - bits, version 1", type->id); + + /* check store + */ + 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, BITS, ""); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "zero one two"; + 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, BITS, "zero one two", "zero", "one", "two"); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "zero two"; + 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, BITS, "zero two", "zero", "two"); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "\n "; + 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_SUCCESS, ly_ret); + CHECK_LYD_VALUE(value, BITS, ""); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + /* + * minor tests + * dynamic alocated input text + */ + val_text = "two"; + alloc = (char *)malloc(strlen(val_text) + 1); + memcpy(alloc, val_text, strlen(val_text) + 1); + ly_ret = type->store(UTEST_LYCTX, lysc_type, alloc, strlen(val_text), + LYPLG_TYPE_STORE_DYNAMIC, LY_VALUE_XML, NULL, LYD_VALHINT_STRING, NULL, &value, NULL, &err); + alloc = NULL; + assert_int_equal(LY_SUCCESS, ly_ret); + CHECK_LYD_VALUE(value, BITS, "two", "two"); + type->free(UTEST_LYCTX, &value); + + /* wrong lysc_type of value */ + lysc_type_test = *lysc_type; + lysc_type_test.basetype = LY_TYPE_INT8; + val_text = "two"; + 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); + + /* + * ERROR TESTS + */ + val_text = "two"; + err = NULL; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_HEXNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_EVALID, ly_ret); + ly_err_free(err); + + val_text = "two two"; + 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); +} + +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_BITS]); + 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; + /* Value which are going to be created to tested */ + const char *val_init[] = {"", "two zero", "three", "zero two", "zero", "three"}; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("T0", "typedef my_int_type { type bits { bit zero; bit one;" + " bit two; bit three;}}" + "leaf p1 {type my_int_type;}" + "leaf p2 {type my_int_type;}" + "leaf p3 {type my_int_type{bit three; bit zero;}}" + "leaf p4 {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type; + + /* CREATE VALUES */ + for (unsigned int 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[1]), &(values[3]))); + assert_int_equal(LY_ENOT, type->compare(&(values[0]), &(values[1]))); + assert_int_equal(LY_ENOT, type->compare(&(values[3]), &(values[4]))); + 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[2]), &(values[5]))); + + /* + * SAME TYPE but different node + */ + diff_type_text = val_init[2]; + 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[2]))); + assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[1]))); + type->free(UTEST_LYCTX, &(diff_type_val)); + + /* + * derivated type add some limitations + */ + diff_type_text = val_init[2]; + 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[2]))); + assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[1]))); + type->free(UTEST_LYCTX, &(diff_type_val)); + + /* + * different type (STRING) + */ + diff_type_text = val_init[2]; + 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_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[2]))); + assert_int_equal(LY_ENOT, type->compare(&diff_type_val, &(values[0]))); + type->free(UTEST_LYCTX, &(diff_type_val)); + + /* delete values */ + for (unsigned int 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_BITS]); + struct lysc_type *lysc_type; + LY_ERR ly_ret; + const char *schema; + /* Value which are going to be created to tested */ + const char *val_init[] = {"", "two zero", "three", "zero two", "zero", "three"}; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("T0", + "leaf p1 { type bits { bit zero; bit one;" + " bit two; bit three;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type; + + /* CREATE VALUES */ + for (unsigned int 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("", type->print(UTEST_LYCTX, &(values[0]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("zero two", type->print(UTEST_LYCTX, &(values[1]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("three", type->print(UTEST_LYCTX, &(values[2]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("zero two", type->print(UTEST_LYCTX, &(values[3]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("zero", type->print(UTEST_LYCTX, &(values[4]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("three", type->print(UTEST_LYCTX, &(values[5]), LY_VALUE_XML, NULL, &dynamic, NULL)); + + for (unsigned int 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_BITS]); + struct lysc_type *lysc_type; + const char *schema; + LY_ERR ly_ret; + /* Value which are going to be tested */ + const char *val_init[] = {"", "two zero", "three", "zero two", "zero", "three one two zero"}; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("T0", + "leaf p1 { type bits { bit zero; bit one;" + " bit two; bit three;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type; + + /* CREATE VALUES */ + for (unsigned int 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 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, BITS, ""); + 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, BITS, "zero two", "zero", "two"); + 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, BITS, "three", "three"); + 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, BITS, "zero two", "zero", "two"); + assert_ptr_equal(dup_value.realtype, values[3].realtype); + type->free(UTEST_LYCTX, &dup_value); + + assert_int_equal(LY_SUCCESS, type->duplicate(UTEST_LYCTX, &(values[4]), &dup_value)); + CHECK_LYD_VALUE(dup_value, BITS, "zero", "zero"); + assert_ptr_equal(dup_value.realtype, values[4].realtype); + type->free(UTEST_LYCTX, &dup_value); + + assert_int_equal(LY_SUCCESS, type->duplicate(UTEST_LYCTX, &(values[5]), &dup_value)); + CHECK_LYD_VALUE(dup_value, BITS, "zero one two three", "zero", "one", "two", "three"); + assert_ptr_equal(dup_value.realtype, values[5].realtype); + type->free(UTEST_LYCTX, &dup_value); + + /* error tests */ + assert_int_equal(LY_EINVAL, type->duplicate(NULL, &(values[0]), &dup_value)); + + for (unsigned int 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); +} diff --git a/tests/utests/types/boolean.c b/tests/utests/types/boolean.c new file mode 100644 index 0000000..841db2a --- /dev/null +++ b/tests/utests/types/boolean.c @@ -0,0 +1,111 @@ +/** + * @file boolean.c + * @author Adam Piecek <piecek@cesnet.cz> + * @brief test for built-in enumeration type + * + * 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" + +#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, NODE_NAME, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \ + lyd_free_all(tree); \ + } + +#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \ + {\ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \ + assert_null(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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "typedef tboolean {type boolean;}" + "leaf l1 {type boolean;}" + "leaf l2 {type tboolean;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML("defs", "l1", "true", BOOL, "true", 1); + + TEST_SUCCESS_XML("defs", "l1", "false", BOOL, "false", 0); + + TEST_SUCCESS_XML("defs", "l2", "false", BOOL, "false", 0); + + /* invalid value */ + TEST_ERROR_XML("defs", "l1", "unsure"); + CHECK_LOG_CTX("Invalid boolean value \"unsure\".", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "l1", " true"); + CHECK_LOG_CTX("Invalid boolean value \" true\".", + "Schema location \"/defs:l1\", line number 1."); +} + +static void +test_plugin_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", + "leaf bool {type boolean;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "bool", "true"); + TEST_SUCCESS_LYB("lyb", "bool", "false"); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + UTEST(test_plugin_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/decimal64.c b/tests/utests/types/decimal64.c new file mode 100644 index 0000000..e0a7cab --- /dev/null +++ b/tests/utests/types/decimal64.c @@ -0,0 +1,125 @@ +/** + * @file decimal64.c + * @author Adam Piecek <piecek@cesnet.cz> + * @brief test for built-in enumeration type + * + * 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" + +#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, NODE_NAME, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \ + lyd_free_all(tree); \ + } + +#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \ + {\ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \ + assert_null(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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "leaf l1 {type decimal64 {fraction-digits 1; range 1.5..10;}}" + "leaf l2 {type decimal64 {fraction-digits 18;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML("defs", "l1", "\n +8 \t\n ", DEC64, "8.0", 80); + TEST_SUCCESS_XML("defs", "l1", "8.00", DEC64, "8.0", 80); + + TEST_SUCCESS_XML("defs", "l2", "-9.223372036854775808", DEC64, "-9.223372036854775808", + INT64_C(-9223372036854775807) - INT64_C(1)); + TEST_SUCCESS_XML("defs", "l2", "9.223372036854775807", DEC64, "9.223372036854775807", INT64_C(9223372036854775807)); + + TEST_ERROR_XML("defs", "l1", "\n 15 \t\n "); + CHECK_LOG_CTX("Unsatisfied range - value \"15.0\" is out of the allowed range.", + "Schema location \"/defs:l1\", line number 3."); + + TEST_ERROR_XML("defs", "l1", "\n 0 \t\n "); + CHECK_LOG_CTX("Unsatisfied range - value \"0.0\" is out of the allowed range.", + "Schema location \"/defs:l1\", line number 3."); + + TEST_ERROR_XML("defs", "l1", "xxx"); + CHECK_LOG_CTX("Invalid 1. character of decimal64 value \"xxx\".", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "l1", ""); + CHECK_LOG_CTX("Invalid empty decimal64 value.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "l1", "8.5 xxx"); + CHECK_LOG_CTX("Invalid 6. character of decimal64 value \"8.5 xxx\".", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "l1", "8.55 xxx"); + CHECK_LOG_CTX("Value \"8.55\" of decimal64 type exceeds defined number (1) of fraction digits.", + "Schema location \"/defs:l1\", line number 1."); +} + +static void +test_plugin_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", + "leaf dec64 {type decimal64 {fraction-digits 1; range 1.5..10;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "dec64", "8.00"); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + UTEST(test_plugin_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/empty.c b/tests/utests/types/empty.c new file mode 100644 index 0000000..0ab9710 --- /dev/null +++ b/tests/utests/types/empty.c @@ -0,0 +1,108 @@ +/** + * @file empty.c + * @author Adam Piecek <piecek@cesnet.cz> + * @brief test for built-in enumeration type + * + * 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" + +#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, NODE_NAME, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \ + lyd_free_all(tree); \ + } + +#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \ + {\ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \ + assert_null(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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "typedef tempty {type empty;}" + "leaf l1 {type empty;}" + "leaf l2 {type tempty;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML("defs", "l1", "", EMPTY, ""); + + TEST_SUCCESS_XML("defs", "l2", "", EMPTY, ""); + + /* invalid value */ + TEST_ERROR_XML("defs", "l1", "x"); + CHECK_LOG_CTX("Invalid empty value length 1.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "l1", " "); + CHECK_LOG_CTX("Invalid empty value length 1.", + "Schema location \"/defs:l1\", line number 1."); +} + +static void +test_plugin_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", + "leaf empty {type empty;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "empty", ""); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + UTEST(test_plugin_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/enumeration.c b/tests/utests/types/enumeration.c new file mode 100644 index 0000000..660479f --- /dev/null +++ b/tests/utests/types/enumeration.c @@ -0,0 +1,114 @@ +/** + * @file enumeration.c + * @author Adam Piecek <piecek@cesnet.cz> + * @brief test for built-in enumeration type + * + * 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" + +#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, NODE_NAME, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \ + lyd_free_all(tree); \ + } + +#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \ + {\ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \ + assert_null(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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "feature f; leaf l1 {type enumeration {enum white; enum yellow {if-feature f;}}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML("defs", "l1", "white", ENUM, "white", "white"); + + /* disabled feature */ + TEST_ERROR_XML("defs", "l1", "yellow"); + CHECK_LOG_CTX("Invalid enumeration value \"yellow\".", + "Schema location \"/defs:l1\", line number 1."); + + /* leading/trailing whitespaces */ + TEST_ERROR_XML("defs", "l1", " white"); + CHECK_LOG_CTX("Invalid enumeration value \" white\".", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "l1", "white\n"); + CHECK_LOG_CTX("Invalid enumeration value \"white\n\".", + "Schema location \"/defs:l1\", line number 2."); + + /* invalid value */ + TEST_ERROR_XML("defs", "l1", "black"); + CHECK_LOG_CTX("Invalid enumeration value \"black\".", + "Schema location \"/defs:l1\", line number 1."); +} + +static void +test_plugin_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", "leaf l1 {type enumeration {enum white; enum yellow; enum black;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "l1", "white"); + TEST_SUCCESS_LYB("lyb", "l1", "black"); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + UTEST(test_plugin_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/identityref.c b/tests/utests/types/identityref.c new file mode 100644 index 0000000..cdfe057 --- /dev/null +++ b/tests/utests/types/identityref.c @@ -0,0 +1,123 @@ +/** + * @file identityref.c + * @author Adam Piecek <piecek@cesnet.cz> + * @brief test for built-in enumeration type + * + * 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" + +#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, NAMESPACES, NODE_NAME, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \ + lyd_free_all(tree); \ + } + +#define TEST_ERROR_XML(MOD_NAME, NAMESPACES, NODE_NAME, DATA) \ + {\ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \ + assert_null(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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema, *schema2; + + /* xml test */ + schema = MODULE_CREATE_YANG("ident-base", "identity ident-base;" + "identity ident-imp {base ident-base;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + schema2 = MODULE_CREATE_YANG("defs", "import ident-base {prefix ib;}" + "identity ident1 {base ib:ident-base;}" + "leaf l1 {type identityref {base ib:ident-base;}}"); + UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML("defs", "", "l1", "ident1", IDENT, "defs:ident1", "ident1"); + + TEST_SUCCESS_XML("defs", "xmlns:i=\"urn:tests:ident-base\"", "l1", "i:ident-imp", IDENT, "ident-base:ident-imp", + "ident-imp"); + + /* invalid value */ + TEST_ERROR_XML("defs", "", "l1", "fast-ethernet"); + CHECK_LOG_CTX("Invalid identityref \"fast-ethernet\" value - identity not found in module \"defs\".", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "xmlns:x=\"urn:tests:defs\"", "l1", "x:slow-ethernet"); + CHECK_LOG_CTX("Invalid identityref \"x:slow-ethernet\" value - identity not found in module \"defs\".", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "xmlns:x=\"urn:tests:ident-base\"", "l1", "x:ident-base"); + CHECK_LOG_CTX("Invalid identityref \"x:ident-base\" value - identity not derived from the base \"ident-base:ident-base\".", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "xmlns:x=\"urn:tests:unknown\"", "l1", "x:ident-base"); + CHECK_LOG_CTX("Invalid identityref \"x:ident-base\" value - unable to map prefix to YANG schema.", + "Schema location \"/defs:l1\", line number 1."); +} + +static void +test_plugin_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", + "identity idbase;" + "identity ident {base idbase;}" + "leaf lf {type identityref {base idbase;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "lf", "ident"); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + UTEST(test_plugin_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/inet_types.c b/tests/utests/types/inet_types.c new file mode 100644 index 0000000..eb4e480 --- /dev/null +++ b/tests/utests/types/inet_types.c @@ -0,0 +1,149 @@ +/** + * @file inet_types.c + * @author Michal Vaško <mvasko@cesnet.cz> + * @brief test for ietf-inet-types 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.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" \ + " import ietf-inet-types {\n" \ + " prefix inet;\n" \ + " }\n" \ + NODES \ + "}\n" + +#define TEST_SUCCESS_XML(MOD_NAME, NODE_NAME, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + 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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("a", + "leaf l {type inet:ip-address;}" + "leaf l2 {type inet:ipv6-address;}" + "leaf l3 {type inet:ip-address-no-zone;}" + "leaf l4 {type inet:ipv6-address-no-zone;}" + "leaf l5 {type inet:ip-prefix;}" + "leaf l6 {type inet:ipv4-prefix;}" + "leaf l7 {type inet:ipv6-prefix;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + /* ip-address */ + TEST_SUCCESS_XML("a", "l", "192.168.0.1", UNION, "192.168.0.1", STRING, "192.168.0.1"); + TEST_SUCCESS_XML("a", "l", "192.168.0.1%12", UNION, "192.168.0.1%12", STRING, "192.168.0.1%12"); + TEST_SUCCESS_XML("a", "l", "2008:15:0:0:0:0:feAC:1", UNION, "2008:15::feac:1", STRING, "2008:15::feac:1"); + + /* ipv6-address */ + TEST_SUCCESS_XML("a", "l2", "FAAC:21:011:Da85::87:daaF%1", STRING, "faac:21:11:da85::87:daaf%1"); + + /* ip-address-no-zone */ + TEST_SUCCESS_XML("a", "l3", "127.0.0.1", UNION, "127.0.0.1", STRING, "127.0.0.1"); + TEST_SUCCESS_XML("a", "l3", "0:00:000:0000:000:00:0:1", UNION, "::1", STRING, "::1"); + + /* ipv6-address-no-zone */ + TEST_SUCCESS_XML("a", "l4", "A:B:c:D:e:f:1:0", STRING, "a:b:c:d:e:f:1:0"); + + /* ip-prefix */ + TEST_SUCCESS_XML("a", "l5", "158.1.58.4/1", UNION, "128.0.0.0/1", STRING, "128.0.0.0/1"); + TEST_SUCCESS_XML("a", "l5", "158.1.58.4/24", UNION, "158.1.58.0/24", STRING, "158.1.58.0/24"); + TEST_SUCCESS_XML("a", "l5", "2000:A:B:C:D:E:f:a/16", UNION, "2000::/16", STRING, "2000::/16"); + + /* ipv4-prefix */ + TEST_SUCCESS_XML("a", "l6", "0.1.58.4/32", STRING, "0.1.58.4/32"); + TEST_SUCCESS_XML("a", "l6", "12.1.58.4/8", STRING, "12.0.0.0/8"); + + /* ipv6-prefix */ + TEST_SUCCESS_XML("a", "l7", "::C:D:E:f:a/112", STRING, "::c:d:e:f:0/112"); + TEST_SUCCESS_XML("a", "l7", "::C:D:E:f:a/110", STRING, "::c:d:e:c:0/110"); + TEST_SUCCESS_XML("a", "l7", "::C:D:E:f:a/96", STRING, "::c:d:e:0:0/96"); + TEST_SUCCESS_XML("a", "l7", "::C:D:E:f:a/55", STRING, "::/55"); +} + +static void +test_data_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", + "leaf l {type inet:ip-address;}" + "leaf l2 {type inet:ipv6-address;}" + "leaf l3 {type inet:ip-address-no-zone;}" + "leaf l4 {type inet:ipv6-address-no-zone;}" + "leaf l5 {type inet:ip-prefix;}" + "leaf l6 {type inet:ipv4-prefix;}" + "leaf l7 {type inet:ipv6-prefix;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_LYB("lyb", "l", "192.168.0.1"); + TEST_SUCCESS_LYB("lyb", "l2", "FAAC:21:011:Da85::87:daaF%1"); + TEST_SUCCESS_LYB("lyb", "l3", "127.0.0.1"); + TEST_SUCCESS_LYB("lyb", "l4", "A:B:c:D:e:f:1:0"); + TEST_SUCCESS_LYB("lyb", "l5", "158.1.58.4/1"); + TEST_SUCCESS_LYB("lyb", "l6", "12.1.58.4/8"); + TEST_SUCCESS_LYB("lyb", "l7", "::C:D:E:f:a/112"); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + UTEST(test_data_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/instanceid.c b/tests/utests/types/instanceid.c new file mode 100644 index 0000000..06c8622 --- /dev/null +++ b/tests/utests/types/instanceid.c @@ -0,0 +1,292 @@ +/** + * @file instanceid.c + * @author Adam Piecek <piecek@cesnet.cz> + * @brief test for built-in enumeration type + * + * 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" +#include "path.h" + +#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_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = XML1 "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 1, 0, 1, TYPE, __VA_ARGS__); \ + lyd_free_all(tree); \ + } + +#define TEST_ERROR_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, RET) \ + {\ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, RET, tree); \ + assert_null(tree); \ + } + +#define LYB_CHECK_START \ + struct lyd_node *tree_1; \ + struct lyd_node *tree_2; \ + char *xml_out, *data; + +#define LYB_CHECK_END \ + { \ + 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_SUCCESS_LYB(MOD_NAME, NODE_NAME1, DATA1, NODE_NAME2, DATA2) \ + LYB_CHECK_START \ + data = "<" NODE_NAME1 " xmlns=\"urn:tests:" MOD_NAME "\">" DATA1 "</" NODE_NAME1 ">" \ + "<xdf:" NODE_NAME2 " xmlns:xdf=\"urn:tests:" MOD_NAME "\">/xdf:" DATA2 "</xdf:" NODE_NAME2 ">"; \ + LYB_CHECK_END \ + +#define TEST_SUCCESS_LYB2(MOD_NAME, NODE_NAME, DATA) \ + { \ + LYB_CHECK_START \ + data = "<" NODE_NAME " xmlns:aa=\"urn:tests:lyb2\" xmlns=\"urn:tests:" MOD_NAME "\">/aa:" DATA "</" NODE_NAME ">"; \ + LYB_CHECK_END \ + } + +static void +test_data_xml(void **state) +{ + const char *schema, *schema2; + const enum ly_path_pred_type val1[] = {LY_PATH_PREDTYPE_NONE, LY_PATH_PREDTYPE_NONE}; + const enum ly_path_pred_type val2[] = {LY_PATH_PREDTYPE_LIST, LY_PATH_PREDTYPE_NONE}; + const enum ly_path_pred_type val3[] = {LY_PATH_PREDTYPE_LEAFLIST}; + const enum ly_path_pred_type val4[] = {LY_PATH_PREDTYPE_LIST, LY_PATH_PREDTYPE_NONE}; + const enum ly_path_pred_type val5[] = {LY_PATH_PREDTYPE_LIST, LY_PATH_PREDTYPE_NONE}; + const enum ly_path_pred_type val6[] = {LY_PATH_PREDTYPE_LIST, LY_PATH_PREDTYPE_NONE}; + + /* xml test */ + schema = MODULE_CREATE_YANG("mod", "container cont {leaf l2 {type empty;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + schema2 = MODULE_CREATE_YANG("defs", "identity ident; identity ident-der1 {base ident;} identity ident-der2 {base ident;}" + "leaf l1 {type instance-identifier {require-instance true;}}" + "leaf l2 {type instance-identifier {require-instance false;}}" + "container cont {leaf l {type empty;}}" + "list list {key \"id\"; leaf id {type string;} leaf value {type string;}}" + "leaf-list llist {type uint32;}" + "list list-inst {key \"id\"; leaf id {type instance-identifier;} leaf value {type string;}}" + "list list-ident {key \"id\"; leaf id {type identityref {base ident;}} leaf value {type string;}}" + "list list2 {key \"id id2\"; leaf id {type string;} leaf id2 {type string;}}" + "list list-keyless {config false; leaf value {type string;}}"); + UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML2("<cont xmlns=\"urn:tests:defs\"><l/></cont>", "defs", "xmlns:xdf=\"urn:tests:defs\"", "l1", + "/xdf:cont/xdf:l", INST, "/defs:cont/l", val1); + + TEST_SUCCESS_XML2("<list xmlns=\"urn:tests:defs\"><id>a</id></list><list xmlns=\"urn:tests:defs\"><id>b</id></list>", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/xdf:list[xdf:id='b']/xdf:id", INST, + "/defs:list[id='b']/id", val2); + + TEST_SUCCESS_XML2("<llist xmlns=\"urn:tests:defs\">1</llist><llist xmlns=\"urn:tests:defs\">2</llist>", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/xdf:llist[.='1']", INST, "/defs:llist[.='1']", val3); + + TEST_SUCCESS_XML2("<list-inst xmlns=\"urn:tests:defs\"><id xmlns:b=\"urn:tests:defs\">/b:llist[.='1']</id>" + "<value>x</value></list-inst>" + "<list-inst xmlns=\"urn:tests:defs\"><id xmlns:b=\"urn:tests:defs\">/b:llist[.='2']</id>" + "<value>y</value></list-inst>" + "<llist xmlns=\"urn:tests:defs\">1</llist><llist xmlns=\"urn:tests:defs\">2</llist>", + "defs", "xmlns:a=\"urn:tests:defs\"", "a:l1", "/a:list-inst[a:id=\"/a:llist[.='1']\"]/a:value", + INST, "/defs:list-inst[id=\"/defs:llist[.='1']\"]/value", val4); + + TEST_SUCCESS_XML2("<list-ident xmlns=\"urn:tests:defs\"><id xmlns:b=\"urn:tests:defs\">b:ident-der1</id>" + "<value>x</value></list-ident>" + "<list-ident xmlns=\"urn:tests:defs\"><id xmlns:b=\"urn:tests:defs\">b:ident-der2</id>" + "<value>y</value></list-ident>", + "defs", "xmlns:a=\"urn:tests:defs\"", "a:l1", "/a:list-ident[a:id='a:ident-der1']/a:value", + INST, "/defs:list-ident[id='defs:ident-der1']/value", val5); + + TEST_SUCCESS_XML2("<list2 xmlns=\"urn:tests:defs\"><id>defs:xxx</id><id2>x</id2></list2>" + "<list2 xmlns=\"urn:tests:defs\"><id>a:xxx</id><id2>y</id2></list2>", + "defs", "xmlns:a=\"urn:tests:defs\"", "a:l1", "/a:list2[a:id='a:xxx'][a:id2='y']/a:id2", + INST, "/defs:list2[id='a:xxx'][id2='y']/id2", val6); + + /* syntax/semantic errors */ + TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>a</id></list>" + "<list xmlns=\"urn:tests:defs\"><id>b</id><value>x</value></list>", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/xdf:list[2]/xdf:value", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[2]/xdf:value\" value - semantic error.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML2("", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/t:cont/t:1l", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/t:cont/t:1l\" value - syntax error.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML2("", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/t:cont:t:1l", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/t:cont:t:1l\" value - syntax error.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML2("", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l1", "/xdf:cont/xdf:invalid/xdf:path", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:cont/xdf:invalid/xdf:path\" value - semantic error.", + "Schema location \"/defs:l1\", line number 1."); + + /* non-existing instances, instance-identifier is here in JSON format because it is already in internal + * representation without canonical prefixes */ + TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"/>", + "defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont/m:l2", LY_ENOTFOUND); + CHECK_LOG_CTX_APPTAG("Invalid instance-identifier \"/mod:cont/l2\" value - required instance not found.", + "Data location \"/defs:l1\".", "instance-required"); + + TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">1</llist>", + "defs", "xmlns:a=\"urn:tests:defs\"", "l1", "/a:llist[.='2']", LY_ENOTFOUND); + CHECK_LOG_CTX_APPTAG("Invalid instance-identifier \"/defs:llist[.='2']\" value - required instance not found.", + "Data location \"/defs:l1\".", "instance-required"); + + TEST_ERROR_XML2("<list2 xmlns=\"urn:tests:defs\"><id>a</id><id2>a</id2></list2>" + "<list2 xmlns=\"urn:tests:defs\"><id>c</id><id2>b</id2></list2>" + "<llist xmlns=\"urn:tests:defs\">a</llist>" + "<llist xmlns=\"urn:tests:defs\">b</llist>", + "defs", "xmlns:a=\"urn:tests:defs\"", "l1", "/a:list2[a:id='a'][a:id2='a']/a:id", LY_ENOTFOUND); + CHECK_LOG_CTX_APPTAG("Invalid instance-identifier \"/defs:list2[id='a'][id2='a']/id\" value - required instance not found.", + "Data location \"/defs:l1\".", "instance-required"); + + TEST_ERROR_XML2("<list2 xmlns=\"urn:tests:defs\"><id>a</id><id2>a</id2></list2>" + "<list2 xmlns=\"urn:tests:defs\"><id>c</id><id2>b</id2></list2>" + "<llist xmlns=\"urn:tests:defs\">1</llist>" + "<llist xmlns=\"urn:tests:defs\">2</llist>", + "defs", "xmlns:a=\"urn:tests:defs\"", "l1", "/a:llist[.='3']", LY_ENOTFOUND); + CHECK_LOG_CTX_APPTAG("Invalid instance-identifier \"/defs:llist[.='3']\" value - required instance not found.", + "Data location \"/defs:l1\".", "instance-required"); + + TEST_ERROR_XML2("", + "defs", "xmlns:a=\"urn:tests:defs\"", "l1", "/a:list-keyless[3]", LY_ENOTFOUND); + CHECK_LOG_CTX_APPTAG("Invalid instance-identifier \"/defs:list-keyless[3]\" value - required instance not found.", + "Data location \"/defs:l1\".", "instance-required"); + + /* more errors */ + TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">x</llist>", + "defs", "xmlns:t=\"urn:tests:defs\"", "t:l1", "/t:llist[1", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[1\" value - syntax error.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"/>", + "defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont[1]", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont[1]\" value - semantic error.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"/>", + "defs", "xmlns:m=\"urn:tests:mod\"", "l1", "[1]", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"[1]\" value - syntax error.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"><l2/></cont>", + "defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont/m:l2[l2='1']", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont/m:l2[l2='1']\" value - syntax error.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML2("<cont xmlns=\"urn:tests:mod\"><l2/></cont>", + "defs", "xmlns:m=\"urn:tests:mod\"", "l1", "/m:cont/m:l2[m:l2='1']", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/m:cont/m:l2[m:l2='1']\" value - semantic error.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">1</llist><llist xmlns=\"urn:tests:defs\">2</llist>", + "defs", "xmlns:t=\"urn:tests:defs\"", "t:l1", "/t:llist[4]", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[4]\" value - semantic error.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML2("", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/t:llist[6]", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[6]\" value - semantic error.", + "Schema location \"/defs:l2\", line number 1."); + + TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>1</id><value>x</value></list>", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list[xdf:value='x']", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[xdf:value='x']\" value - semantic error.", + "Schema location \"/defs:l2\", line number 1."); + + TEST_ERROR_XML2("", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list[.='x']", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[.='x']\" value - semantic error.", + "Schema location \"/defs:l2\", line number 1."); + + TEST_ERROR_XML2("<llist xmlns=\"urn:tests:defs\">1</llist>", + "defs", "xmlns:t=\"urn:tests:defs\"", "t:l1", "/t:llist[.='x']", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[.='x']\" value - semantic error.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML2("", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/t:llist[1][2]", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[1][2]\" value - syntax error.", + "Schema location \"/defs:l2\", line number 1."); + + TEST_ERROR_XML2("", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/t:llist[.='a'][.='b']", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/t:llist[.='a'][.='b']\" value - syntax error.", + "Schema location \"/defs:l2\", line number 1."); + + TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>1</id><value>x</value></list>", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list[xdf:id='1'][xdf:id='2']/xdf:value", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list[xdf:id='1'][xdf:id='2']/xdf:value\" value - syntax error.", + "Schema location \"/defs:l2\", line number 1."); + + TEST_ERROR_XML2("", + "defs", "xmlns:xdf=\"urn:tests:defs\"", "xdf:l2", "/xdf:list2[xdf:id='1']/xdf:value", LY_EVALID); + CHECK_LOG_CTX("Invalid instance-identifier \"/xdf:list2[xdf:id='1']/xdf:value\" value - semantic error.", + "Schema location \"/defs:l2\", line number 1."); +} + +static void +test_plugin_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", + "leaf-list leaflisttarget {type string;}" + "leaf inst {type instance-identifier {require-instance true;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "leaflisttarget", "1", "inst", "leaflisttarget[.='1']"); + + /* ietf-netconf-acm node-instance-identifier type */ + assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG)); + schema = MODULE_CREATE_YANG("lyb2", + "import ietf-netconf-acm {prefix acm;}" + "leaf-list ll {type string;}" + "leaf nii {type acm:node-instance-identifier;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB2("lyb2", "nii", "ll[. = 'some_string']"); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + UTEST(test_plugin_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/instanceid_keys.c b/tests/utests/types/instanceid_keys.c new file mode 100644 index 0000000..6d527cb --- /dev/null +++ b/tests/utests/types/instanceid_keys.c @@ -0,0 +1,77 @@ +/** + * @file instanceid_keys.c + * @author Michal Vasko <mvasko@cesnet.cz> + * @brief test for yang instance-identifier-keys type + * + * Copyright (c) 2022 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" + +#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_NS1(MOD_NAME, NODE_NAME, PREFIX, NS, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" xmlns:" PREFIX "=\"" NS "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \ + lyd_free_all(tree); \ + } + +#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \ + {\ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \ + assert_null(tree); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "import yang {prefix y;} leaf l1 {type y:instance-identifier-keys;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML_NS1("defs", "l1", "px", "urn:tests:defs", "[px:key='val']", STRING, "[defs:key='val']"); + + TEST_ERROR_XML("defs", "l1", "black"); + CHECK_LOG_CTX("Invalid first character 'b', list key predicates expected.", "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "l1", "[this is not a valid xpath]"); + CHECK_LOG_CTX("Invalid character 0x69 ('i'), perhaps \"this\" is supposed to be a function call.", + "Schema location \"/defs:l1\", line number 1."); + + TEST_ERROR_XML("defs", "l1", "[px:key='val']"); + CHECK_LOG_CTX("Failed to resolve prefix \"px\".", "Schema location \"/defs:l1\", line number 1."); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/int16.c b/tests/utests/types/int16.c new file mode 100644 index 0000000..f6796a1 --- /dev/null +++ b/tests/utests/types/int16.c @@ -0,0 +1,75 @@ +/** + * @file int16.c + * @author Michal Vasko <mvasko@cesnet.cz> + * @brief test for int16 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 + */ + +/* INCLUDE UTEST HEADER */ +#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_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_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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type int16 {range -20..-10;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_ERROR_XML("defs", "100"); + CHECK_LOG_CTX("Unsatisfied range - value \"100\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/int32.c b/tests/utests/types/int32.c new file mode 100644 index 0000000..9989a67 --- /dev/null +++ b/tests/utests/types/int32.c @@ -0,0 +1,75 @@ +/** + * @file int32.c + * @author Michal Vasko <mvasko@cesnet.cz> + * @brief test for int32 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 + */ + +/* INCLUDE UTEST HEADER */ +#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_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_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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type int32;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_ERROR_XML("defs", "0x01"); + CHECK_LOG_CTX("Invalid type int32 value \"0x01\".", + "Schema location \"/defs:port\", line number 1."); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/int64.c b/tests/utests/types/int64.c new file mode 100644 index 0000000..6b5e47e --- /dev/null +++ b/tests/utests/types/int64.c @@ -0,0 +1,83 @@ +/** + * @file int64.c + * @author Michal Vasko <mvasko@cesnet.cz> + * @brief test for int32 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 + */ + +/* INCLUDE UTEST HEADER */ +#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_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_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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type int64;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_ERROR_XML("defs", ""); + CHECK_LOG_CTX("Invalid type int64 empty value.", + "Schema location \"/defs:port\", line number 1."); + + TEST_ERROR_XML("defs", " "); + CHECK_LOG_CTX("Invalid type int64 empty value.", + "Schema location \"/defs:port\", line number 1."); + + TEST_ERROR_XML("defs", "-10 xxx"); + CHECK_LOG_CTX("Invalid type int64 value \"-10 xxx\".", + "Schema location \"/defs:port\", line number 1."); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/int8.c b/tests/utests/types/int8.c new file mode 100644 index 0000000..7d0b9ad --- /dev/null +++ b/tests/utests/types/int8.c @@ -0,0 +1,1765 @@ +/** + * @file int8.c + * @author Radek Iša <isa@cesnet.cz> + * @brief test for int8 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 + */ + +/* INCLUDE UTEST HEADER */ +#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 LYD_TREE_CREATE(INPUT, MODEL) \ + CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, MODEL) + +#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_range *range; + + schema = MODULE_CREATE_YANG("defs", "leaf port {type int8 {range \"0 .. 50 | 127\";}}"); + 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_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_64, 0); + assert_int_equal(range->parts[0].max_64, 50); + assert_int_equal(range->parts[1].min_64, 127); + assert_int_equal(range->parts[1].max_64, 127); + 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, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "0 .. 50 | 127", NULL, NULL, NULL, 0, NULL); + + /* TEST MODULE T0 */ + schema = MODULE_CREATE_YANG("T0", "leaf port {type int8;}"); + 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_INT8, 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, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST MODULE T1 */ + schema = MODULE_CREATE_YANG("T1", "leaf port {type int8 {range \"0 .. 50 |51 .. 60\";}}"); + 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_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_64, 0); + assert_int_equal(range->parts[0].max_64, 50); + assert_int_equal(range->parts[1].min_64, 51); + assert_int_equal(range->parts[1].max_64, 60); + 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, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "0 .. 50 |51 .. 60", NULL, NULL, NULL, 0, NULL); + + /* TEST MODULE T1 */ + schema = MODULE_CREATE_YANG("T2", "leaf port {type int8 {range \"20\";}}"); + 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_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_64, 20); + assert_int_equal(range->parts[0].max_64, 20); + 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, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "20", NULL, NULL, NULL, 0, NULL); + + /* TEST MODULE T3 */ + schema = MODULE_CREATE_YANG("T3", "leaf port {type int8 {range \"-128 .. -60 | -1 .. 1 | 60 .. 127\";}}"); + 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_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 3, NULL); + assert_int_equal(range->parts[0].min_64, -128); + assert_int_equal(range->parts[0].max_64, -60); + assert_int_equal(range->parts[1].min_64, -1); + assert_int_equal(range->parts[1].max_64, 1); + assert_int_equal(range->parts[2].min_64, 60); + assert_int_equal(range->parts[2].max_64, 127); + 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, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "-128 .. -60 | -1 .. 1 | 60 .. 127", NULL, NULL, NULL, 0, NULL); + + /* TEST MODULE T4 */ + schema = MODULE_CREATE_YANG("T4", "leaf port {type int8 {range \"1 .. 1\";}}"); + 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_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_64, 1); + assert_int_equal(range->parts[0].max_64, 1); + 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, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "1 .. 1", NULL, NULL, NULL, 0, NULL); + + /* TEST MODULE T4 */ + schema = MODULE_CREATE_YANG("T5", "leaf port {type int8 {range \"7\";}}"); + 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_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_64, 7); + assert_int_equal(range->parts[0].max_64, 7); + 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, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "7", NULL, NULL, NULL, 0, NULL); + + /* TEST MODULE T4 */ + schema = MODULE_CREATE_YANG("T6", "leaf port {type int8 {range \"min .. 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_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_64, -128); + assert_int_equal(range->parts[0].max_64, 127); + 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, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "min .. max", NULL, NULL, NULL, 0, NULL); + + /* TEST ERROR -60 .. 0 | 0 .. 127 */ + schema = MODULE_CREATE_YANG("ERR0", "leaf port {type int8 {range \"-60 .. 0 | 0 .. 127\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EEXIST); + CHECK_LOG_CTX("Invalid range restriction - values are not in ascending order (0).", "/ERR0:port"); + + /* TEST ERROR 0 .. 128 */ + schema = MODULE_CREATE_YANG("ERR1", "leaf port {type int8 {range \"0 .. 128\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED); + CHECK_LOG_CTX("Invalid range restriction - value \"128\" does not fit the type limitations.", "/ERR1:port"); + + /* TEST ERROR -129 .. 126 */ + schema = MODULE_CREATE_YANG("ERR2", "leaf port {type int8 {range \"-129 .. 0\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED); + CHECK_LOG_CTX("Invalid range restriction - value \"-129\" does not fit the type limitations.", "/ERR2:port"); + + /* TEST ERROR 0 */ + schema = MODULE_CREATE_YANG("ERR3", "leaf port {type int8 {range \"-129\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED); + CHECK_LOG_CTX("Invalid range restriction - value \"-129\" does not fit the type limitations.", "/ERR3:port"); + + /* + * TEST MODULE SUBTYPE + */ + schema = MODULE_CREATE_YANG("TS0", + "typedef my_int_type {" + " type int8 {range \"-128 .. -60 | -1 .. 1 | 60 .. 127\";}" + "}" + "leaf my_leaf {type my_int_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, "my_leaf", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 3, NULL); + assert_int_equal(range->parts[0].min_64, -128); + assert_int_equal(range->parts[0].max_64, -60); + assert_int_equal(range->parts[1].min_64, -1); + assert_int_equal(range->parts[1].max_64, 1); + assert_int_equal(range->parts[2].min_64, 60); + assert_int_equal(range->parts[2].max_64, 127); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "my_leaf", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_int_type", 0, 0, 1, 0, 0, 0); + + /* TEST SUBTYPE RANGE */ + schema = MODULE_CREATE_YANG("TS1", + "typedef my_int_type {" + " type int8 {range \"-100 .. -60 | -1 .. 1 | 60 .. 127\";}" + "}" + "leaf my_leaf {type my_int_type {range \"min .. -60\";}}"); + 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, "my_leaf", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_64, -100); + assert_int_equal(range->parts[0].max_64, -60); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "my_leaf", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "my_int_type", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "min .. -60", NULL, NULL, NULL, 0, NULL); + + /* TEST SUBTYPE RANGE */ + schema = MODULE_CREATE_YANG("TS2", + "typedef my_int_type {" + " type int8 {range \"-100 .. -60 | -1 .. 1 | 60 .. 120\";}" + "}" + "leaf my_leaf {type my_int_type {range \"70 .. 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, "my_leaf", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_64, 70); + assert_int_equal(range->parts[0].max_64, 120); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "my_leaf", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "my_int_type", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "70 .. max", NULL, NULL, NULL, 0, NULL); + + /* TEST SUBTYPE RANGE */ + schema = MODULE_CREATE_YANG("TS3", + "typedef my_int_type {" + " type int8 {range \"-100 .. -60 | -1 .. 1 | 60 .. 127\";}" + "}" + "leaf my_leaf {type my_int_type {range \"-1 .. 1\";}}"); + 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, "my_leaf", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_64, -1); + assert_int_equal(range->parts[0].max_64, 1); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "my_leaf", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "my_int_type", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "-1 .. 1", NULL, NULL, NULL, 0, NULL); + + /* TEST SUBTYPE RANGE */ + schema = MODULE_CREATE_YANG("TS4", + "typedef my_int_type {" + " type int8 {range \"-128 .. -60 | -1 .. 1 | 60 .. 127\";}" + "}" + "leaf my_leaf {type my_int_type { " + " range \"min .. -60 | -1 .. 1 | 60 .. 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, "my_leaf", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 3, NULL); + assert_int_equal(range->parts[0].min_64, -128); + assert_int_equal(range->parts[0].max_64, -60); + assert_int_equal(range->parts[1].min_64, -1); + assert_int_equal(range->parts[1].max_64, 1); + assert_int_equal(range->parts[2].min_64, 60); + assert_int_equal(range->parts[2].max_64, 127); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "my_leaf", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "my_int_type", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "min .. -60 | -1 .. 1 | 60 .. max", NULL, NULL, NULL, 0, NULL); + + /* TEST SUBTYPE ERROR min .. max */ + schema = MODULE_CREATE_YANG("TS_ERR0", + "typedef my_int_type { type int8 {range \"-128 .. -60 | -1 .. 1 | 60 .. 127\";}}" + "leaf my_leaf {type my_int_type {range \"min .. max\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid range restriction - the derived restriction (min .. max) is not equally or more limiting.", + "/TS_ERR0:my_leaf"); + + /* TEST SUBTYPE ERROR -80 .. 80 */ + schema = MODULE_CREATE_YANG("TS_ERR1", + "typedef my_int_type { type int8 {range \"-128 .. -60 | -1 .. 1 | 60 .. 127\";}}" + " leaf my_leaf {type my_int_type {range \"-80 .. 80\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid range restriction - the derived restriction (-80 .. 80) is not equally or more limiting.", + "/TS_ERR1:my_leaf"); + + /* TEST SUBTYPE ERROR 0 .. max */ + schema = MODULE_CREATE_YANG("TS_ERR2", + "typedef my_int_type { type int8 {range \"-128 .. -60 | -1 .. 1 | 60 .. 127\";}}" + "leaf my_leaf {type my_int_type {range \"0 .. max\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid range restriction - the derived restriction (0 .. max) is not equally or more limiting.", + "/TS_ERR2:my_leaf"); + + /* TEST SUBTYPE ERROR -2 .. 2 */ + schema = MODULE_CREATE_YANG("TS_ERR3", + "typedef my_int_type { type int8 {range \"-128 .. -60 | -1 .. 1 | 60 .. 127\";}}" + "leaf my_leaf {type my_int_type {range \"-2 .. 2\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid range restriction - the derived restriction (-2 .. 2) is not equally or more limiting.", + "/TS_ERR3:my_leaf"); + + /* TEST SUBTYPE ERROR -2 .. 2 */ + schema = MODULE_CREATE_YANG("TS_ERR4", + "typedef my_int_type { type int8 {range \"-128 .. -60 | -1 .. 1 | 60 .. 127\";}}" + "leaf my_leaf {type my_int_type {range \"-100 .. -90 | 100 .. 128\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EDENIED); + CHECK_LOG_CTX("Invalid range restriction - value \"128\" does not fit the type limitations.", + "/TS_ERR4:my_leaf"); + + /* + * TEST DEFAULT VALUE + */ + schema = MODULE_CREATE_YANG("DF0", + "leaf port {" + " type int8 {range \"0 .. 50 | 127\";}" + " default \"20\";" + "}"); + 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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "20", 20); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_64, 0); + assert_int_equal(range->parts[0].max_64, 50); + assert_int_equal(range->parts[1].min_64, 127); + assert_int_equal(range->parts[1].max_64, 127); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "20"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "0 .. 50 | 127", NULL, NULL, NULL, 0, NULL); + + /* TEST DEFAULT VALUE */ + schema = MODULE_CREATE_YANG("DF1", "leaf port {type int8 {range \"0 .. 50 | 127\";}" + "default \"127\"; }"); + 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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "127", 127); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_64, 0); + assert_int_equal(range->parts[0].max_64, 50); + assert_int_equal(range->parts[1].min_64, 127); + assert_int_equal(range->parts[1].max_64, 127); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "127"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "0 .. 50 | 127", NULL, NULL, NULL, 0, NULL); + + /* TEST DEFAULT VALUE ERROR */ + schema = MODULE_CREATE_YANG("TD_ERR0", + "leaf port {" + " type int8 {range \"0 .. 50 | 127\";}" + " default \"128\";" + "}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"128\" is out of type int8 min/max bounds.).", + "Schema location \"/TD_ERR0:port\"."); + + /* TEST DEFAULT VALUE ERROR */ + schema = MODULE_CREATE_YANG("TD_ERR1", + "leaf port {" + " type int8 {range \"0 .. 50 | 127\";}" + " default \"-1\";" + "}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Unsatisfied range - value \"-1\" is out of the allowed range.).", + "Schema location \"/TD_ERR1:port\"."); + + /* TEST DEFAULT VALUE ERROR */ + schema = MODULE_CREATE_YANG("TD_ERR2", + "leaf port {" + " type int8 {range \"0 .. 50 | 127\";}" + " default \"60\";" + "}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Unsatisfied range - value \"60\" is out of the allowed range.).", + "Schema location \"/TD_ERR2:port\"."); + + /* TEST DEFAULT VALUE ERROR */ + schema = MODULE_CREATE_YANG("TD_ERR3", + "typedef my_int_type { type int8 {range \"60 .. 127\";} default \"127\";}" + "leaf my_leaf {type my_int_type {range \"70 .. 80\";}}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Unsatisfied range - value \"127\" is out of the allowed range.).", + "Schema location \"/TD_ERR3:my_leaf\"."); + + /* TEST DEFAULT HEXADECIMAL */ + schema = MODULE_CREATE_YANG("DF_HEX0", + "leaf port {" + " type int8;" + " default \"0xf\";" + "}"); + 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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "15", 15); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "0xf"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST DEFAULT HEXADECIMAL */ + schema = MODULE_CREATE_YANG("DF_HEX1", + "leaf port {" + " type int8;" + " default \"-0xf\";" + "}"); + 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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "-15", -15); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "-0xf"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST DEFAULT HEXADECIMAL */ + schema = MODULE_CREATE_YANG("DF_HEXI0", + "leaf port {" + " type int8 {range \"0 .. 50 | 127\";}" + " default \"+0x7F\";" + "}"); + 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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "127", 127); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_64, 0); + assert_int_equal(range->parts[0].max_64, 50); + assert_int_equal(range->parts[1].min_64, 127); + assert_int_equal(range->parts[1].max_64, 127); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "+0x7F"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "0 .. 50 | 127", NULL, NULL, NULL, 0, NULL); + + /* TEST DEFAULT HEXADECIMAL ERROR */ + schema = MODULE_CREATE_YANG("DF_HEX2", + "leaf port {" + " type int8;" + " default \"0xff\";" + "}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"0xff\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_HEX2:port\"."); + + /* TEST DEFAULT HEXADECIMAL ERROR */ + schema = MODULE_CREATE_YANG("DF_HEX3", + "leaf port {" + " type int8;" + " default \"-0x81\";" + "}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"-0x81\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_HEX3:port\"."); + + /* TEST DEFAULT HEXADECIMAL ERROR */ + schema = MODULE_CREATE_YANG("DF_HEX4", + "leaf port {" + " type int8;" + " default \"0x80\";" + "}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"0x80\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_HEX4:port\"."); + + /* TEST DEFAULT VALUE OCTAL */ + schema = MODULE_CREATE_YANG("DF_OCT0", + "leaf port {" + " type int8;" + " default \"017\";" + "}"); + 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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "15", 15); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "017"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST DEFAULT VALUE OCTAL */ + schema = MODULE_CREATE_YANG("DF_OCT1", + "leaf port {" + " type int8;" + " default \"-017\";" + "}"); + 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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "-15", -15); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "-017"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST DEFAULT VALUE OCTAL */ + schema = MODULE_CREATE_YANG("DF_OCTI0", + "leaf port {" + " type int8;" + " default \"+017\";" + "}"); + 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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "15", 15); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "+017"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST DEFAULT VALUE OCTAL ERROR*/ + schema = MODULE_CREATE_YANG("DF_OCT2", + "leaf port {" + " type int8;" + " default \"0377\";" + "}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"0377\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_OCT2:port\"."); + + /* TEST DEFAULT VALUE OCTAL ERROR*/ + schema = MODULE_CREATE_YANG("DF_OCT3", + "leaf port {" + " type int8;" + " default \"-0201\";" + "}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"-0201\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_OCT3:port\"."); + + /* TEST DEFAULT VALUE OCTAL ERROR*/ + schema = MODULE_CREATE_YANG("DF_OCT4", + "leaf port {" + " type int8;" + " default \"0200\";" + "}"); + UTEST_INVALID_MODULE(schema, LYS_IN_YANG, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"0200\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_OCT4:port\"."); +} + +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_range *range; + + /* TEST T0 */ + schema = MODULE_CREATE_YIN("T0", "<leaf name=\"port\"> <type name=\"int8\"/> </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_INT8, 0, 0); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + 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, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST T1 */ + schema = MODULE_CREATE_YIN("T1", + "<leaf name=\"port\"> " + " <type name=\"int8\"> <range value = \"0 .. 10\"/> </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_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 1, NULL); + assert_int_equal(range->parts[0].min_64, 0); + assert_int_equal(range->parts[0].max_64, 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, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "0 .. 10", NULL, NULL, NULL, 0, NULL); + + /* TEST T1 */ + schema = MODULE_CREATE_YIN("T2", + "<leaf name=\"port\"> " + " <type name=\"int8\"> <range value = \"-127 .. 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_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_64, -127); + assert_int_equal(range->parts[0].max_64, 10); + assert_int_equal(range->parts[1].min_64, 127); + assert_int_equal(range->parts[1].max_64, 127); + 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, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "-127 .. 10 | max", NULL, NULL, NULL, 0, NULL); + + /* TEST T2 */ + schema = MODULE_CREATE_YIN("T3", + "<leaf name=\"port\"> " + " <type name=\"int8\"> <range value =\"min .. 10 | 11 .. 12 | 30\"/> </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_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 3, NULL); + assert_int_equal(range->parts[0].min_64, -128); + assert_int_equal(range->parts[0].max_64, 10); + assert_int_equal(range->parts[1].min_64, 11); + assert_int_equal(range->parts[1].max_64, 12); + assert_int_equal(range->parts[2].min_64, 30); + assert_int_equal(range->parts[2].max_64, 30); + 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, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "min .. 10 | 11 .. 12 | 30", NULL, NULL, NULL, 0, NULL); + + /* TEST ERROR -60 .. 0 | 0 .. 127 */ + schema = MODULE_CREATE_YIN("TE0", + "<leaf name=\"port\"> " + " <type name=\"int8\"> <range value = \"min .. 0 | 0 .. 12\"/> </type>" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EEXIST); + CHECK_LOG_CTX("Invalid range restriction - values are not in ascending order (0).", "/TE0:port"); + + /* TEST ERROR 0 .. 128 */ + schema = MODULE_CREATE_YIN("TE1", + "<leaf name=\"port\">" + " <type name=\"int8\"> <range value = \"0 .. 128\"/> </type>" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EDENIED); + CHECK_LOG_CTX("Invalid range restriction - value \"128\" does not fit the type limitations.", "/TE1:port"); + + /* TEST ERROR -129 .. 126 */ + schema = MODULE_CREATE_YIN("TE2", + "<leaf name=\"port\"> " + " <type name=\"int8\"> <range value =\"-129 .. 126\"/> </type>" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EDENIED); + CHECK_LOG_CTX("Invalid range restriction - value \"-129\" does not fit the type limitations.", "/TE2:port"); + + /* TEST YIN */ + schema = MODULE_CREATE_YIN("TS0", + "<typedef name= \"my_int_type\">" + " <type name=\"int8\"> <range value = \"-127 .. 10 | max\"/> </type>" + "</typedef>" + "<leaf name=\"my_leaf\"> <type name=\"my_int_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, "my_leaf", 0, 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_64, -127); + assert_int_equal(range->parts[0].max_64, 10); + assert_int_equal(range->parts[1].min_64, 127); + assert_int_equal(range->parts[1].max_64, 127); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "my_leaf", 0, 0, NULL, 0, 0, NULL, NULL); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "my_int_type", 0, 0, 1, 0, 0, 0); + + /* TEST YIN */ + schema = MODULE_CREATE_YIN("TS1", + "<typedef name= \"my_int_type\">" + " <type name=\"int8\"> <range value = \"-127 .. 10 | 90 .. 100\"/> </type>" + "</typedef>" + "<leaf name=\"port\"> <type name=\"my_int_type\"> <range value =" + " \"min .. -30 | 100 .. 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_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_64, -127); + assert_int_equal(range->parts[0].max_64, -30); + assert_int_equal(range->parts[1].min_64, 100); + assert_int_equal(range->parts[1].max_64, 100); + 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, 0x80, 0, 0, "my_int_type", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "min .. -30 | 100 .. max", NULL, NULL, NULL, 0, NULL); + + /* TEST ERROR */ + schema = MODULE_CREATE_YIN("TS_ERR1", + "<typedef name= \"my_int_type\">" + " <type name=\"int8\"> <range value = \"-127 .. 10 | 90 .. 100\"/> </type>" + "</typedef>" + "<leaf name=\"port\">" + " <type name=\"my_int_type\"> <range value = \"min .. max\"/> </type>" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid range restriction - the derived restriction (min .. max) is not equally or more limiting.", + "/TS_ERR1:port"); + + /* TEST ERROR */ + schema = MODULE_CREATE_YIN("TS_ERR2", + "<typedef name= \"my_int_type\">" + " <type name=\"int8\"> <range value = \"-127 .. 10 | 90 .. 100\"/> </type>" + "</typedef>" + "<leaf name=\"port\">" + " <type name=\"my_int_type\"> <range value = \"5 .. 11\"/> </type>" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid range restriction - the derived restriction (5 .. 11) is not equally or more limiting.", + "/TS_ERR2:port"); + + /* TEST DEFAULT VALUE */ + schema = MODULE_CREATE_YIN("DF0", + "<leaf name=\"port\">" + " <default value=\"12\" />" + " <type name=\"int8\"> <range value = \"min .. 0 | 1 .. 12\"/> </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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 1); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "12", 12); + range = ((struct lysc_type_num *)lysc_leaf->type)->range; + CHECK_LYSC_RANGE(range, NULL, NULL, NULL, 0, 2, NULL); + assert_int_equal(range->parts[0].min_64, -128); + assert_int_equal(range->parts[0].max_64, 0); + assert_int_equal(range->parts[1].min_64, 1); + assert_int_equal(range->parts[1].max_64, 12); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "12"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x80, 0, 0, "int8", 0, 0, 1, 1, 0, 0); + CHECK_LYSP_RESTR(lysp_leaf->type.range, "min .. 0 | 1 .. 12", NULL, NULL, NULL, 0, NULL); + + /* TEST ERROR TD0 */ + schema = MODULE_CREATE_YIN("TD_ERR0", + "<leaf name=\"port\">" + " <default value=\"128\" />" + " <type name=\"int8\"> <range value = \"min .. 0 | 1 .. 12\"/> </type>" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"128\" is out of type int8 min/max bounds.).", + "Schema location \"/TD_ERR0:port\"."); + + /* TEST ERROR TD1 */ + schema = MODULE_CREATE_YIN("TD_ERR1", + "<leaf name=\"port\">" + " <default value=\"13\" />" + " <type name=\"int8\"> <range value = \"min .. 0 | 1 .. 12\"/> </type>" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Unsatisfied range - value \"13\" is out of the allowed range.).", + "Schema location \"/TD_ERR1:port\"."); + + /* TEST ERROR TD1 */ + schema = MODULE_CREATE_YIN("TD_ERR3", + "<typedef name= \"my_int_type\">" + " <default value=\"10\" />" + " <type name=\"int8\"> <range value = \"-127 .. 10 | max\"/> </type>" + "</typedef>" + "<leaf name=\"my_leaf\">" + " <type name=\"my_int_type\">" + " <range value = \"-127 .. -80\"/> </type>" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Unsatisfied range - value \"10\" is out of the allowed range.).", + "Schema location \"/TD_ERR3:my_leaf\"."); + + /* TEST DEFAULT VALUE HEXADECIMAL */ + schema = MODULE_CREATE_YIN("DF_HEX0", + "<leaf name=\"port\">" + " <default value=\"+0xf\" />" + " <type name=\"int8\" />" + "</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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "15", 15); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "+0xf"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST DEFAULT VALUE HEXADECIMAL */ + schema = MODULE_CREATE_YIN("DF_HEX1", + "<leaf name=\"port\">" + " <default value=\"-0xf\" />" + " <type name=\"int8\" />" + "</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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "-15", -15); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "-0xf"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST DEFAULT VALUE HEXADECIMAL ERROR */ + schema = MODULE_CREATE_YIN("DF_HEX2", + "<leaf name=\"port\">" + " <default value=\"0xff\" />" + " <type name=\"int8\" />" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"0xff\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_HEX2:port\"."); + + /* TEST DEFAULT VALUE HEXADECIMAL ERROR */ + schema = MODULE_CREATE_YIN("DF_HEX2", + "<leaf name=\"port\">" + " <default value=\"-0x81\" />" + " <type name=\"int8\" />" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"-0x81\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_HEX2:port\"."); + + /* TEST DEFAULT VALUE HEXADECIMAL ERROR */ + schema = MODULE_CREATE_YIN("DF_HEX4", + "<leaf name=\"port\">" + " <default value=\"0x80\" />" + " <type name=\"int8\" />" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"0x80\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_HEX4:port\"."); + + /* TEST DEFAULT VALUE OCTAL */ + schema = MODULE_CREATE_YIN("DF_OCT0", + "<leaf name=\"port\">" + " <default value=\"+017\" />" + " <type name=\"int8\" />" + "</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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "15", 15); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "+017"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST DEFAULT VALUE OCTAL */ + schema = MODULE_CREATE_YIN("DF_OCT1", + "<leaf name=\"port\">" + " <default value=\"-017\" />" + " <type name=\"int8\" />" + "</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, 0x205, 1, "port", 0, 0, 0, NULL, 0, 0, NULL, 1); + CHECK_LYSC_TYPE_NUM((struct lysc_type_num *)lysc_leaf->type, LY_TYPE_INT8, 0, 0); + CHECK_LYD_VALUE(*(lysc_leaf->dflt), INT8, "-15", -15); + lysp_leaf = (void *)mod->parsed->data; + CHECK_LYSP_NODE_LEAF(lysp_leaf, NULL, 0, 0x0, 0, "port", 0, 0, NULL, 0, 0, NULL, "-017"); + CHECK_LYSP_TYPE(&(lysp_leaf->type), 0, 0, 0, 0, 0, 0x0, 0, 0, "int8", 0, 0, 1, 0, 0, 0); + + /* TEST DEFAULT VALUE OCTAL ERROR */ + schema = MODULE_CREATE_YIN("DF_OCT2", + "<leaf name=\"port\">" + " <default value=\"-0201\" />" + " <type name=\"int8\" />" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"-0201\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_OCT2:port\"."); + + /* TEST DEFAULT VALUE OCTAL ERROR */ + schema = MODULE_CREATE_YIN("DF_OCT3", + "<leaf name=\"port\">" + " <default value=\"0200\" />" + " <type name=\"int8\" />" + "</leaf>"); + UTEST_INVALID_MODULE(schema, LYS_IN_YIN, NULL, LY_EVALID); + CHECK_LOG_CTX("Invalid default - value does not fit the type (Value \"0200\" is out of type int8 min/max bounds.).", + "Schema location \"/DF_OCT3:port\"."); +} + +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", + " description \"desc\";\n" + "leaf port {type int8 {range \"0 .. 50 | 127\";} default \"20\";}"); + schema_yin = MODULE_CREATE_YIN("PRINT0", + "\n" + " <description>\n" + " <text>desc</text>\n" + " </description>\n" + " <leaf name=\"port\">\n" + " <type name=\"int8\">\n" + " <range value=\"0 .. 50 | 127\"/>\n" + " </type>\n" + " <default value=\"20\"/>\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" + " description\n" + " \"desc\";\n\n" + " leaf port {\n" + " type int8 {\n" + " range \"0 .. 50 | 127\";\n" + " }\n" + " default \"20\";\n" + " }\n"); + schema_yin = MODULE_CREATE_YIN("PRINT1", + "<description>" + " <text>desc</text>" + "</description>" + "<leaf name=\"port\">" + " <type name=\"int8\">" + " <range value=\"0 .. 50 | 127\"/>" + " </type>" + "<default value=\"20\"/>" + "</leaf>"); + + 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); + + /* test print yang to yin */ + schema_yang = MODULE_CREATE_YANG("PRINT2", + " description \"desc\";\n" + "leaf port {type int8;}"); + schema_yin = MODULE_CREATE_YIN("PRINT2", + "\n" + " <description>\n" + " <text>desc</text>\n" + " </description>\n" + " <leaf name=\"port\">\n" + " <type name=\"int8\"/>\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("PRINT3", + "\n" + " leaf port {\n" + " type int8;\n" + " }\n"); + schema_yin = MODULE_CREATE_YIN("PRINT3", + "<leaf name=\"port\">" + " <type name=\"int8\"/>" + "</leaf>"); + + 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; + /* variable for default value test */ + struct lysc_node_container *lysc_root; + struct lyd_node_inner *lyd_root; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type int8 {range \"0 .. 50 | 105\";}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML("defs", "+50", INT8, "50", 50); + TEST_SUCCESS_XML("defs", "50", INT8, "50", 50); + TEST_SUCCESS_XML("defs", "105", INT8, "105", 105); + TEST_SUCCESS_XML("defs", "0", INT8, "0", 0); + TEST_SUCCESS_XML("defs", "-0", INT8, "0", 0); + TEST_ERROR_XML("defs", "-1"); + CHECK_LOG_CTX("Unsatisfied range - value \"-1\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + TEST_ERROR_XML("defs", "51"); + CHECK_LOG_CTX("Unsatisfied range - value \"51\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + TEST_ERROR_XML("defs", "106"); + CHECK_LOG_CTX("Unsatisfied range - value \"106\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + TEST_ERROR_XML("defs", "104"); + CHECK_LOG_CTX("Unsatisfied range - value \"104\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + TEST_ERROR_XML("defs", "60"); + CHECK_LOG_CTX("Unsatisfied range - value \"60\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + + schema = MODULE_CREATE_YANG("T0", "leaf port {type int8; }"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_XML("T0", "-128", INT8, "-128", -128); + TEST_SUCCESS_XML("T0", "-100", INT8, "-100", -100); + TEST_SUCCESS_XML("T0", "0", INT8, "0", 0); + TEST_SUCCESS_XML("T0", "10", INT8, "10", 10); + TEST_SUCCESS_XML("T0", "50", INT8, "50", 50); + TEST_SUCCESS_XML("T0", "127", INT8, "127", 127); + /* leading zeros */ + TEST_SUCCESS_XML("T0", "-015", INT8, "-15", -15); + TEST_SUCCESS_XML("T0", "015", INT8, "15", 15); + TEST_ERROR_XML("T0", "-129"); + CHECK_LOG_CTX("Value \"-129\" is out of type int8 min/max bounds.", + "Schema location \"/T0:port\", line number 1."); + TEST_ERROR_XML("T0", "128"); + CHECK_LOG_CTX("Value \"128\" is out of type int8 min/max bounds.", + "Schema location \"/T0:port\", line number 1."); + TEST_ERROR_XML("T0", "256"); + CHECK_LOG_CTX("Value \"256\" is out of type int8 min/max bounds.", + "Schema location \"/T0:port\", line number 1."); + TEST_ERROR_XML("T0", "1024"); + CHECK_LOG_CTX("Value \"1024\" is out of type int8 min/max bounds.", + "Schema location \"/T0:port\", line number 1."); + + /* + * default value + */ + schema = MODULE_CREATE_YANG("T1", + "container cont {\n" + " leaf port {type int8 {range \"0 .. 50 | 105\";} default \"20\";}" + "}"); + /* check using default value */ + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + data = "<cont xmlns=\"urn:tests:" "T1" "\">" "</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, + INT8, "20", 20);\ + lyd_free_all(tree); + + /* check rewriting default value */ + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + data = "<cont xmlns=\"urn:tests:T1\">" "<port> 30 </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, + INT8, "30", 30); + lyd_free_all(tree); + + /* + * specific error + */ + schema = MODULE_CREATE_YANG("T2", "leaf port {type int8 {range \"0 .. 50 | 105\" {" + " error-app-tag \"range-violation\";" + " error-message \"invalid range of value\";" + "}}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_ERROR_XML("T2", "120"); + CHECK_LOG_CTX_APPTAG("invalid range of value", "Schema location \"/T2:port\", line number 1.", "range-violation"); +} + +static void +test_data_json(void **state) +{ + const char *schema; + /* value for default test */ + struct lysc_node_container *lysc_root; + struct lyd_node_inner *lyd_root; + const char *data; + struct lyd_node *tree; + + /* parsing json data */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type int8 {range \"0 .. 50 | 105\";}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_JSON("defs", "50", INT8, "50", 50); + TEST_SUCCESS_JSON("defs", "50", INT8, "50", 50); + TEST_SUCCESS_JSON("defs", "105", INT8, "105", 105); + TEST_SUCCESS_JSON("defs", "0", INT8, "0", 0); + TEST_SUCCESS_JSON("defs", "-0", INT8, "0", 0); + TEST_ERROR_JSON("defs", "-1"); + CHECK_LOG_CTX("Unsatisfied range - value \"-1\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + TEST_ERROR_JSON("defs", "51"); + CHECK_LOG_CTX("Unsatisfied range - value \"51\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + TEST_ERROR_JSON("defs", "106"); + CHECK_LOG_CTX("Unsatisfied range - value \"106\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + TEST_ERROR_JSON("defs", "104"); + CHECK_LOG_CTX("Unsatisfied range - value \"104\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + TEST_ERROR_JSON("defs", "60"); + CHECK_LOG_CTX("Unsatisfied range - value \"60\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + + schema = MODULE_CREATE_YANG("T0", "leaf port {type int8; }"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_JSON("T0", "-128", INT8, "-128", -128); + TEST_SUCCESS_JSON("T0", "-100", INT8, "-100", -100); + TEST_SUCCESS_JSON("T0", "0", INT8, "0", 0); + TEST_SUCCESS_JSON("T0", "10", INT8, "10", 10); + TEST_SUCCESS_JSON("T0", "50", INT8, "50", 50); + TEST_SUCCESS_JSON("T0", "127", INT8, "127", 127); + /* leading zeros */ + TEST_ERROR_JSON("T0", "015"); + TEST_ERROR_JSON("T0", "-015"); + TEST_ERROR_JSON("defs", "+50"); + TEST_ERROR_JSON("T0", "-129"); + CHECK_LOG_CTX("Value \"-129\" is out of type int8 min/max bounds.", + "Schema location \"/T0:port\", line number 1."); + TEST_ERROR_JSON("T0", "128"); + CHECK_LOG_CTX("Value \"128\" is out of type int8 min/max bounds.", + "Schema location \"/T0:port\", line number 1."); + TEST_ERROR_JSON("T0", "256"); + CHECK_LOG_CTX("Value \"256\" is out of type int8 min/max bounds.", + "Schema location \"/T0:port\", line number 1."); + TEST_ERROR_JSON("T0", "1024"); + CHECK_LOG_CTX("Value \"1024\" is out of type int8 min/max bounds.", + "Schema location \"/T0:port\", line number 1."); + + /* + * default value + */ + schema = MODULE_CREATE_YANG("T1", + "container cont {\n" + " leaf port {type int8 {range \"0 .. 50 | 105\";} default \"20\";}" + "}"); + /* check using default value */ + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + data = "{\"T1: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, + INT8, "20", 20);\ + lyd_free_all(tree); + + /* check rewriting default value */ + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + data = "{\"T1:cont\":{\":port\":30}}"; + 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, + INT8, "30", 30); + lyd_free_all(tree); + +} + +static void +test_data_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", "leaf port {type int8;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "port", "-128"); + TEST_SUCCESS_LYB("lyb", "port", "0"); + TEST_SUCCESS_LYB("lyb", "port", "1"); + TEST_SUCCESS_LYB("lyb", "port", "127"); +} + +static void +test_diff(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("defs", "leaf port {type int8 {range \"0 .. 50 | 120\";}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + struct lyd_node *model_1, *model_2; + struct lyd_node *diff; + const char *expected_string; + const char *data_1 = "<port xmlns=\"urn:tests:defs\"> 5 </port>"; + const char *data_2 = "<port xmlns=\"urn:tests:defs\"> 6 </port>"; + const char *diff_expected = "<port xmlns=\"urn:tests:defs\" " + "xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" " + "yang:operation=\"replace\" yang:orig-default=\"false\" yang:orig-value=\"5\">" + "6</port>"; + + LYD_TREE_CREATE(data_1, model_1); + LYD_TREE_CREATE(data_2, 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:defs\" " + "xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" " + "yang:operation=\"replace\" yang:orig-default=\"false\" yang:orig-value=\"5\">" + "120</port>"; + LYD_TREE_CREATE(diff_expected, diff); + data_1 = "<port xmlns=\"urn:tests:defs\"> 5 </port>"; + LYD_TREE_CREATE(data_1, model_1); + assert_int_equal(LY_SUCCESS, lyd_diff_apply_all(&model_1, diff)); + expected_string = "<port xmlns=\"urn:tests:defs\">120</port>"; + + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_XML, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + lyd_free_all(model_1); + lyd_free_all(diff); + + /* + * check creating data out of range + */ + diff_expected = "<port xmlns=\"urn:tests:defs\" " + "xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" " + "yang:operation=\"replace\" yang:orig-default=\"false\" yang:orig-value=\"5\">" + "121</port>"; + CHECK_PARSE_LYD_PARAM(diff_expected, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, model_1); + CHECK_LOG_CTX("Unsatisfied range - value \"121\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 1."); + + /* + * diff from default value + */ + data_1 = "<cont xmlns=\"urn:tests:T0\"></cont>"; + data_2 = "<cont xmlns=\"urn:tests:T0\"> <port> 6 </port> </cont>"; + diff_expected = "<cont xmlns=\"urn:tests:T0\"" + " xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\"" + " yang:operation=\"create\"><port>6</port></cont>"; + + schema = MODULE_CREATE_YANG("T0", + "container cont {\n" + " leaf port {type int8; default \"20\";}" + "}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + LYD_TREE_CREATE(data_1, model_1); + LYD_TREE_CREATE(data_2, 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) +{ + const char *schema = MODULE_CREATE_YANG("defs", "leaf port {type int8 {range \"0 .. 50\";}}"); + const char *expected_string; + + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + struct lyd_node *model_1; + const char *data_1 = "<port xmlns=\"urn:tests:defs\"> 50 </port>"; + + LYD_TREE_CREATE(data_1, model_1); + + /* XML */ + expected_string = "<port xmlns=\"urn:tests:defs\">50</port>"; + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + + /* JSON */ + expected_string = "{\"defs:port\":50}"; + CHECK_LYD_STRING_PARAM(model_1, expected_string, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK); + + lyd_free_all(model_1); +} + +static void +test_plugin_store(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_INT8]); + struct lysc_type *lysc_type; + LY_ERR ly_ret; + char *alloc; + const char *schema; + struct lysc_type lysc_type_test; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type int8 {range \"-50 .. 50\";}}"); + 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 - integers, version 1", type->id); + + /* check store + * options = LY_TYPE_STORE_IMPLEMENT | LY_TYPE_STORE_DYNAMIC + * hint = LYD_VALHINT_DECNUM, LYD_VALHINT_HEXNUM, LYD_VALHINT_OCTNUM + */ + 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_DECNUM, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, INT8, "20", 20); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + 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_DECNUM, NULL, &value, NULL, &err)); + CHECK_LYD_VALUE(value, INT8, "-20", -20); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "0xf"; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_HEXNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + CHECK_LYD_VALUE(value, INT8, "15", 15); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "1B"; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_HEXNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + CHECK_LYD_VALUE(value, INT8, "27", 27); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "-0xf"; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_HEXNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + CHECK_LYD_VALUE(value, INT8, "-15", -15); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "027"; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_OCTNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + CHECK_LYD_VALUE(value, INT8, "23", 23); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + val_text = "-027"; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_OCTNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + CHECK_LYD_VALUE(value, INT8, "-23", -23); + assert_ptr_equal(value.realtype, lysc_type); + type->free(UTEST_LYCTX, &value); + + /* + * minor tests + * dynamic alocated input text + */ + val_text = "0xa"; + alloc = (char *)malloc(strlen(val_text) + 1); + + memcpy(alloc, val_text, strlen(val_text) + 1); + ly_ret = type->store(UTEST_LYCTX, lysc_type, alloc, strlen(val_text), + LYPLG_TYPE_STORE_DYNAMIC, LY_VALUE_XML, NULL, LYD_VALHINT_HEXNUM, NULL, &value, NULL, &err); + alloc = NULL; + assert_int_equal(LY_SUCCESS, ly_ret); + CHECK_LYD_VALUE(value, INT8, "10", 10); + type->free(UTEST_LYCTX, &value); + + /* wrong lysc_type of value */ + 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_HEXNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_EINT, ly_ret); + + /* + * ERROR TESTS + */ + val_text = ""; + err = NULL; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_HEXNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_EVALID, ly_ret); + ly_err_free(err); + + val_text = ""; + err = NULL; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, 1, + 0, LY_VALUE_XML, NULL, LYD_VALHINT_HEXNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_EVALID, ly_ret); + ly_err_free(err); + + val_text = "10 b"; + err = NULL; + ly_ret = type->store(UTEST_LYCTX, lysc_type, val_text, strlen(val_text), + 0, LY_VALUE_XML, NULL, LYD_VALHINT_HEXNUM, NULL, &value, NULL, &err); + assert_int_equal(LY_EVALID, ly_ret); + ly_err_free(err); + + val_text = "a"; + 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_INT8]); + 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; + /* Value which are going to be created to tested */ + const char *val_init[] = {"20", "30", "-30", "0", "-0", "20"}; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("T0", "typedef my_int_type {type int8; }" + "leaf p1 {type my_int_type;}" + "leaf p2 {type my_int_type;}" + "leaf p3 {type my_int_type{range \"0 .. 50\";}}" + "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 */ + for (unsigned int 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_DECNUM, 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[5]))); + 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[3]), &(values[4]))); + + /* + * SAME TYPE but different node + */ + diff_type_text = "20"; + 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_DECNUM, 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)); + + /* + * derivated type add some limitations + */ + diff_type_text = "20"; + 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_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)); + + /* + * 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 (unsigned int 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_INT8]); + struct lysc_type *lysc_type; + LY_ERR ly_ret; + const char *schema; + /* Value which are going to be created to tested */ + const char *val_init[] = {"20", "0x4A", "-f", "0", "-0", "-20"}; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type int8;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, &mod); + lysc_type = ((struct lysc_node_leaf *)mod->compiled->data)->type; + + /* CREATE VALUES */ + for (unsigned int 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_HEXNUM, NULL, &(values[it]), NULL, &err); + assert_int_equal(LY_SUCCESS, ly_ret); + } + + /* print value */ + ly_bool dynamic = 0; + + assert_string_equal("32", type->print(UTEST_LYCTX, &(values[0]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("74", type->print(UTEST_LYCTX, &(values[1]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("-15", type->print(UTEST_LYCTX, &(values[2]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("0", type->print(UTEST_LYCTX, &(values[3]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("0", type->print(UTEST_LYCTX, &(values[4]), LY_VALUE_XML, NULL, &dynamic, NULL)); + assert_string_equal("-32", type->print(UTEST_LYCTX, &(values[5]), LY_VALUE_XML, NULL, &dynamic, NULL)); + + for (unsigned int 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_INT8]); + struct lysc_type *lysc_type[2]; + const char *schema; + LY_ERR ly_ret; + /* Value which are going to be tested */ + const char *val_init[] = {"20", "0x4A", "-f", "0", "-0x80", "-20"}; + + /* create schema. Prepare common used variables */ + schema = MODULE_CREATE_YANG("T0", "leaf port {type int8;}"); + 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 int8 {range \"-100 .. 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 */ + for (unsigned int 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_HEXNUM, 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, INT8, "32", 0x20); + 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, INT8, "74", 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, INT8, "-15", -0xf); + 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, INT8, "0", 0x0); + assert_ptr_equal(dup_value.realtype, values[3].realtype); + type->free(UTEST_LYCTX, &dup_value); + + assert_int_equal(LY_SUCCESS, type->duplicate(UTEST_LYCTX, &(values[4]), &dup_value)); + CHECK_LYD_VALUE(dup_value, INT8, "-128", -0x80); + assert_ptr_equal(dup_value.realtype, values[4].realtype); + type->free(UTEST_LYCTX, &dup_value); + + assert_int_equal(LY_SUCCESS, type->duplicate(UTEST_LYCTX, &(values[5]), &dup_value)); + CHECK_LYD_VALUE(dup_value, INT8, "-32", -0x20); + assert_ptr_equal(dup_value.realtype, values[5].realtype); + type->free(UTEST_LYCTX, &dup_value); + + /* error tests */ + assert_int_equal(LY_EINVAL, type->duplicate(NULL, &(values[0]), &dup_value)); + + for (unsigned int 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); +} diff --git a/tests/utests/types/leafref.c b/tests/utests/types/leafref.c new file mode 100644 index 0000000..c8d0cb6 --- /dev/null +++ b/tests/utests/types/leafref.c @@ -0,0 +1,222 @@ +/** + * @file leafref.c + * @author Adam Piecek <piecek@cesnet.cz> + * @brief test for built-in enumeration type + * + * 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" + +#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_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = XML1 "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 1, 0, 1, TYPE, __VA_ARGS__); \ + lyd_free_all(tree); \ + } + +#define TEST_ERROR_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, RET) \ + {\ + struct lyd_node *tree; \ + const char *data = XML1 "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, RET, tree); \ + assert_null(tree); \ + } + +#define TEST_SUCCESS_LYB(MOD_NAME, NODE_NAME1, DATA1, NODE_NAME2, DATA2) \ + { \ + struct lyd_node *tree_1; \ + struct lyd_node *tree_2; \ + char *xml_out, *data; \ + data = "<" NODE_NAME1 " xmlns=\"urn:tests:" MOD_NAME "\"><name>" DATA1 "</name></" NODE_NAME1 ">" \ + "<" NODE_NAME2 " xmlns=\"urn:tests:" MOD_NAME "\">" DATA2 "</" NODE_NAME2 ">"; \ + 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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema, *schema2, *schema3, *data; + struct lyd_node *tree; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "leaf lref {type leafref {path /leaflisttarget; require-instance true;}}" + "leaf lref2 {type leafref {path \"../list[id = current()/../str-norestr]/targets\"; require-instance true;}}" + "leaf str-norestr {type string;}" + "list list {key id; leaf id {type string;} leaf value {type string;} leaf-list targets {type string;}}" + "container cont {leaf leaftarget {type empty;}" + " list listtarget {key id; max-elements 5;leaf id {type uint8;} leaf value {type string;}}" + " leaf-list leaflisttarget {type uint8; max-elements 5;}}" + "leaf-list leaflisttarget {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + schema2 = MODULE_CREATE_YANG("leafrefs", "import defs {prefix t;}" + "container c { container x {leaf x {type string;}} list l {" + " key \"id value\"; leaf id {type string;} leaf value {type string;}" + " leaf lr1 {type leafref {path \"../../../t:str-norestr\"; require-instance true;}}" + " leaf lr2 {type leafref {path \"../../l[id=current()/../../../t:str-norestr]\" +" + " \"[value=current()/../../../t:str-norestr]/value\"; require-instance true;}}" + " leaf lr3 {type leafref {path \"/t:list[t:id=current ( )/../../x/x]/t:targets\";}}" + "}}"); + UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML2("<leaflisttarget xmlns=\"urn:tests:defs\">x</leaflisttarget>" + "<leaflisttarget xmlns=\"urn:tests:defs\">y</leaflisttarget>", + "defs", "xmlns:a=\"urn:tests:defs\"", "a:lref", "y", STRING, "y"); + + TEST_SUCCESS_XML2("<list xmlns=\"urn:tests:defs\"><id>x</id><targets>a</targets><targets>b</targets></list>" + "<list xmlns=\"urn:tests:defs\"><id>y</id><targets>x</targets><targets>y</targets></list>" + "<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>", + "defs", "xmlns:a=\"urn:tests:defs\"", "a:lref2", "y", STRING, "y"); + + data = "<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>" + "<c xmlns=\"urn:tests:leafrefs\"><l><id>x</id><value>x</value><lr1>y</lr1></l></c>"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + CHECK_LYD_NODE_TERM((struct lyd_node_term *)lyd_child(lyd_child(tree->next->next)->next)->next->next, + 0, 0, 0, 1, 1, STRING, "y"); + lyd_free_all(tree); + + data = "<list xmlns=\"urn:tests:defs\"><id>x</id><targets>a</targets><targets>b</targets></list>" + "<list xmlns=\"urn:tests:defs\"><id>y</id><targets>c</targets><targets>d</targets></list>" + "<c xmlns=\"urn:tests:leafrefs\"><x><x>y</x></x>" + "<l><id>x</id><value>x</value><lr3>c</lr3></l></c>"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + CHECK_LYD_NODE_TERM((struct lyd_node_term *)lyd_child(lyd_child(tree->next->next->next)->next)->next->next, + 0, 0, 0, 1, 1, STRING, "c"); + lyd_free_all(tree); + + schema3 = MODULE_CREATE_YANG("simple", "leaf l1 {type leafref {path \"../target\";}}" + "leaf target {type string;}"); + UTEST_ADD_MODULE(schema3, LYS_IN_YANG, NULL, NULL); + + data = "<l1 xmlns=\"urn:tests:simple\">"*"'</l1>" + "<target xmlns=\"urn:tests:simple\">"*"'</target>"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lyd_free_all(tree); + + data = "<l1 xmlns=\"urn:tests:simple\">"*'"</l1>" + "<target xmlns=\"urn:tests:simple\">"*'"</target>"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lyd_free_all(tree); + + /* invalid value */ + TEST_ERROR_XML2("<leaflisttarget xmlns=\"urn:tests:defs\">x</leaflisttarget>", + "defs", "", "lref", "y", LY_EVALID); + CHECK_LOG_CTX_APPTAG("Invalid leafref value \"y\" - no target instance \"/leaflisttarget\" with the same value.", + "Data location \"/defs:lref\".", "instance-required"); + + TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>x</id><targets>a</targets><targets>b</targets></list>" + "<list xmlns=\"urn:tests:defs\"><id>y</id><targets>x</targets><targets>y</targets></list>" + "<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>", + "defs", "", "lref2", "b", LY_EVALID); + CHECK_LOG_CTX_APPTAG("Invalid leafref value \"b\" - " + "no target instance \"../list[id = current()/../str-norestr]/targets\" with the same value.", + "Data location \"/defs:lref2\".", "instance-required"); + + TEST_ERROR_XML2("<list xmlns=\"urn:tests:defs\"><id>x</id><targets>a</targets><targets>b</targets></list>" + "<list xmlns=\"urn:tests:defs\"><id>y</id><targets>x</targets><targets>y</targets></list>", + "defs", "", "lref2", "b", LY_EVALID); + CHECK_LOG_CTX_APPTAG("Invalid leafref value \"b\" - " + "no target instance \"../list[id = current()/../str-norestr]/targets\" with the same value.", + "Data location \"/defs:lref2\".", "instance-required"); + + TEST_ERROR_XML2("<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>", + "defs", "", "lref2", "b", LY_EVALID); + CHECK_LOG_CTX_APPTAG("Invalid leafref value \"b\" - " + "no target instance \"../list[id = current()/../str-norestr]/targets\" with the same value.", + "Data location \"/defs:lref2\".", "instance-required"); + + TEST_ERROR_XML2("<str-norestr xmlns=\"urn:tests:defs\">y</str-norestr>", + "leafrefs", "", "c", "<l><id>x</id><value>x</value><lr1>a</lr1></l>", LY_EVALID); + CHECK_LOG_CTX_APPTAG("Invalid leafref value \"a\" - no target instance \"../../../t:str-norestr\" with the same value.", + "Data location \"/leafrefs:c/l[id='x'][value='x']/lr1\".", "instance-required"); + + TEST_ERROR_XML2("<str-norestr xmlns=\"urn:tests:defs\">z</str-norestr>", + "leafrefs", "", "c", "<l><id>y</id><value>y</value></l><l><id>x</id><value>x</value><lr2>z</lr2></l>", LY_EVALID); + CHECK_LOG_CTX_APPTAG("Invalid leafref value \"z\" - no target instance \"../../l[id=current()/../../../t:str-norestr]" + "[value=current()/../../../t:str-norestr]/value\" with the same value.", + "Data location \"/leafrefs:c/l[id='x'][value='x']/lr2\".", "instance-required"); + + TEST_ERROR_XML2("", + "defs", "", "lref", "%n", LY_EVALID); + CHECK_LOG_CTX_APPTAG("Invalid leafref value \"%n\" - no target instance \"/leaflisttarget\" with the same value.", + "Data location \"/defs:lref\".", "instance-required"); +} + +static void +test_data_json(void **state) +{ + const char *schema, *data; + struct lyd_node *tree; + + /* json test */ + schema = MODULE_CREATE_YANG("simple", "leaf l1 {type leafref {path \"../target\";}}" + "leaf target {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + data = "{" + " \"simple:l1\":\"\\\"*\\\"'\"," + " \"simple:target\":\"\\\"*\\\"'\"" + "}"; + CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lyd_free_all(tree); + + data = "{" + " \"simple:l1\":\"\\\"*'\\\"\"," + " \"simple:target\":\"\\\"*'\\\"\"" + "}"; + CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + lyd_free_all(tree); +} + +static void +test_plugin_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", + "list lst {key \"name\"; leaf name {type string;}}" + "leaf lref {type leafref {path \"../lst/name\";}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "lst", "key_str", "lref", "key_str"); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + UTEST(test_data_json), + UTEST(test_plugin_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} 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); +} diff --git a/tests/utests/types/uint16.c b/tests/utests/types/uint16.c new file mode 100644 index 0000000..7cbb014 --- /dev/null +++ b/tests/utests/types/uint16.c @@ -0,0 +1,75 @@ +/** + * @file uint16.c + * @author Michal Vasko <mvasko@cesnet.cz> + * @brief test for uint16 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 + */ + +/* INCLUDE UTEST HEADER */ +#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_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_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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type uint16 {range 150..200;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_ERROR_XML("defs", "\n 1500 \t\n "); + CHECK_LOG_CTX("Unsatisfied range - value \"1500\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 3."); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/uint32.c b/tests/utests/types/uint32.c new file mode 100644 index 0000000..e3e6377 --- /dev/null +++ b/tests/utests/types/uint32.c @@ -0,0 +1,75 @@ +/** + * @file uint32.c + * @author Michal Vasko <mvasko@cesnet.cz> + * @brief test for uint32 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 + */ + +/* INCLUDE UTEST HEADER */ +#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_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_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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type uint32;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_ERROR_XML("defs", "-10"); + CHECK_LOG_CTX("Value \"-10\" is out of type uint32 min/max bounds.", + "Schema location \"/defs:port\", line number 1."); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/uint64.c b/tests/utests/types/uint64.c new file mode 100644 index 0000000..401c37c --- /dev/null +++ b/tests/utests/types/uint64.c @@ -0,0 +1,83 @@ +/** + * @file uint64.c + * @author Michal Vasko <mvasko@cesnet.cz> + * @brief test for uint64 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 + */ + +/* INCLUDE UTEST HEADER */ +#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_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_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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type uint64;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_ERROR_XML("defs", ""); + CHECK_LOG_CTX("Invalid type uint64 empty value.", + "Schema location \"/defs:port\", line number 1."); + + TEST_ERROR_XML("defs", " "); + CHECK_LOG_CTX("Invalid type uint64 empty value.", + "Schema location \"/defs:port\", line number 1."); + + TEST_ERROR_XML("defs", "10 xxx"); + CHECK_LOG_CTX("Invalid type uint64 value \"10 xxx\".", + "Schema location \"/defs:port\", line number 1."); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/uint8.c b/tests/utests/types/uint8.c new file mode 100644 index 0000000..dad4039 --- /dev/null +++ b/tests/utests/types/uint8.c @@ -0,0 +1,77 @@ +/** + * @file uint8.c + * @author Michal Vasko <mvasko@cesnet.cz> + * @brief test for uint8 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 + */ + +/* INCLUDE UTEST HEADER */ +#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_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_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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "leaf port {type uint8 {range 150..200;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML("defs", "\n 150 \t\n ", UINT8, "150", 150); + + TEST_ERROR_XML("defs", "\n 15 \t\n "); + CHECK_LOG_CTX("Unsatisfied range - value \"15\" is out of the allowed range.", + "Schema location \"/defs:port\", line number 3."); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/union.c b/tests/utests/types/union.c new file mode 100644 index 0000000..9a0705a --- /dev/null +++ b/tests/utests/types/union.c @@ -0,0 +1,136 @@ +/** + * @file union.c + * @author Adam Piecek <piecek@cesnet.cz> + * @brief test for built-in enumeration type + * + * 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +/* LOCAL INCLUDE HEADERS */ +#include "libyang.h" +#include "path.h" + +#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_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = XML1 "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 1, 0, 1, TYPE, __VA_ARGS__); \ + lyd_free_all(tree); \ + } + +#define TEST_ERROR_XML2(XML1, MOD_NAME, NAMESPACES, NODE_NAME, DATA, RET) \ + {\ + struct lyd_node *tree; \ + const char *data = XML1 "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\" " NAMESPACES ">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, RET, tree); \ + assert_null(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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + const enum ly_path_pred_type val1[] = {LY_PATH_PREDTYPE_LEAFLIST}; + + /* xml test */ + schema = MODULE_CREATE_YANG("defs", "identity ident1; identity ident2 {base ident1;}" + "leaf un1 {type union {" + " type leafref {path /int8; require-instance true;}" + " type leafref {path /int64; require-instance true;}" + " type union { type identityref {base ident1;} type instance-identifier {require-instance true;} }" + " type string {length 1..20;}}}" + "leaf int8 {type int8 {range 10..20;}}" + "leaf int64 {type int64;}" + "leaf-list llist {type string;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + TEST_SUCCESS_XML2("<int8 xmlns=\"urn:tests:defs\">12</int8>", + "defs", "", "un1", "12", UNION, "12", INT8, "12", 12); + + TEST_SUCCESS_XML2("<int8 xmlns=\"urn:tests:defs\">12</int8>", + "defs", "", "un1", "2", UNION, "2", STRING, "2"); + + TEST_SUCCESS_XML2("<int8 xmlns=\"urn:tests:defs\">10</int8>", + "defs", "xmlns:x=\"urn:tests:defs\"", "un1", "x:ident2", UNION, "defs:ident2", IDENT, "defs:ident2", "ident2"); + + TEST_SUCCESS_XML2("<int8 xmlns=\"urn:tests:defs\">10</int8>", + "defs", "xmlns:x=\"urn:tests:defs\"", "un1", "x:ident55", UNION, "x:ident55", STRING, "x:ident55"); + + TEST_SUCCESS_XML2("<llist xmlns=\"urn:tests:defs\">x</llist>" + "<llist xmlns=\"urn:tests:defs\">y</llist>", + "defs", "xmlns:x=\"urn:tests:defs\"", "un1", "/x:llist[.='y']", UNION, "/defs:llist[.='y']", + INST, "/defs:llist[.='y']", val1); + + TEST_SUCCESS_XML2("<llist xmlns=\"urn:tests:defs\">x</llist>" + "<llist xmlns=\"urn:tests:defs\">y</llist>", + "defs", "xmlns:x=\"urn:tests:defs\"", "un1", "/x:llist[3]", UNION, "/x:llist[3]", + STRING, "/x:llist[3]"); + + /* invalid value */ + TEST_ERROR_XML2("", + "defs", "", "un1", "123456789012345678901", LY_EVALID); + CHECK_LOG_CTX("Invalid union value \"123456789012345678901\" - no matching subtype found.", + "Schema location \"/defs:un1\", line number 1."); +} + +static void +test_plugin_lyb(void **state) +{ + const char *schema; + + schema = MODULE_CREATE_YANG("lyb", + "leaf int8 {type int8 {range 10..20;}}" + "leaf un1 {type union {" + " type leafref {path /int8; require-instance true;}" + " type string;}}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + TEST_SUCCESS_LYB("lyb", "un1", "12"); + TEST_SUCCESS_LYB("lyb", "un1", "some_string"); + TEST_SUCCESS_LYB("lyb", "un1", ""); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + UTEST(test_plugin_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/tests/utests/types/yang_types.c b/tests/utests/types/yang_types.c new file mode 100644 index 0000000..6ce7671 --- /dev/null +++ b/tests/utests/types/yang_types.c @@ -0,0 +1,223 @@ +/** + * @file yang_types.c + * @author Michal Vaško <mvasko@cesnet.cz> + * @brief test for ietf-yang-types 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 + */ + +/* INCLUDE UTEST HEADER */ +#define _UTEST_MAIN_ +#include "../utests.h" + +#include <stdlib.h> + +#include "compat.h" +#include "libyang.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" \ + " import ietf-yang-types {\n" \ + " prefix yang;\n" \ + " }\n" \ + NODES \ + "}\n" + +#define TEST_SUCCESS_XML(MOD_NAME, NODE_NAME, DATA, TYPE, ...) \ + { \ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); \ + CHECK_LYD_NODE_TERM((struct lyd_node_term *)tree, 0, 0, 0, 0, 1, TYPE, __VA_ARGS__); \ + lyd_free_all(tree); \ + } + +#define TEST_ERROR_XML(MOD_NAME, NODE_NAME, DATA) \ + {\ + struct lyd_node *tree; \ + const char *data = "<" NODE_NAME " xmlns=\"urn:tests:" MOD_NAME "\">" DATA "</" NODE_NAME ">"; \ + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree); \ + assert_null(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); \ + } + +static void +test_data_xml(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("a", + "leaf l {type yang:date-and-time;}" + "leaf l2 {type yang:xpath1.0;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + schema = MODULE_CREATE_YANG("b", + ""); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + /* date-and-time */ +#if defined (HAVE_TM_GMTOFF) && defined (HAVE_TIME_H_TIMEZONE) + TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888Z", STRING, "2005-05-25T21:15:15.88888-02:00"); + TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-08:59", STRING, "2005-06-01T06:14:15-02:00"); + TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-23:00", STRING, "2005-06-01T20:15:15-02:00"); + + /* test 1 second before epoch (mktime returns -1, but it is a correct value), with and without DST */ + TEST_SUCCESS_XML("a", "l", "1970-01-01T00:59:59-02:00", STRING, "1970-01-01T00:59:59-02:00"); + TEST_SUCCESS_XML("a", "l", "1969-12-31T23:59:59-02:00", STRING, "1969-12-31T23:59:59-02:00"); + + /* canonize */ + TEST_SUCCESS_XML("a", "l", "2005-02-29T23:15:15-02:00", STRING, "2005-03-01T23:15:15-02:00"); + + /* fractional hours */ + TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888+04:30", STRING, "2005-05-25T16:45:15.88888-02:00"); +#else + /* Tests run with a TZ offset of +02:00, but this platform cannot represent that in time_t, + * so libyang always returns unspecified TZ. */ + TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888Z", STRING, "2005-05-25T23:15:15.88888-00:00"); + TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-08:59", STRING, "2005-06-01T08:14:15-00:00"); + TEST_SUCCESS_XML("a", "l", "2005-05-31T23:15:15-23:00", STRING, "2005-06-01T22:15:15-00:00"); + + /* test 1 second before epoch (mktime returns -1, but it is a correct value), with and without DST */ + TEST_SUCCESS_XML("a", "l", "1970-01-01T00:59:59-02:00", STRING, "1970-01-01T02:59:59-00:00"); + TEST_SUCCESS_XML("a", "l", "1969-12-31T23:59:59-02:00", STRING, "1970-01-01T01:59:59-00:00"); + + /* canonize */ + TEST_SUCCESS_XML("a", "l", "2005-02-29T23:15:15-02:00", STRING, "2005-03-02T01:15:15-00:00"); + + /* fractional hours */ + TEST_SUCCESS_XML("a", "l", "2005-05-25T23:15:15.88888+04:30", STRING, "2005-05-25T18:45:15.88888-00:00"); +#endif + + /* unknown timezone -- timezone conversion MUST NOT happen */ + TEST_SUCCESS_XML("a", "l", "2017-02-01T00:00:00-00:00", STRING, "2017-02-01T00:00:00-00:00"); + TEST_SUCCESS_XML("a", "l", "2021-02-29T00:00:00-00:00", STRING, "2021-03-01T00:00:00-00:00"); + + TEST_ERROR_XML("a", "l", "2005-05-31T23:15:15.-08:00"); + CHECK_LOG_CTX("Unsatisfied pattern - \"2005-05-31T23:15:15.-08:00\" does not conform to " + "\"\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[\\+\\-]\\d{2}:\\d{2})\".", + "Schema location \"/a:l\", line number 1."); + + /* xpath1.0 */ + TEST_SUCCESS_XML("a\" xmlns:aa=\"urn:tests:a", "l2", "/aa:l2[. = '4']", STRING, "/a:l2[.='4']"); + TEST_SUCCESS_XML("a\" xmlns:yl=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\" " + "xmlns:ds=\"urn:ietf:params:xml:ns:yang:ietf-datastores", "l2", + "/yl:yang-library/yl:datastore/yl:name = 'ds:running'", STRING, + "/ietf-yang-library:yang-library/datastore/name='ietf-datastores:running'"); + TEST_SUCCESS_XML("a\" xmlns:a1=\"urn:tests:a\" xmlns:a2=\"urn:tests:a\" xmlns:bb=\"urn:tests:b", "l2", + "/a1:node1/a2:node2[a1:node3/bb:node4]/bb:node5 | bb:node6 and (bb:node7)", STRING, + "/a:node1/node2[node3/b:node4]/b:node5 | b:node6 and (b:node7)"); + TEST_SUCCESS_XML("a", "l2", "/l2[. = '4']", STRING, "/l2[.='4']"); + + TEST_ERROR_XML("a", "l2", "/a:l2[. = '4']"); + CHECK_LOG_CTX("Failed to resolve prefix \"a\".", "Schema location \"/a:l2\", line number 1."); + TEST_ERROR_XML("a\" xmlns:yl=\"urn:ietf:params:xml:ns:yang:ietf-yang-library", "l2", + "/yl:yang-library/yl:datastore/yl::name"); + CHECK_LOG_CTX("Storing value failed.", "Schema location \"/a:l2\", line number 1.", + "Invalid character 'y'[31] of expression '/yl:yang-library/yl:datastore/yl::name'.", + "Schema location \"/a:l2\", line number 1."); +} + +static void +test_print(void **state) +{ + const char *schema = MODULE_CREATE_YANG("a", "leaf l {type yang:xpath1.0;}"); + const char *data, *expected; + struct lyd_node *tree; + + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + /* XML data */ + data = "<l xmlns=\"urn:tests:a\" xmlns:aa=\"urn:tests:a\">/aa:l[. = '/aa:l']</l>"; + CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + + /* XML print */ + expected = "<l xmlns=\"urn:tests:a\" xmlns:pref=\"urn:tests:a\">/pref:l[.='/pref:l']</l>"; + CHECK_LYD_STRING_PARAM(tree, expected, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS); + + /* JSON print */ + expected = "{\"a:l\":\"/a:l[.='/a:l']\"}"; + CHECK_LYD_STRING_PARAM(tree, expected, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS); + + lyd_free_tree(tree); + + /* JSON data */ + data = "{\"a:l\":\"/a:l/k/m[. = '/a:l']\"}"; + CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree); + + /* XML print */ + expected = "<l xmlns=\"urn:tests:a\" xmlns:pref=\"urn:tests:a\">/pref:l/pref:k/pref:m[.='/pref:l']</l>"; + CHECK_LYD_STRING_PARAM(tree, expected, LYD_XML, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS); + + /* JSON print */ + expected = "{\"a:l\":\"/a:l/k/m[. = '/a:l']\"}"; + CHECK_LYD_STRING_PARAM(tree, expected, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS); + + lyd_free_tree(tree); +} + +static void +test_lyb(void **state) +{ + const char *schema; + + /* xml test */ + schema = MODULE_CREATE_YANG("a", + "leaf l {type yang:date-and-time;}" + "leaf l2 {type yang:xpath1.0;}"); + UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL); + + /* date-and-time */ + TEST_SUCCESS_LYB("a", "l", "2005-05-25T23:15:15.88888Z"); + TEST_SUCCESS_LYB("a", "l", "2005-05-31T23:15:15-08:59"); + TEST_SUCCESS_LYB("a", "l", "2005-05-01T20:15:15-00:00"); + + /* xpath1.0 */ + TEST_SUCCESS_LYB("a\" xmlns:aa=\"urn:tests:a", "l2", "/aa:l2[. = '4']"); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_data_xml), + UTEST(test_print), + UTEST(test_lyb), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} |