From cd07912073c951b4bbb871ed2653af1be2cfc714 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 11:55:11 +0200 Subject: Adding upstream version 2.1.30. Signed-off-by: Daniel Baumann --- tests/utests/extensions/test_schema_mount.c | 1566 +++++++++++++++++++++++++++ 1 file changed, 1566 insertions(+) create mode 100644 tests/utests/extensions/test_schema_mount.c (limited to 'tests/utests/extensions/test_schema_mount.c') diff --git a/tests/utests/extensions/test_schema_mount.c b/tests/utests/extensions/test_schema_mount.c new file mode 100644 index 0000000..be879ec --- /dev/null +++ b/tests/utests/extensions/test_schema_mount.c @@ -0,0 +1,1566 @@ +/** + * @file test_schema_mount.c + * @author Tadeas Vintrlik + * @author Michal Vasko + * @brief unit tests for Schema Mount extension support + * + * Copyright (c) 2021 - 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 + */ + +#define _UTEST_MAIN_ +#include "utests.h" + +#include "libyang.h" + +void **glob_state; + +static int +setup(void **state) +{ + const char *schema = + "module sm {yang-version 1.1;namespace \"urn:sm\";prefix \"sm\";" + "import ietf-yang-schema-mount {prefix yangmnt;}" + "import ietf-interfaces {prefix if;}" + "container root {yangmnt:mount-point \"root\";}" + "container root2 {yangmnt:mount-point \"root\";}" + "container root3 {" + " list ls { key name; leaf name {type string;}" + " yangmnt:mount-point \"mnt-root\";" + " }" + "}" + "container root4 {config false; yangmnt:mount-point \"root\";}" + "leaf target{type string;}" + "augment /if:interfaces/if:interface {" + " leaf sm-name {type leafref {path \"/sm:target\";}}" + "}" + "}"; + + UTEST_SETUP; + glob_state = state; + + assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG)); + assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL)); + assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "iana-if-type", NULL, NULL)); + + return 0; +} + +static void +test_schema(void **state) +{ + struct lys_module *mod; + const char *schema; + char *str; + + /* invalid */ + schema = + "module sm {\n" + " namespace \"urn:sm\";\n" + " prefix sm;\n" + "\n" + " import ietf-yang-schema-mount {\n" + " prefix yangmnt;\n" + " }\n" + "\n" + " container root {\n" + " yangmnt:mount-point \"root\";\n" + " }\n" + "}\n"; + assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL)); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Extension \"yangmnt:mount-point\" instance not allowed in YANG version 1 module.", + "/sm:root/{extension='yangmnt:mount-point'}/root"); + + schema = + "module sm {\n" + " yang-version 1.1;\n" + " namespace \"urn:sm\";\n" + " prefix sm;\n" + "\n" + " import ietf-yang-schema-mount {\n" + " prefix yangmnt;\n" + " }\n" + "\n" + " yangmnt:mount-point \"root\";\n" + "}\n"; + assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL)); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Extension \"yangmnt:mount-point\" instance allowed only in container or list statement.", + "/sm:{extension='yangmnt:mount-point'}/root"); + + schema = + "module sm {\n" + " yang-version 1.1;\n" + " namespace \"urn:sm\";\n" + " prefix sm;\n" + "\n" + " import ietf-yang-schema-mount {\n" + " prefix yangmnt;\n" + " }\n" + "\n" + " container root {\n" + " leaf l {\n" + " type empty;\n" + " yangmnt:mount-point \"root\";\n" + " }\n" + " }\n" + "}\n"; + assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL)); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Extension \"yangmnt:mount-point\" instance allowed only in container or list statement.", + "/sm:root/l/{extension='yangmnt:mount-point'}/root"); + + schema = + "module sm {\n" + " yang-version 1.1;\n" + " namespace \"urn:sm\";\n" + " prefix sm;\n" + "\n" + " import ietf-yang-schema-mount {\n" + " prefix yangmnt;\n" + " }\n" + "\n" + " list l {\n" + " key \"k\";\n" + " leaf k {\n" + " type string;\n" + " }\n" + " yangmnt:mount-point \"root\";\n" + " yangmnt:mount-point \"root2\";\n" + " }\n" + "}\n"; + assert_int_equal(LY_EINVAL, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, NULL)); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Multiple extension \"yangmnt:mount-point\" instances.", + "/sm:l/{extension='yangmnt:mount-point'}/root"); + + /* valid */ + schema = + "module sm {\n" + " yang-version 1.1;\n" + " namespace \"urn:sm\";\n" + " prefix sm;\n" + "\n" + " import ietf-yang-schema-mount {\n" + " prefix yangmnt;\n" + " }\n" + "\n" + " container root {\n" + " yangmnt:mount-point \"root\";\n" + " }\n" + "}\n"; + assert_int_equal(LY_SUCCESS, lys_parse_mem(UTEST_LYCTX, schema, LYS_IN_YANG, &mod)); + lys_print_mem(&str, mod, LYS_OUT_YANG, 0); + assert_string_equal(str, schema); + free(str); +} + +static LY_ERR +test_ext_data_clb(const struct lysc_ext_instance *ext, void *user_data, void **ext_data, ly_bool *ext_data_free) +{ + void **state = glob_state; + struct lyd_node *data = NULL; + + (void)ext; + + if (user_data) { + CHECK_PARSE_LYD_PARAM(user_data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + } + + *ext_data = data; + *ext_data_free = 1; + return LY_SUCCESS; +} + +static void +test_parse_invalid(void **state) +{ + const char *xml, *json; + struct lyd_node *data; + + /* no callback set */ + xml = + "" + " " + " " + " bu" + " ii:ethernetCsmacd" + " " + " " + ""; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EINVAL, data); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": Failed to get extension data, no callback set.", + NULL); + + json = + "{" + " \"sm:root\": {" + " \"unknown:unknown\": {" + " \"interface\": [" + " {" + " \"name\": \"bu\"," + " \"type\": \"iana-if-type:ethernetCsmacd\"" + " }" + " ]" + " }" + " }" + "}"; + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_EINVAL, data); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": Failed to get extension data, no callback set.", + NULL); + + /* unknown data */ + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, NULL); + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + assert_string_equal(LYD_NAME(data), "root"); + assert_null(lyd_child(data)); + assert_non_null(data->next); + assert_true(data->next->flags & LYD_DEFAULT); + lyd_free_siblings(data); + + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("No module with namespace \"unknown\" in the context.", + "Data location \"/sm:root\", line number 1."); + + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + assert_string_equal(LYD_NAME(data), "root"); + assert_null(lyd_child(data)); + assert_non_null(data->next); + assert_true(data->next->flags & LYD_DEFAULT); + lyd_free_siblings(data); + + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("No module named \"unknown\" in the context.", + "Data location \"/sm:root\", line number 1."); + + /* missing required callback data */ + xml = + "" + " " + " " + " bu" + " " + " " + ""; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Node \"interfaces\" not found as a child of \"root\" node.", + "Data location \"/sm:root\", line number 1."); + + json = + "{" + " \"sm:root\": {" + " \"ietf-interfaces:interfaces\": {" + " \"interface\": [" + " {" + " \"name\": \"bu\"" + " }" + " ]" + " }" + " }" + "}"; + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Node \"interfaces\" not found as a child of \"root\" node.", + "Data location \"/sm:root\", line number 1."); + + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + ""); + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Node \"interfaces\" not found as a child of \"root\" node.", + "Data location \"/sm:root\", line number 1."); + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Node \"interfaces\" not found as a child of \"root\" node.", + "Data location \"/sm:root\", line number 1."); + + /* missing module in yang-library data */ + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + "" + "" + " " + " sm" + " " + " " + " " + ""); + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Node \"interfaces\" not found as a child of \"root\" node.", + "Data location \"/sm:root\", line number 1."); + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Node \"interfaces\" not found as a child of \"root\" node.", + "Data location \"/sm:root\", line number 1."); + + /* callback data correct, invalid YANG data */ + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-datastores" + " 2018-02-14" + " urn:ietf:params:xml:ns:yang:ietf-datastores" + " " + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " ietf-yang-schema-mount" + " 2019-01-14" + " urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount" + " " + " " + " ietf-interfaces" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " iana-if-type" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:iana-if-type" + " " + " " + " ietf-yang-types" + " 2013-07-15" + " urn:ietf:params:xml:ns:yang:ietf-yang-types" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + "" + "" + " " + " sm" + " " + " " + " " + ""); + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Mandatory node \"type\" instance does not exist.", + "Schema location \"/ietf-interfaces:interfaces/interface/type\"."); + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Mandatory node \"type\" instance does not exist.", + "Schema location \"/ietf-interfaces:interfaces/interface/type\"."); + + /* same validation fail in separate validation */ + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT | LYD_PARSE_ONLY, 0, LY_SUCCESS, data); + assert_int_equal(LY_EVALID, lyd_validate_all(&data, NULL, LYD_VALIDATE_PRESENT, NULL)); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Mandatory node \"type\" instance does not exist.", + "Schema location \"/ietf-interfaces:interfaces/interface/type\"."); + lyd_free_siblings(data); + + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT | LYD_PARSE_ONLY, 0, LY_SUCCESS, data); + assert_int_equal(LY_EVALID, lyd_validate_all(&data, NULL, LYD_VALIDATE_PRESENT, NULL)); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Mandatory node \"type\" instance does not exist.", + "Schema location \"/ietf-interfaces:interfaces/interface/type\"."); + lyd_free_siblings(data); + + /* success */ + xml = + "\n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " \n" + " \n" + "\n"; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, xml, LYD_XML, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(data); + + json = + "{\n" + " \"sm:root\": {\n" + " \"ietf-interfaces:interfaces\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"bu\",\n" + " \"type\": \"iana-if-type:ethernetCsmacd\"\n" + " }\n" + " ]\n" + " }\n" + " }\n" + "}\n"; + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, json, LYD_JSON, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(data); +} + +static void +test_parse_inline(void **state) +{ + const char *xml, *json; + char *lyb; + struct lyd_node *data; + const struct ly_ctx *ext_ctx; + + /* valid */ + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-datastores" + " 2018-02-14" + " urn:ietf:params:xml:ns:yang:ietf-datastores" + " " + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " ietf-yang-schema-mount" + " 2019-01-14" + " urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount" + " " + " " + " ietf-interfaces" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " iana-if-type" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:iana-if-type" + " " + " " + " ietf-yang-types" + " 2013-07-15" + " urn:ietf:params:xml:ns:yang:ietf-yang-types" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + "" + "" + " " + " sm" + " " + " " + " " + ""); + xml = + "\n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " \n" + " \n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " not-present\n" + " \n" + " 2022-01-01T10:00:00-00:00\n" + " \n" + " \n" + " \n" + "\n"; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, xml, LYD_XML, LYD_PRINT_WITHSIBLINGS); + ext_ctx = LYD_CTX(lyd_child(data)); + lyd_free_siblings(data); + + json = + "{\n" + " \"sm:root\": {\n" + " \"ietf-interfaces:interfaces\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"bu\",\n" + " \"type\": \"iana-if-type:ethernetCsmacd\"\n" + " }\n" + " ]\n" + " },\n" + " \"ietf-interfaces:interfaces-state\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"bu\",\n" + " \"type\": \"iana-if-type:ethernetCsmacd\",\n" + " \"oper-status\": \"not-present\",\n" + " \"statistics\": {\n" + " \"discontinuity-time\": \"2022-01-01T10:00:00-00:00\"\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " }\n" + "}\n"; + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, json, LYD_JSON, LYD_PRINT_WITHSIBLINGS); + assert_ptr_equal(ext_ctx, LYD_CTX(lyd_child(data))); + lyd_free_siblings(data); + + /* different yang-lib data with the same content-id */ + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-datastores" + " 2018-02-14" + " urn:ietf:params:xml:ns:yang:ietf-datastores" + " " + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " ietf-yang-schema-mount" + " 2019-01-14" + " urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount" + " " + " " + " ietf-interfaces" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " ietf-ip" + " 2014-06-16" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " iana-if-type" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:iana-if-type" + " " + " " + " ietf-yang-types" + " 2013-07-15" + " urn:ietf:params:xml:ns:yang:ietf-yang-types" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + "" + "" + " " + " sm" + " " + " " + " " + ""); + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, xml, LYD_XML, LYD_PRINT_WITHSIBLINGS); + assert_ptr_not_equal(ext_ctx, LYD_CTX(lyd_child(data))); + ext_ctx = LYD_CTX(lyd_child(data)); + lyd_free_siblings(data); + + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, json, LYD_JSON, LYD_PRINT_WITHSIBLINGS); + assert_ptr_equal(ext_ctx, LYD_CTX(lyd_child(data))); + + assert_int_equal(LY_SUCCESS, lyd_print_mem(&lyb, data, LYD_LYB, 0)); + lyd_free_siblings(data); + + CHECK_PARSE_LYD_PARAM(lyb, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + assert_ptr_equal(ext_ctx, LYD_CTX(lyd_child(data))); + free(lyb); + lyd_free_siblings(data); +} + +static void +test_parse_shared(void **state) +{ + const char *xml, *json; + char *lyb; + struct lyd_node *data; + + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-datastores" + " 2018-02-14" + " urn:ietf:params:xml:ns:yang:ietf-datastores" + " " + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " ietf-yang-schema-mount" + " 2019-01-14" + " urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount" + " " + " " + " ietf-interfaces" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " iana-if-type" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:iana-if-type" + " " + " " + " ietf-yang-types" + " 2013-07-15" + " urn:ietf:params:xml:ns:yang:ietf-yang-types" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + "" + "" + " " + " sm" + " " + " " + " " + ""); + xml = + "\n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " \n" + " \n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " not-present\n" + " \n" + " 2022-01-01T10:00:00-00:00\n" + " \n" + " \n" + " \n" + "\n"; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, xml, LYD_XML, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(data); + + json = + "{\n" + " \"sm:root\": {\n" + " \"ietf-interfaces:interfaces\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"bu\",\n" + " \"type\": \"iana-if-type:ethernetCsmacd\"\n" + " }\n" + " ]\n" + " },\n" + " \"ietf-interfaces:interfaces-state\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"bu\",\n" + " \"type\": \"iana-if-type:ethernetCsmacd\",\n" + " \"oper-status\": \"not-present\",\n" + " \"statistics\": {\n" + " \"discontinuity-time\": \"2022-01-01T10:00:00-00:00\"\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " }\n" + "}\n"; + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, json, LYD_JSON, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(data); + + /* different yang-lib data */ + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-datastores" + " 2018-02-14" + " urn:ietf:params:xml:ns:yang:ietf-datastores" + " " + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " ietf-yang-schema-mount" + " 2019-01-14" + " urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount" + " " + " " + " ietf-interfaces" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " ietf-ip" + " 2014-06-16" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " iana-if-type" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:iana-if-type" + " " + " " + " ietf-yang-types" + " 2013-07-15" + " urn:ietf:params:xml:ns:yang:ietf-yang-types" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 2" + "" + "" + " 1" + "" + "" + " " + " sm" + " " + " " + " " + ""); + xml = + "\n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " \n" + " \n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " not-present\n" + " \n" + " 2022-01-01T10:00:00-00:00\n" + " \n" + " \n" + " \n" + "\n"; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Shared-schema yang-library content-id \"2\" differs from \"1\" used previously.", + "/ietf-yang-library:yang-library/content-id"); + + /* data for 2 mount points */ + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-datastores" + " 2018-02-14" + " urn:ietf:params:xml:ns:yang:ietf-datastores" + " " + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " ietf-yang-schema-mount" + " 2019-01-14" + " urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount" + " " + " " + " ietf-interfaces" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " iana-if-type" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:iana-if-type" + " " + " " + " ietf-yang-types" + " 2013-07-15" + " urn:ietf:params:xml:ns:yang:ietf-yang-types" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + "" + "" + " " + " sm" + " " + " " + " " + ""); + xml = + "\n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " \n" + " \n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " not-present\n" + " \n" + " 2022-01-01T10:00:00-00:00\n" + " \n" + " \n" + " \n" + "\n" + "\n" + " \n" + " \n" + " fu\n" + " ianaift:fddi\n" + " \n" + " \n" + " \n" + " \n" + " fu\n" + " ianaift:fddi\n" + " down\n" + " \n" + " 2020-01-01T10:00:00-00:00\n" + " \n" + " \n" + " \n" + "\n"; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, xml, LYD_XML, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(data); + + json = + "{\n" + " \"sm:root\": {\n" + " \"ietf-interfaces:interfaces\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"bu\",\n" + " \"type\": \"iana-if-type:ethernetCsmacd\"\n" + " }\n" + " ]\n" + " },\n" + " \"ietf-interfaces:interfaces-state\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"bu\",\n" + " \"type\": \"iana-if-type:ethernetCsmacd\",\n" + " \"oper-status\": \"not-present\",\n" + " \"statistics\": {\n" + " \"discontinuity-time\": \"2022-01-01T10:00:00-00:00\"\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " },\n" + " \"sm:root2\": {\n" + " \"ietf-interfaces:interfaces\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"fu\",\n" + " \"type\": \"iana-if-type:fddi\"\n" + " }\n" + " ]\n" + " },\n" + " \"ietf-interfaces:interfaces-state\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"fu\",\n" + " \"type\": \"iana-if-type:fddi\",\n" + " \"oper-status\": \"down\",\n" + " \"statistics\": {\n" + " \"discontinuity-time\": \"2020-01-01T10:00:00-00:00\"\n" + " }\n" + " }\n" + " ]\n" + " }\n" + " }\n" + "}\n"; + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, json, LYD_JSON, LYD_PRINT_WITHSIBLINGS); + + assert_int_equal(LY_SUCCESS, lyd_print_mem(&lyb, data, LYD_LYB, LYD_PRINT_WITHSIBLINGS)); + lyd_free_siblings(data); + + CHECK_PARSE_LYD_PARAM(lyb, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + free(lyb); + lyd_free_siblings(data); +} + +static void +test_parse_shared_parent_ref(void **state) +{ + const char *xml, *json; + struct lyd_node *data; + + /* wrong leafref value */ + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-datastores" + " 2018-02-14" + " urn:ietf:params:xml:ns:yang:ietf-datastores" + " " + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " ietf-yang-schema-mount" + " 2019-01-14" + " urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount" + " " + " " + " sm" + " urn:sm" + " " + " " + " ietf-interfaces" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " iana-if-type" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:iana-if-type" + " " + " " + " ietf-yang-types" + " 2013-07-15" + " urn:ietf:params:xml:ns:yang:ietf-yang-types" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + "" + "" + " " + " smp" + " urn:sm" + " " + " " + " sm" + " " + " " + " /smp:target[. = current()/smp:name]" + " " + " " + ""); + xml = + "\n" + " \n" + " target-value\n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " target-value\n" + " \n" + " \n" + " \n" + "\n" + "wrong-target-value\n"; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Invalid leafref value \"target-value\" - no target instance \"/sm:target\" with the same value.", + "Data location \"/ietf-interfaces:interfaces/interface[name='bu']/sm:sm-name\"."); + + json = + "{\n" + " \"sm:root3\": {\n" + " \"ls\": [" + " {\n" + " \"name\": \"target-value\",\n" + " \"ietf-interfaces:interfaces\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"bu\",\n" + " \"type\": \"iana-if-type:ethernetCsmacd\",\n" + " \"sm:sm-name\": \"target-value\"\n" + " }\n" + " ]\n" + " }\n" + " }\n" + " ]\n" + " },\n" + " \"sm:target\": \"wrong-target-value\"\n" + "}\n"; + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_EVALID, data); + CHECK_LOG_CTX("Ext plugin \"ly2 schema mount v1\": " + "Invalid leafref value \"target-value\" - no target instance \"/sm:target\" with the same value.", + "Data location \"/ietf-interfaces:interfaces/interface[name='bu']/sm:sm-name\"."); + + /* success */ + xml = + "\n" + " \n" + " target-value\n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " target-value\n" + " \n" + " \n" + " \n" + "\n" + "target-value\n"; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, xml, LYD_XML, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(data); + + json = + "{\n" + " \"sm:root3\": {\n" + " \"ls\": [\n" + " {\n" + " \"name\": \"target-value\",\n" + " \"ietf-interfaces:interfaces\": {\n" + " \"interface\": [\n" + " {\n" + " \"name\": \"bu\",\n" + " \"type\": \"iana-if-type:ethernetCsmacd\",\n" + " \"sm:sm-name\": \"target-value\"\n" + " }\n" + " ]\n" + " }\n" + " }\n" + " ]\n" + " },\n" + " \"sm:target\": \"target-value\"\n" + "}\n"; + CHECK_PARSE_LYD_PARAM(json, LYD_JSON, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, json, LYD_JSON, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(data); +} + +static void +test_parse_config(void **state) +{ + const char *xml; + char *lyb; + struct lyd_node *data; + const struct lyd_node *node; + + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-datastores" + " 2018-02-14" + " urn:ietf:params:xml:ns:yang:ietf-datastores" + " " + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " ietf-yang-schema-mount" + " 2019-01-14" + " urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount" + " " + " " + " ietf-interfaces" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " iana-if-type" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:iana-if-type" + " " + " " + " ietf-yang-types" + " 2013-07-15" + " urn:ietf:params:xml:ns:yang:ietf-yang-types" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + "" + "" + " " + " sm" + " " + " false" + " " + " " + ""); + xml = + "\n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " true\n" + " \n" + " \n" + "\n"; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, xml, LYD_XML, LYD_PRINT_WITHSIBLINGS); + + node = lyd_child(data); + assert_string_equal(LYD_NAME(node), "interfaces"); + assert_true(node->schema->flags & LYS_CONFIG_R); + node = lyd_child(node); + assert_string_equal(LYD_NAME(node), "interface"); + assert_true(node->schema->flags & LYS_CONFIG_R); + node = lyd_child(node); + assert_string_equal(LYD_NAME(node), "name"); + assert_true(node->schema->flags & LYS_CONFIG_R); + node = node->next; + assert_string_equal(LYD_NAME(node), "type"); + assert_true(node->schema->flags & LYS_CONFIG_R); + + lyd_print_mem(&lyb, data, LYD_LYB, 0); + lyd_free_siblings(data); + CHECK_PARSE_LYD_PARAM(lyb, LYD_LYB, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + free(lyb); + + node = lyd_child(data); + assert_string_equal(LYD_NAME(node), "interfaces"); + assert_true(node->schema->flags & LYS_CONFIG_R); + node = lyd_child(node); + assert_string_equal(LYD_NAME(node), "interface"); + assert_true(node->schema->flags & LYS_CONFIG_R); + node = lyd_child(node); + assert_string_equal(LYD_NAME(node), "name"); + assert_true(node->schema->flags & LYS_CONFIG_R); + node = node->next; + assert_string_equal(LYD_NAME(node), "type"); + assert_true(node->schema->flags & LYS_CONFIG_R); + + lyd_free_siblings(data); + + /* the same effect but use a config false mount point instead of the separate metadata node */ + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-datastores" + " 2018-02-14" + " urn:ietf:params:xml:ns:yang:ietf-datastores" + " " + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " ietf-yang-schema-mount" + " 2019-01-14" + " urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount" + " " + " " + " ietf-interfaces" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " iana-if-type" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:iana-if-type" + " " + " " + " ietf-yang-types" + " 2013-07-15" + " urn:ietf:params:xml:ns:yang:ietf-yang-types" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + "" + "" + " " + " sm" + " " + " " + " " + ""); + xml = + "\n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " true\n" + " \n" + " \n" + "\n"; + CHECK_PARSE_LYD_PARAM(xml, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, LY_SUCCESS, data); + CHECK_LYD_STRING_PARAM(data, xml, LYD_XML, LYD_PRINT_WITHSIBLINGS); + + node = lyd_child(data->next->next->next); + assert_string_equal(LYD_NAME(node), "interfaces"); + assert_true(node->schema->flags & LYS_CONFIG_R); + node = lyd_child(node); + assert_string_equal(LYD_NAME(node), "interface"); + assert_true(node->schema->flags & LYS_CONFIG_R); + node = lyd_child(node); + assert_string_equal(LYD_NAME(node), "name"); + assert_true(node->schema->flags & LYS_CONFIG_R); + node = node->next; + assert_string_equal(LYD_NAME(node), "type"); + assert_true(node->schema->flags & LYS_CONFIG_R); + + lyd_free_siblings(data); +} + +static void +test_new(void **state) +{ + const char *xml; + const struct lys_module *mod; + struct lyd_node *data, *node; + + ly_ctx_set_ext_data_clb(UTEST_LYCTX, test_ext_data_clb, + "" + " " + " test-set" + " " + " ietf-datastores" + " 2018-02-14" + " urn:ietf:params:xml:ns:yang:ietf-datastores" + " " + " " + " ietf-yang-library" + " 2019-01-04" + " urn:ietf:params:xml:ns:yang:ietf-yang-library" + " " + " " + " ietf-yang-schema-mount" + " 2019-01-14" + " urn:ietf:params:xml:ns:yang:ietf-yang-schema-mount" + " " + " " + " ietf-interfaces" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:ietf-interfaces" + " " + " " + " iana-if-type" + " 2014-05-08" + " urn:ietf:params:xml:ns:yang:iana-if-type" + " " + " " + " ietf-ip" + " 2014-06-16" + " urn:ietf:params:xml:ns:yang:ietf-ip" + " " + " " + " ietf-yang-types" + " 2013-07-15" + " urn:ietf:params:xml:ns:yang:ietf-yang-types" + " " + " " + " " + " test-schema" + " test-set" + " " + " " + " ds:running" + " test-schema" + " " + " " + " ds:operational" + " test-schema" + " " + " 1" + "" + "" + " 1" + "" + "" + " " + " sm" + " " + " " + " " + ""); + xml = + "\n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " \n" + " false\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " bu\n" + " ianaift:ethernetCsmacd\n" + " not-present\n" + " \n" + " 2022-01-01T10:00:00-00:00\n" + " \n" + " \n" + " \n" + "\n"; + + /* create the data manually with simple new functions */ + mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "sm"); + assert_non_null(mod); + assert_int_equal(LY_SUCCESS, lyd_new_inner(NULL, mod, "root", 0, &data)); + + mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "ietf-interfaces"); + assert_non_null(mod); + assert_int_equal(LY_SUCCESS, lyd_new_inner(data, mod, "interfaces", 0, &node)); + assert_int_equal(LY_SUCCESS, lyd_new_list(node, NULL, "interface", 0, &node, "bu")); + assert_int_equal(LY_SUCCESS, lyd_new_term(node, NULL, "type", "iana-if-type:ethernetCsmacd", 0, NULL)); + mod = ly_ctx_get_module_implemented(LYD_CTX(node), "ietf-ip"); + assert_non_null(mod); + assert_int_equal(LY_SUCCESS, lyd_new_inner(node, mod, "ipv4", 0, &node)); + assert_int_equal(LY_SUCCESS, lyd_new_term(node, NULL, "enabled", "false", 0, NULL)); + + mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "ietf-interfaces"); + assert_non_null(mod); + assert_int_equal(LY_SUCCESS, lyd_new_inner(data, mod, "interfaces-state", 0, &node)); + assert_int_equal(LY_SUCCESS, lyd_new_list(node, NULL, "interface", 0, &node, "bu")); + assert_int_equal(LY_SUCCESS, lyd_new_term(node, NULL, "type", "iana-if-type:ethernetCsmacd", 0, NULL)); + assert_int_equal(LY_SUCCESS, lyd_new_term(node, NULL, "oper-status", "not-present", 0, NULL)); + assert_int_equal(LY_SUCCESS, lyd_new_inner(node, NULL, "statistics", 0, &node)); + assert_int_equal(LY_SUCCESS, lyd_new_term(node, NULL, "discontinuity-time", "2022-01-01T10:00:00-00:00", 0, NULL)); + + CHECK_LYD_STRING_PARAM(data, xml, LYD_XML, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(data); + + /* create the data using lyd_new_path */ + assert_int_equal(LY_SUCCESS, lyd_new_path(NULL, UTEST_LYCTX, + "/sm:root/ietf-interfaces:interfaces/interface[name='bu']/type", "iana-if-type:ethernetCsmacd", 0, &data)); + assert_int_equal(LY_SUCCESS, lyd_new_path(data, NULL, + "/sm:root/ietf-interfaces:interfaces/interface[name='bu']/ietf-ip:ipv4/enabled", "false", 0, NULL)); + assert_int_equal(LY_SUCCESS, lyd_new_path(data, NULL, + "/sm:root/ietf-interfaces:interfaces-state/interface[name='bu']/type", "iana-if-type:ethernetCsmacd", 0, NULL)); + assert_int_equal(LY_SUCCESS, lyd_new_path(data, NULL, + "/sm:root/ietf-interfaces:interfaces-state/interface[name='bu']/oper-status", "not-present", 0, NULL)); + assert_int_equal(LY_SUCCESS, lyd_new_path(data, NULL, + "/sm:root/ietf-interfaces:interfaces-state/interface[name='bu']/statistics/discontinuity-time", + "2022-01-01T10:00:00-00:00", 0, NULL)); + + CHECK_LYD_STRING_PARAM(data, xml, LYD_XML, LYD_PRINT_WITHSIBLINGS); + lyd_free_siblings(data); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + UTEST(test_schema), + UTEST(test_parse_invalid, setup), + UTEST(test_parse_inline, setup), + UTEST(test_parse_shared, setup), + UTEST(test_parse_shared_parent_ref, setup), + UTEST(test_parse_config, setup), + UTEST(test_new, setup), + }; + + return cmocka_run_group_tests(tests, NULL, NULL); +} -- cgit v1.2.3