Adding upstream version 3.1.0+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
64dbec996d
commit
cfcebb1a7d
569 changed files with 205393 additions and 0 deletions
1463
tests/utests/data/test_diff.c
Normal file
1463
tests/utests/data/test_diff.c
Normal file
File diff suppressed because it is too large
Load diff
2841
tests/utests/data/test_lyb.c
Normal file
2841
tests/utests/data/test_lyb.c
Normal file
File diff suppressed because it is too large
Load diff
756
tests/utests/data/test_merge.c
Normal file
756
tests/utests/data/test_merge.c
Normal file
|
@ -0,0 +1,756 @@
|
|||
/**
|
||||
* @file test_merge.c
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief tests for complex data merges.
|
||||
*
|
||||
* Copyright (c) 2020 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"
|
||||
|
||||
#define LYD_TREE_CREATE(INPUT, MODEL) \
|
||||
CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, MODEL)
|
||||
|
||||
#define CONTEXT_CREATE \
|
||||
CONTEXT_CREATE_PATH(NULL)
|
||||
|
||||
#define LYD_TREE_CHECK_CHAR(MODEL, TEXT, PARAMS) \
|
||||
CHECK_LYD_STRING_PARAM(MODEL, TEXT, LYD_XML, LYD_PRINT_WITHSIBLINGS | PARAMS)
|
||||
|
||||
static void
|
||||
test_batch(void **state)
|
||||
{
|
||||
const char *start =
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>yang</name>\n"
|
||||
" <revision>2016-02-11</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n";
|
||||
const char *data[] = {
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-yang-library</name>\n"
|
||||
" <revision>2016-02-01</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-acm</name>\n"
|
||||
" <revision>2012-02-22</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-monitoring</name>\n"
|
||||
" <revision>2010-10-04</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-with-defaults</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>yang</name>\n"
|
||||
" <revision>2016-02-11</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-yang-library</name>\n"
|
||||
" <revision>2016-02-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-acm</name>\n"
|
||||
" <revision>2012-02-22</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-acm</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace>\n"
|
||||
" <feature>writable-running</feature>\n"
|
||||
" <feature>candidate</feature>\n"
|
||||
" <feature>rollback-on-error</feature>\n"
|
||||
" <feature>validate</feature>\n"
|
||||
" <feature>startup</feature>\n"
|
||||
" <feature>xpath</feature>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-monitoring</name>\n"
|
||||
" <revision>2010-10-04</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n",
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-with-defaults</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n"
|
||||
};
|
||||
const char *output_template =
|
||||
"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">\n"
|
||||
" <module>\n"
|
||||
" <name>yang</name>\n"
|
||||
" <revision>2016-02-11</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:1</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-yang-library</name>\n"
|
||||
" <revision>2016-02-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-yang-library</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-acm</name>\n"
|
||||
" <revision>2012-02-22</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-acm</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:netconf:base:1.0</namespace>\n"
|
||||
" <feature>writable-running</feature>\n"
|
||||
" <feature>candidate</feature>\n"
|
||||
" <feature>rollback-on-error</feature>\n"
|
||||
" <feature>validate</feature>\n"
|
||||
" <feature>startup</feature>\n"
|
||||
" <feature>xpath</feature>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-monitoring</name>\n"
|
||||
" <revision>2010-10-04</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
" <module>\n"
|
||||
" <name>ietf-netconf-with-defaults</name>\n"
|
||||
" <revision>2011-06-01</revision>\n"
|
||||
" <namespace>urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults</namespace>\n"
|
||||
" <conformance-type>implement</conformance-type>\n"
|
||||
" </module>\n"
|
||||
"</modules-state>\n";
|
||||
|
||||
struct lyd_node *target;
|
||||
|
||||
CHECK_PARSE_LYD_PARAM(start, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, target);
|
||||
|
||||
for (int32_t i = 0; i < 11; ++i) {
|
||||
struct lyd_node *source;
|
||||
|
||||
CHECK_PARSE_LYD_PARAM(data[i], LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, source);
|
||||
assert_int_equal(LY_SUCCESS, lyd_merge_siblings(&target, source, LYD_MERGE_DESTRUCT));
|
||||
}
|
||||
|
||||
LYD_TREE_CHECK_CHAR(target, output_template, 0);
|
||||
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_leaf(void **state)
|
||||
{
|
||||
const char *sch = "module x {"
|
||||
" namespace urn:x;"
|
||||
" prefix x;"
|
||||
" container A {"
|
||||
" leaf f1 {type string;}"
|
||||
" container B {"
|
||||
" leaf f2 {type string;}"
|
||||
" }"
|
||||
" }"
|
||||
" }";
|
||||
const char *trg = "<A xmlns=\"urn:x\"> <f1>block</f1> </A>";
|
||||
const char *src = "<A xmlns=\"urn:x\"> <f1>aa</f1> <B> <f2>bb</f2> </B> </A>";
|
||||
const char *result = "<A xmlns=\"urn:x\"><f1>aa</f1><B><f2>bb</f2></B></A>";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, LYD_PRINT_SHRINK);
|
||||
|
||||
lyd_free_all(target);
|
||||
lyd_free_all(source);
|
||||
}
|
||||
|
||||
static void
|
||||
test_container(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module A {\n"
|
||||
" namespace \"aa:A\";\n"
|
||||
" prefix A;\n"
|
||||
" container A {\n"
|
||||
" leaf f1 {type string;}\n"
|
||||
" container B {\n"
|
||||
" leaf f2 {type string;}\n"
|
||||
" }\n"
|
||||
" container C {\n"
|
||||
" leaf f3 {type string;}\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg = "<A xmlns=\"aa:A\"> <B> <f2>aaa</f2> </B> </A>";
|
||||
const char *src = "<A xmlns=\"aa:A\"> <C> <f3>bbb</f3> </C> </A>";
|
||||
const char *result = "<A xmlns=\"aa:A\"><B><f2>aaa</f2></B><C><f3>bbb</f3></C></A>";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, LYD_PRINT_SHRINK);
|
||||
|
||||
/* destroy */
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_list(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge {\n"
|
||||
" namespace \"http://test/merge\";\n"
|
||||
" prefix merge;\n"
|
||||
"\n"
|
||||
" container inner1 {\n"
|
||||
" list b-list1 {\n"
|
||||
" key p1;\n"
|
||||
" leaf p1 {\n"
|
||||
" type uint8;\n"
|
||||
" }\n"
|
||||
" leaf p2 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf p3 {\n"
|
||||
" type boolean;\n"
|
||||
" default false;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" <p3>true</p3>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *src =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *result =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" <p3>true</p3>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, 0);
|
||||
|
||||
lyd_free_all(target);
|
||||
lyd_free_all(source);
|
||||
}
|
||||
|
||||
static void
|
||||
test_list2(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge {\n"
|
||||
" namespace \"http://test/merge\";\n"
|
||||
" prefix merge;\n"
|
||||
"\n"
|
||||
" container inner1 {\n"
|
||||
" list b-list1 {\n"
|
||||
" key p1;\n"
|
||||
" leaf p1 {\n"
|
||||
" type uint8;\n"
|
||||
" }\n"
|
||||
" leaf p2 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" container inner2 {\n"
|
||||
" leaf p3 {\n"
|
||||
" type boolean;\n"
|
||||
" default false;\n"
|
||||
" }\n"
|
||||
" leaf p4 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" <inner2>\n"
|
||||
" <p4>val</p4>\n"
|
||||
" </inner2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *src =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *result =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" <inner2>\n"
|
||||
" <p4>val</p4>\n"
|
||||
" </inner2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, 0);
|
||||
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dup_inst_list(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge {\n"
|
||||
" namespace \"http://test/merge\";\n"
|
||||
" prefix merge;\n"
|
||||
"\n"
|
||||
" container inner1 {\n"
|
||||
" config false;\n"
|
||||
" list b-list1 {\n"
|
||||
" leaf p1 {\n"
|
||||
" type uint8;\n"
|
||||
" }\n"
|
||||
" leaf p2 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" container inner2 {\n"
|
||||
" leaf p4 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" </b-list1>\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" <inner2>\n"
|
||||
" <p4>val</p4>\n"
|
||||
" </inner2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *src =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" </b-list1>\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>2</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
const char *result =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>b</p2>\n"
|
||||
" </b-list1>\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" <inner2>\n"
|
||||
" <p4>val</p4>\n"
|
||||
" </inner2>\n"
|
||||
" </b-list1>\n"
|
||||
" <b-list1>\n"
|
||||
" <p1>2</p1>\n"
|
||||
" <p2>a</p2>\n"
|
||||
" </b-list1>\n"
|
||||
"</inner1>\n";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, 0);
|
||||
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dup_inst_llist(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge {\n"
|
||||
" namespace \"http://test/merge\";\n"
|
||||
" prefix merge;\n"
|
||||
"\n"
|
||||
" container inner1 {\n"
|
||||
" config false;\n"
|
||||
" leaf-list b-llist1 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>b</b-llist1>\n"
|
||||
" <b-llist1>c</b-llist1>\n"
|
||||
" <b-llist1>d</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>b</b-llist1>\n"
|
||||
" <b-llist1>c</b-llist1>\n"
|
||||
" <b-llist1>d</b-llist1>\n"
|
||||
"</inner1>\n";
|
||||
const char *src =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-llist1>d</b-llist1>\n"
|
||||
" <b-llist1>c</b-llist1>\n"
|
||||
" <b-llist1>b</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>f</b-llist1>\n"
|
||||
" <b-llist1>f</b-llist1>\n"
|
||||
"</inner1>\n";
|
||||
const char *result =
|
||||
"<inner1 xmlns=\"http://test/merge\">\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>b</b-llist1>\n"
|
||||
" <b-llist1>c</b-llist1>\n"
|
||||
" <b-llist1>d</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>b</b-llist1>\n"
|
||||
" <b-llist1>c</b-llist1>\n"
|
||||
" <b-llist1>d</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>a</b-llist1>\n"
|
||||
" <b-llist1>f</b-llist1>\n"
|
||||
" <b-llist1>f</b-llist1>\n"
|
||||
"</inner1>\n";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, 0);
|
||||
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_case(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge {\n"
|
||||
" namespace \"http://test/merge\";\n"
|
||||
" prefix merge;\n"
|
||||
" container cont {\n"
|
||||
" choice ch {\n"
|
||||
" container inner {\n"
|
||||
" leaf p1 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" case c2 {\n"
|
||||
" leaf p1 {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
const char *trg =
|
||||
"<cont xmlns=\"http://test/merge\">\n"
|
||||
" <inner>\n"
|
||||
" <p1>1</p1>\n"
|
||||
" </inner>\n"
|
||||
"</cont>\n";
|
||||
const char *src =
|
||||
"<cont xmlns=\"http://test/merge\">\n"
|
||||
" <p1>1</p1>\n"
|
||||
"</cont>\n";
|
||||
const char *result =
|
||||
"<cont xmlns=\"http://test/merge\">\n"
|
||||
" <p1>1</p1>\n"
|
||||
"</cont>\n";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
/* merge them */
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
/* check the result */
|
||||
LYD_TREE_CHECK_CHAR(target, result, 0);
|
||||
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dflt(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge-dflt {\n"
|
||||
" namespace \"urn:merge-dflt\";\n"
|
||||
" prefix md;\n"
|
||||
" container top {\n"
|
||||
" leaf a {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf b {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf c {\n"
|
||||
" type string;\n"
|
||||
" default \"c_dflt\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
struct lyd_node *target = NULL;
|
||||
struct lyd_node *source = NULL;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/c", "c_dflt", 0, &target), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/a", "a_val", 0, &source), LY_SUCCESS);
|
||||
assert_int_equal(lyd_new_path(source, UTEST_LYCTX, "/merge-dflt:top/b", "b_val", 0, NULL), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&source, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, LYD_MERGE_DESTRUCT | LYD_MERGE_DEFAULTS), LY_SUCCESS);
|
||||
source = NULL;
|
||||
|
||||
/* c should be replaced and now be default */
|
||||
assert_string_equal(lyd_child(target)->prev->schema->name, "c");
|
||||
assert_true(lyd_child(target)->prev->flags & LYD_DEFAULT);
|
||||
|
||||
lyd_free_all(target);
|
||||
lyd_free_all(source);
|
||||
}
|
||||
|
||||
static void
|
||||
test_dflt2(void **state)
|
||||
{
|
||||
const char *sch =
|
||||
"module merge-dflt {\n"
|
||||
" namespace \"urn:merge-dflt\";\n"
|
||||
" prefix md;\n"
|
||||
" container top {\n"
|
||||
" leaf a {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf b {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf c {\n"
|
||||
" type string;\n"
|
||||
" default \"c_dflt\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
struct lyd_node *target;
|
||||
struct lyd_node *source;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/c", "c_dflt", 0, &target), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&target, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
assert_int_equal(lyd_new_path(NULL, UTEST_LYCTX, "/merge-dflt:top/a", "a_val", 0, &source), LY_SUCCESS);
|
||||
assert_int_equal(lyd_new_path(source, UTEST_LYCTX, "/merge-dflt:top/b", "b_val", 0, NULL), LY_SUCCESS);
|
||||
assert_int_equal(lyd_validate_all(&source, NULL, LYD_VALIDATE_PRESENT, NULL), LY_SUCCESS);
|
||||
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
|
||||
/* c should not be replaced, so c remains not default */
|
||||
assert_false(lyd_child(target)->flags & LYD_DEFAULT);
|
||||
|
||||
lyd_free_all(target);
|
||||
lyd_free_all(source);
|
||||
}
|
||||
|
||||
static void
|
||||
test_leafrefs(void **state)
|
||||
{
|
||||
const char *sch = "module x {"
|
||||
" namespace urn:x;"
|
||||
" prefix x;"
|
||||
" list l {"
|
||||
" key n;"
|
||||
" leaf n { type string; }"
|
||||
" leaf t { type string; }"
|
||||
" leaf r { type leafref { path '/l/n'; } }}}";
|
||||
const char *trg = "<l xmlns=\"urn:x\"><n>a</n></l>"
|
||||
"<l xmlns=\"urn:x\"><n>b</n><r>a</r></l>";
|
||||
const char *src = "<l xmlns=\"urn:x\"><n>c</n><r>a</r></l>"
|
||||
"<l xmlns=\"urn:x\"><n>a</n><t>*</t></l>";
|
||||
const char *res = "<l xmlns=\"urn:x\"><n>a</n><t>*</t></l>"
|
||||
"<l xmlns=\"urn:x\"><n>b</n><r>a</r></l>"
|
||||
"<l xmlns=\"urn:x\"><n>c</n><r>a</r></l>";
|
||||
struct lyd_node *source, *target;
|
||||
|
||||
UTEST_ADD_MODULE(sch, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
LYD_TREE_CREATE(src, source);
|
||||
LYD_TREE_CREATE(trg, target);
|
||||
|
||||
assert_int_equal(lyd_merge_siblings(&target, source, 0), LY_SUCCESS);
|
||||
|
||||
LYD_TREE_CHECK_CHAR(target, res, LYD_PRINT_SHRINK);
|
||||
|
||||
lyd_free_all(source);
|
||||
lyd_free_all(target);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_batch),
|
||||
UTEST(test_leaf),
|
||||
UTEST(test_container),
|
||||
UTEST(test_list),
|
||||
UTEST(test_list2),
|
||||
UTEST(test_dup_inst_list),
|
||||
UTEST(test_dup_inst_llist),
|
||||
UTEST(test_case),
|
||||
UTEST(test_dflt),
|
||||
UTEST(test_dflt2),
|
||||
UTEST(test_leafrefs),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
536
tests/utests/data/test_new.c
Normal file
536
tests/utests/data/test_new.c
Normal file
|
@ -0,0 +1,536 @@
|
|||
/**
|
||||
* @file test_new.c
|
||||
* @author: Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief unit tests for functions for creating data
|
||||
*
|
||||
* Copyright (c) 2020 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"
|
||||
|
||||
/* common module for the tests */
|
||||
const char *schema_a = "module a {\n"
|
||||
" namespace urn:tests:a;\n"
|
||||
" prefix a;yang-version 1.1;\n"
|
||||
" list l1 {\n"
|
||||
" key \"a b\";\n"
|
||||
" leaf a {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf b {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf c {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" list l11 {\n"
|
||||
" key \"a\";\n"
|
||||
" leaf a {\n"
|
||||
" type uint32;\n"
|
||||
" }\n"
|
||||
" leaf b {\n"
|
||||
" type uint32;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" leaf foo {\n"
|
||||
" type uint16;\n"
|
||||
" }\n"
|
||||
" leaf-list ll {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" container c {\n"
|
||||
" leaf-list x {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" anydata any {\n"
|
||||
" config false;\n"
|
||||
" }\n"
|
||||
" anyxml anyx;\n"
|
||||
" leaf-list ll2 {\n"
|
||||
" config false;\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" list l2 {\n"
|
||||
" config false;\n"
|
||||
" container c {\n"
|
||||
" leaf x {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" container c2 {\n"
|
||||
" config false;\n"
|
||||
" list l3 {\n"
|
||||
" leaf x {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf y {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" rpc oper {\n"
|
||||
" input {\n"
|
||||
" leaf param {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" output {\n"
|
||||
" leaf param {\n"
|
||||
" type int8;\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
|
||||
static void
|
||||
test_top_level(void **state)
|
||||
{
|
||||
struct lys_module *mod;
|
||||
struct lyd_node *node, *rpc;
|
||||
|
||||
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, &mod);
|
||||
|
||||
/* list */
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l1", 0, &node, "val_a", "val_b"), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[]", 0, &node), LY_EVALID);
|
||||
CHECK_LOG_CTX("Unexpected XPath token \"]\" (\"]\").", "/a:l1", 0);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[key1='a'][key2='b']", 0, &node), LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("Not found node \"key1\" in path.", "/a:l1", 0);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[a='a'][b='b'][c='c']", 0, &node), LY_EVALID);
|
||||
CHECK_LOG_CTX("Key expected instead of leaf \"c\" in path.", "/a:l1", 0);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "c", "[a='a'][b='b']", 0, &node), LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("List node \"c\" not found.", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[a='a'][b='b']", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[a=''][b='']", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[a:a='a'][a:b='b']", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l1", "[a= 'a']\n[b =\t'b']", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
const char *key_vals[] = {"a", "b"};
|
||||
|
||||
assert_int_equal(lyd_new_list3(NULL, mod, "l1", key_vals, NULL, 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
uint32_t val_lens[] = {1, 1};
|
||||
|
||||
assert_int_equal(lyd_new_list3(NULL, mod, "l1", key_vals, val_lens, LYD_NEW_VAL_BIN, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list3(NULL, mod, "l1", key_vals, val_lens, LYD_NEW_VAL_CANON, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_list3(NULL, mod, "l1", key_vals, val_lens, LYD_NEW_VAL_CANON | LYD_NEW_VAL_STORE_ONLY, &node), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)) (lyd_new_list3()).", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l1", LYD_NEW_VAL_BIN, &node, "val_a", 5, "val_b", 5), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l1", LYD_NEW_VAL_BIN | LYD_NEW_VAL_STORE_ONLY, &node, "val_a", 5, "val_b", 5), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)) (lyd_new_list()).", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l1", LYD_NEW_VAL_CANON, &node, "val_a", "val_b"), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l1", LYD_NEW_VAL_CANON | LYD_NEW_VAL_STORE_ONLY, &node, "val_a", "val_b"), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)) (lyd_new_list()).", NULL, 0);
|
||||
|
||||
/* leaf */
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "foo", "[a='a'][b='b'][c='c']", 0, &node), LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid type uint16 value \"[a='a'][b='b'][c='c']\".", "/a:foo", 0);
|
||||
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "c", "value", 0, &node), LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("Term node \"c\" not found.", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "foo", "256", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "foo", "25", LYD_NEW_VAL_BIN, &node), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(options & 0x04) (lyd_new_term()).", NULL, 0);
|
||||
assert_int_equal(lyd_new_term_bin(NULL, mod, "foo", "25", 2, LYD_NEW_VAL_BIN, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_term_bin(NULL, mod, "foo", "25", 2, LYD_NEW_VAL_STORE_ONLY, &node), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)) (_lyd_new_term()).", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "foo", "25", LYD_NEW_VAL_CANON, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "foo", "25", LYD_NEW_VAL_CANON | LYD_NEW_VAL_STORE_ONLY, &node), LY_EINVAL);
|
||||
CHECK_LOG_CTX("Invalid argument !(store_only && (format == LY_VALUE_CANON || format == LY_VALUE_LYB)) (_lyd_new_term()).", NULL, 0);
|
||||
|
||||
/* leaf-list */
|
||||
assert_int_equal(lyd_new_term(NULL, mod, "ll", "ahoy", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
/* container */
|
||||
assert_int_equal(lyd_new_inner(NULL, mod, "c", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_inner(NULL, mod, "l1", 0, &node), LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("Inner node (container, notif, RPC, or action) \"l1\" not found.", NULL, 0);
|
||||
|
||||
assert_int_equal(lyd_new_inner(NULL, mod, "l2", 0, &node), LY_ENOTFOUND);
|
||||
CHECK_LOG_CTX("Inner node (container, notif, RPC, or action) \"l2\" not found.", NULL, 0);
|
||||
|
||||
/* anydata */
|
||||
assert_int_equal(lyd_new_any(NULL, mod, "any", "{\"node\":\"val\"}", LYD_ANYDATA_STRING, 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
assert_int_equal(lyd_new_any(NULL, mod, "any", "<node>val</node>", LYD_ANYDATA_STRING, 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
/* key-less list */
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l2", "[a='a'][b='b']", 0, &node), LY_EVALID);
|
||||
CHECK_LOG_CTX("List predicate defined for keyless list \"l2\" in path.", "/a:l2", 0);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l2", "", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list2(NULL, mod, "l2", NULL, 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
assert_int_equal(lyd_new_list(NULL, mod, "l2", 0, &node), LY_SUCCESS);
|
||||
lyd_free_tree(node);
|
||||
|
||||
/* RPC */
|
||||
assert_int_equal(lyd_new_inner(NULL, mod, "oper", 0, &rpc), LY_SUCCESS);
|
||||
assert_int_equal(lyd_new_term(rpc, mod, "param", "22", 0, &node), LY_SUCCESS);
|
||||
assert_int_equal(LY_TYPE_STRING, ((struct lysc_node_leaf *)node->schema)->type->basetype);
|
||||
assert_int_equal(lyd_new_term(rpc, mod, "param", "22", LYD_NEW_VAL_OUTPUT, &node), LY_SUCCESS);
|
||||
assert_int_equal(LY_TYPE_INT8, ((struct lysc_node_leaf *)node->schema)->type->basetype);
|
||||
lyd_free_tree(rpc);
|
||||
}
|
||||
|
||||
static void
|
||||
test_opaq(void **state)
|
||||
{
|
||||
struct lyd_node *root, *node;
|
||||
struct lyd_node_opaq *opq;
|
||||
|
||||
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
assert_int_equal(lyd_new_opaq(NULL, UTEST_LYCTX, "node1", NULL, NULL, "my-module", &root), LY_SUCCESS);
|
||||
assert_null(root->schema);
|
||||
opq = (struct lyd_node_opaq *)root;
|
||||
assert_string_equal(opq->name.name, "node1");
|
||||
assert_string_equal(opq->name.module_name, "my-module");
|
||||
assert_string_equal(opq->value, "");
|
||||
|
||||
assert_int_equal(lyd_new_opaq(root, NULL, "node2", "value", NULL, "my-module2", &node), LY_SUCCESS);
|
||||
assert_null(node->schema);
|
||||
opq = (struct lyd_node_opaq *)node;
|
||||
assert_string_equal(opq->name.name, "node2");
|
||||
assert_string_equal(opq->name.module_name, "my-module2");
|
||||
assert_string_equal(opq->value, "value");
|
||||
assert_ptr_equal(opq->parent, root);
|
||||
|
||||
lyd_free_tree(root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_path(void **state)
|
||||
{
|
||||
LY_ERR ret;
|
||||
struct lyd_node *root, *node, *parent;
|
||||
struct lys_module *mod;
|
||||
char *str;
|
||||
|
||||
UTEST_ADD_MODULE(schema_a, LYS_IN_YANG, NULL, &mod);
|
||||
|
||||
/* create 2 nodes */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:c/x[.='val']", "vvv", 0, 0, 0, &root, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_string_equal(root->schema->name, "c");
|
||||
assert_non_null(node);
|
||||
assert_string_equal(node->schema->name, "x");
|
||||
assert_string_equal("val", lyd_get_value(node));
|
||||
|
||||
/* append another */
|
||||
ret = lyd_new_path2(root, NULL, "/a:c/x", "val2", 0, 0, 0, &parent, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_ptr_equal(parent, node);
|
||||
assert_string_equal(node->schema->name, "x");
|
||||
assert_string_equal("val2", lyd_get_value(node));
|
||||
|
||||
/* and a last one */
|
||||
ret = lyd_new_path2(root, NULL, "x", "val3", 0, 0, 0, &parent, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_ptr_equal(parent, node);
|
||||
assert_string_equal(node->schema->name, "x");
|
||||
assert_string_equal("val3", lyd_get_value(node));
|
||||
|
||||
lyd_free_tree(root);
|
||||
|
||||
/* try LYD_NEWOPT_OPAQ */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:l1", NULL, 0, 0, 0, NULL, NULL);
|
||||
assert_int_equal(ret, LY_EINVAL);
|
||||
CHECK_LOG_CTX("Predicate missing for list \"l1\" in path \"/a:l1\".", "/a:l1", 0);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:l1", NULL, 0, 0, LYD_NEW_PATH_OPAQ, NULL, &root);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_null(root->schema);
|
||||
|
||||
lyd_free_tree(root);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:foo", NULL, 0, 0, 0, NULL, NULL);
|
||||
assert_int_equal(ret, LY_EVALID);
|
||||
CHECK_LOG_CTX("Invalid type uint16 empty value.", "/a:foo", 0);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:foo", NULL, 0, 0, LYD_NEW_PATH_OPAQ, NULL, &root);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_null(root->schema);
|
||||
|
||||
lyd_free_tree(root);
|
||||
|
||||
ret = lyd_new_path(NULL, UTEST_LYCTX, "/a:l11", NULL, LYD_NEW_PATH_OPAQ, &root);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_null(root->schema);
|
||||
|
||||
ret = lyd_new_path(root, NULL, "a", NULL, LYD_NEW_PATH_OPAQ, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(lyd_child(root));
|
||||
assert_null(lyd_child(root)->schema);
|
||||
|
||||
ret = lyd_new_path(root, NULL, "b", NULL, LYD_NEW_PATH_OPAQ, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(lyd_child(root)->next);
|
||||
assert_null(lyd_child(root)->next->schema);
|
||||
|
||||
lyd_free_tree(root);
|
||||
|
||||
/* key-less list */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:c2/l3/x", "val1", 0, 0, 0, &root, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_string_equal(node->schema->name, "x");
|
||||
assert_string_equal("val1", lyd_get_value(node));
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[1]", NULL, 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_EEXIST);
|
||||
CHECK_LOG_CTX("Path \"/a:c2/l3[1]\" already exists.", "/a:c2/l3[1]", 0);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[2]/x", "val2", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3/x", "val3", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[4]/x", "empty", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[4]/x", "val4", 0, 0, LYD_NEW_PATH_UPDATE, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[5]/x", "val5", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:c2/l3[6]/x", "val6", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<c2 xmlns=\"urn:tests:a\">\n"
|
||||
" <l3>\n"
|
||||
" <x>val1</x>\n"
|
||||
" </l3>\n"
|
||||
" <l3>\n"
|
||||
" <x>val2</x>\n"
|
||||
" </l3>\n"
|
||||
" <l3>\n"
|
||||
" <x>val3</x>\n"
|
||||
" </l3>\n"
|
||||
" <l3>\n"
|
||||
" <x>val4</x>\n"
|
||||
" </l3>\n"
|
||||
" <l3>\n"
|
||||
" <x>val5</x>\n"
|
||||
" </l3>\n"
|
||||
" <l3>\n"
|
||||
" <x>val6</x>\n"
|
||||
" </l3>\n"
|
||||
"</c2>\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
/* state leaf-list */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:ll2", "val_first", 0, 0, 0, &root, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_string_equal(node->schema->name, "ll2");
|
||||
assert_string_equal("val_first", lyd_get_value(node));
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:ll2[1]", "", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_EEXIST);
|
||||
CHECK_LOG_CTX("Path \"/a:ll2[1]\" already exists.", "/a:ll2[1]", 0);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:ll2[2]", "val2", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:ll2[1]", "val", 0, 0, LYD_NEW_PATH_UPDATE, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, UTEST_LYCTX, "/a:ll2", "val3", 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(node);
|
||||
|
||||
ret = lyd_new_path2(root, NULL, "/a:ll2[3][.='val3']", NULL, 0, 0, 0, NULL, &node);
|
||||
assert_int_equal(ret, LY_EVALID);
|
||||
CHECK_LOG_CTX("Unparsed characters \"[.='val3']\" left at the end of path.", NULL, 0);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<ll2 xmlns=\"urn:tests:a\">val</ll2>\n"
|
||||
"<ll2 xmlns=\"urn:tests:a\">val2</ll2>\n"
|
||||
"<ll2 xmlns=\"urn:tests:a\">val3</ll2>\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
/* anydata */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:any", "<elem>val</elem>", 0, LYD_ANYDATA_XML, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<any xmlns=\"urn:tests:a\">\n"
|
||||
" <elem>val</elem>\n"
|
||||
"</any>\n");
|
||||
free(str);
|
||||
lyd_print_mem(&str, root, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"{\n"
|
||||
" \"a:any\": {\n"
|
||||
" \"elem\": \"val\"\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
/* anyxml */
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:anyx", "<a/><b/><c/>", 0, LYD_ANYDATA_XML, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<anyx xmlns=\"urn:tests:a\">\n"
|
||||
" <a/>\n"
|
||||
" <b/>\n"
|
||||
" <c/>\n"
|
||||
"</anyx>\n");
|
||||
free(str);
|
||||
lyd_print_mem(&str, root, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"{\n"
|
||||
" \"a:anyx\": {\n"
|
||||
" \"a\": [null],\n"
|
||||
" \"b\": [null],\n"
|
||||
" \"c\": [null]\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
|
||||
ret = lyd_new_path2(NULL, UTEST_LYCTX, "/a:anyx", "{\"a\":[null],\"b\":[null],\"c\":[null]}", 0, LYD_ANYDATA_JSON, 0, &root, NULL);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
|
||||
lyd_print_mem(&str, root, LYD_XML, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"<anyx xmlns=\"urn:tests:a\">\n"
|
||||
" <a/>\n"
|
||||
" <b/>\n"
|
||||
" <c/>\n"
|
||||
"</anyx>\n");
|
||||
free(str);
|
||||
lyd_print_mem(&str, root, LYD_JSON, LYD_PRINT_WITHSIBLINGS);
|
||||
assert_string_equal(str,
|
||||
"{\n"
|
||||
" \"a:anyx\": {\n"
|
||||
" \"a\": [null],\n"
|
||||
" \"b\": [null],\n"
|
||||
" \"c\": [null]\n"
|
||||
" }\n"
|
||||
"}\n");
|
||||
free(str);
|
||||
lyd_free_siblings(root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_path_ext(void **state)
|
||||
{
|
||||
LY_ERR ret;
|
||||
struct lyd_node *root, *node;
|
||||
struct lys_module *mod;
|
||||
const char *mod_str = "module ext {yang-version 1.1; namespace urn:tests:extensions:ext; prefix e;"
|
||||
"import ietf-restconf {revision-date 2017-01-26; prefix rc;}"
|
||||
"rc:yang-data template {container c {leaf x {type string;} leaf y {type string;} leaf z {type string;}}}}";
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-restconf", "2017-01-26", NULL));
|
||||
|
||||
UTEST_ADD_MODULE(mod_str, LYS_IN_YANG, NULL, &mod);
|
||||
|
||||
/* create x */
|
||||
ret = lyd_new_ext_path(NULL, &mod->compiled->exts[0], "/ext:c/x", "xxx", 0, &root);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_non_null(root);
|
||||
assert_string_equal(root->schema->name, "c");
|
||||
assert_non_null(node = lyd_child(root));
|
||||
assert_string_equal(node->schema->name, "x");
|
||||
assert_string_equal("xxx", lyd_get_value(node));
|
||||
|
||||
/* append y */
|
||||
ret = lyd_new_ext_path(root, &mod->compiled->exts[0], "/ext:c/y", "yyy", 0, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_string_equal(node->schema->name, "y");
|
||||
assert_string_equal("yyy", lyd_get_value(node));
|
||||
|
||||
/* append z */
|
||||
ret = lyd_new_path(root, NULL, "ext:z", "zzz", 0, &node);
|
||||
assert_int_equal(ret, LY_SUCCESS);
|
||||
assert_string_equal(node->schema->name, "z");
|
||||
assert_string_equal("zzz", lyd_get_value(node));
|
||||
|
||||
lyd_free_tree(root);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_top_level),
|
||||
UTEST(test_opaq),
|
||||
UTEST(test_path),
|
||||
UTEST(test_path_ext),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
945
tests/utests/data/test_parser_json.c
Normal file
945
tests/utests/data/test_parser_json.c
Normal file
|
@ -0,0 +1,945 @@
|
|||
/**
|
||||
* @file test_parser_json.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Michal Vasko <mvasko@cesnet.cz>
|
||||
* @brief unit tests for JSON parser
|
||||
*
|
||||
* Copyright (c) 2019 - 2023 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 "context.h"
|
||||
#include "in.h"
|
||||
#include "out.h"
|
||||
#include "parser_data.h"
|
||||
#include "printer_data.h"
|
||||
#include "tests_config.h"
|
||||
#include "tree_data_internal.h"
|
||||
#include "tree_schema.h"
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
const char *schema = "module a {namespace urn:tests:a;prefix a;yang-version 1.1; import ietf-yang-metadata {prefix md;}"
|
||||
"md:annotation hint { type int8;}"
|
||||
"list l1 { key \"a b c\"; leaf a {type string;} leaf b {type string;} leaf c {type int16;}"
|
||||
" leaf d {type string;}"
|
||||
" container cont {leaf e {type boolean;}}"
|
||||
"}"
|
||||
"leaf foo { type string;}"
|
||||
"container c {"
|
||||
" leaf x {type string;}"
|
||||
" action act { input { leaf al {type string;} } output { leaf al {type uint8;} } }"
|
||||
" notification n1 { leaf nl {type string;} }"
|
||||
"}"
|
||||
"container cp {presence \"container switch\"; leaf y {type string;} leaf z {type int8;}}"
|
||||
"anydata any {config false;}"
|
||||
"anyxml axml;"
|
||||
"leaf-list ll1 { type uint8; }"
|
||||
"leaf foo2 { type string; default \"default-val\"; }"
|
||||
"leaf foo3 { type uint32; }"
|
||||
"leaf foo4 { type uint64; }"
|
||||
"rpc r1 {input {leaf l1 {type string;} leaf l2 {type string;}}}"
|
||||
"notification n2;"
|
||||
"}";
|
||||
|
||||
UTEST_SETUP;
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CHECK_PARSE_LYD(INPUT, PARSE_OPTION, VALIDATE_OPTION, TREE) \
|
||||
CHECK_PARSE_LYD_PARAM(INPUT, LYD_JSON, PARSE_OPTION, VALIDATE_OPTION, LY_SUCCESS, TREE)
|
||||
|
||||
#define PARSER_CHECK_ERROR(INPUT, PARSE_OPTION, VALIDATE_OPTION, MODEL, RET_VAL, ERR_MESSAGE, ERR_PATH, ERR_LINE) \
|
||||
assert_int_equal(RET_VAL, lyd_parse_data_mem(UTEST_LYCTX, INPUT, LYD_JSON, PARSE_OPTION, VALIDATE_OPTION, &MODEL));\
|
||||
CHECK_LOG_CTX(ERR_MESSAGE, ERR_PATH, ERR_LINE);\
|
||||
assert_null(MODEL)
|
||||
|
||||
#define CHECK_LYD_STRING(IN_MODEL, PRINT_OPTION, TEXT) \
|
||||
CHECK_LYD_STRING_PARAM(IN_MODEL, TEXT, LYD_JSON, PRINT_OPTION)
|
||||
|
||||
static void
|
||||
test_leaf(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
struct lyd_node_term *leaf;
|
||||
const char *data;
|
||||
|
||||
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-with-defaults", "2011-06-01", NULL));
|
||||
|
||||
data = "{\"a:foo\":\"foo value\"}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "foo", 1, LYS_LEAF, 0, 0, NULL, 0);
|
||||
leaf = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(leaf->value, STRING, "foo value");
|
||||
|
||||
CHECK_LYSC_NODE(tree->next->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_SET_DFLT, 1, "foo2",
|
||||
1, LYS_LEAF, 0, 0, NULL, 0);
|
||||
leaf = (struct lyd_node_term *)tree->next->next;
|
||||
|
||||
CHECK_LYD_VALUE(leaf->value, STRING, "default-val");
|
||||
assert_true(leaf->flags & LYD_DEFAULT);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* make foo2 explicit */
|
||||
data = "{\"a:foo2\":\"default-val\"}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_SET_DFLT, 1, "foo2",
|
||||
1, LYS_LEAF, 0, 0, NULL, 0);
|
||||
leaf = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(leaf->value, STRING, "default-val");
|
||||
assert_false(leaf->flags & LYD_DEFAULT);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* parse foo2 but make it implicit */
|
||||
data = "{\"a:foo2\":\"default-val\",\"@a:foo2\":{\"ietf-netconf-with-defaults:default\":true}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_SET_DFLT, 1, "foo2",
|
||||
1, LYS_LEAF, 0, 0, NULL, 0);
|
||||
leaf = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(leaf->value, STRING, "default-val");
|
||||
assert_true(leaf->flags & LYD_DEFAULT);
|
||||
|
||||
/* print default values */
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS | LYD_PRINT_WD_ALL_TAG, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* skip leaf */
|
||||
data = "{\"a:cp\":{\"x\":\"val\",\"y\":\"valy\",\"z\":5}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{\"a:cp\":{\"y\":\"valy\",\"z\":5}}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* multiple meatadata hint and unknown metadata xxx supposed to be skipped since it is from missing schema */
|
||||
data = "{\"@a:foo\":{\"a:hint\":1,\"a:hint\":2,\"x:xxx\":{\"value\":\"/x:no/x:yes\"}},\"a:foo\":\"xxx\"}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "foo", 1, LYS_LEAF, 0, 0, NULL, 0);
|
||||
CHECK_LYD_META(tree->meta, 1, "hint", 1, 1, INT8, "1", 1);
|
||||
CHECK_LYD_META(tree->meta->next, 1, "hint", 0, 1, INT8, "2", 2);
|
||||
assert_null(tree->meta->next->next);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS,
|
||||
"{\"a:foo\":\"xxx\",\"@a:foo\":{\"a:hint\":1,\"a:hint\":2}}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
PARSER_CHECK_ERROR(data, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Unknown (or not implemented) YANG module \"x\" of metadata \"x:xxx\".", "/@a:foo", 1);
|
||||
|
||||
/* missing referenced metadata node */
|
||||
PARSER_CHECK_ERROR("{\"@a:foo\" : { \"a:hint\" : 1 }}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Missing JSON data instance to be coupled with @a:foo metadata.", "/@a:foo", 1);
|
||||
|
||||
/* missing namespace for meatadata*/
|
||||
PARSER_CHECK_ERROR("{\"a:foo\" : \"value\", \"@a:foo\" : { \"hint\" : 1 }}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Metadata in JSON must be namespace-qualified, missing prefix for \"hint\".", "/a:foo", 1);
|
||||
|
||||
/* invalid JSON type */
|
||||
data = "{\"a:l1\" : [{ \"a\" : \"val-a\", \"b\" : \"val-b\", \"c\" : 1, \"cont\" : { \"e\" : \"0\" } }]}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Invalid non-boolean-encoded boolean value \"0\".", "/a:l1[a='val-a'][b='val-b'][c='1']/cont/e", 1);
|
||||
|
||||
/* reverse solidus in JSON object member name */
|
||||
data = "{\"@a:foo\":{\"a:hi\\nt\":1},\"a:foo\":\"xxx\"}";
|
||||
assert_int_equal(LY_EINVAL, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
CHECK_LOG_CTX("Annotation definition for attribute \"a:hi\nt\" not found.", "/@a:foo/@a:hi\nt", 1);
|
||||
|
||||
data = "{\"a:foo\": null}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Invalid non-string-encoded string value \"\".", "/a:foo", 1);
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_NULL, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_leaflist(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
struct lyd_node_term *ll;
|
||||
|
||||
data = "{\"a:ll1\":[10,11]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "10", 10);
|
||||
|
||||
assert_non_null(tree->next);
|
||||
CHECK_LYSC_NODE(tree->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree->next;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "11", 11);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* accept empty */
|
||||
data = "{\"a:ll1\":[]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
|
||||
/* simple metadata */
|
||||
data = "{\"a:ll1\":[10,11],\"@a:ll1\":[null,{\"a:hint\":2}]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "10", 10);
|
||||
|
||||
assert_non_null(tree->next);
|
||||
CHECK_LYSC_NODE(tree->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree->next;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "11", 11);
|
||||
CHECK_LYD_META(ll->meta, 1, "hint", 0, 1, INT8, "2", 2);
|
||||
assert_null(ll->meta->next);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* multiple meatadata hint and unknown metadata xxx supposed to be skipped since it is from missing schema */
|
||||
data = "{\"@a:ll1\" : [{\"a:hint\" : 1, \"x:xxx\" : { \"value\" : \"/x:no/x:yes\" }, "
|
||||
"\"a:hint\" : 10},null,{\"a:hint\" : 3}], \"a:ll1\" : [1,2,3]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "1", 1);
|
||||
CHECK_LYD_META(ll->meta->next, 1, "hint", 1, 1, INT8, "1", 1);
|
||||
CHECK_LYD_META(ll->meta->next->next, 1, "hint", 0, 1, INT8, "10", 10);
|
||||
|
||||
assert_non_null(tree->next);
|
||||
CHECK_LYSC_NODE(tree->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree->next;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "2", 2);
|
||||
assert_null(ll->meta);
|
||||
|
||||
assert_non_null(tree->next->next);
|
||||
CHECK_LYSC_NODE(tree->next->next->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "ll1",
|
||||
1, LYS_LEAFLIST, 0, 0, NULL, 0);
|
||||
ll = (struct lyd_node_term *)tree->next->next;
|
||||
CHECK_LYD_VALUE(ll->value, UINT8, "3", 3);
|
||||
CHECK_LYD_META(ll->meta, 1, "hint", 0, 1, INT8, "3", 3);
|
||||
assert_null(ll->meta->next);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS,
|
||||
"{\"a:ll1\":[1,2,3],\"@a:ll1\":[{\"a:hint\":1,\"a:hint\":10},null,{\"a:hint\":3}]}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* missing referenced metadata node */
|
||||
PARSER_CHECK_ERROR("{\"@a:ll1\":[{\"a:hint\":1}]}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Missing JSON data instance to be coupled with @a:ll1 metadata.", "/@a:ll1", 1);
|
||||
|
||||
PARSER_CHECK_ERROR("{\"a:ll1\":[1],\"@a:ll1\":[{\"a:hint\":1},{\"a:hint\":2}]}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Missing JSON data instance #2 of a:ll1 to be coupled with metadata.", "/a:ll1", 1);
|
||||
|
||||
PARSER_CHECK_ERROR("{\"@a:ll1\":[{\"a:hint\":1},{\"a:hint\":2},{\"a:hint\":3}],\"a:ll1\" : [1, 2]}", 0, LYD_VALIDATE_PRESENT,
|
||||
tree, LY_EVALID, "Missing JSON data instance #3 to be coupled with @a:ll1 metadata.", "/@a:ll1", 1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_anydata(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
data = "{\"a:any\":{\"x:element1\":{\"element2\":\"/a:some/a:path\",\"list\":[{},{\"key\":\"a\"}]}}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_R | LYS_SET_CONFIG, 1, "any",
|
||||
1, LYS_ANYDATA, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:any\":{}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_R | LYS_SET_CONFIG, 1, "any",
|
||||
1, LYS_ANYDATA, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:any\":{\"node\":20}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_R | LYS_SET_CONFIG, 1, "any",
|
||||
1, LYS_ANYDATA, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:any\": null}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Expecting JSON name/object but anydata \"any\" is represented in input data as name/null.", NULL, 1);
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_NULL, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_anyxml(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
data = "{\"a:axml\":\"some-value in string\"}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":\"\"}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":55}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":false}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":null}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":[null,true,false]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":[null,true,{\"name\":[25,40, false]}]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* same as anydata tests */
|
||||
data = "{\"a:axml\":{\"x:element1\":{\"element2\":\"/a:some/a:path\",\"list\":[{},{\"key\":\"a\"}]}}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:axml\":{}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_STATUS_CURR | LYS_CONFIG_W, 1, "axml", 1, LYS_ANYXML, 0, 0, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_list(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree, *iter;
|
||||
struct lyd_node_inner *list;
|
||||
struct lyd_node_term *leaf;
|
||||
|
||||
/* check hashes */
|
||||
data = "{\"a:l1\":[{\"a\":\"one\",\"b\":\"one\",\"c\":1}]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "l1",
|
||||
1, LYS_LIST, 0, 0, NULL, 0);
|
||||
list = (struct lyd_node_inner *)tree;
|
||||
LY_LIST_FOR(list->child, iter) {
|
||||
assert_int_not_equal(0, iter->hash);
|
||||
}
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* accept empty */
|
||||
data = "{\"a:l1\":[]}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
|
||||
/* missing keys */
|
||||
PARSER_CHECK_ERROR("{ \"a:l1\": [ {\"c\" : 1, \"b\" : \"b\"}]}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"List instance is missing its key \"a\".", "/a:l1[b='b'][c='1']", 1);
|
||||
|
||||
PARSER_CHECK_ERROR("{ \"a:l1\": [ {\"a\" : \"a\"}]}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"List instance is missing its key \"b\".", "/a:l1[a='a']", 1);
|
||||
|
||||
PARSER_CHECK_ERROR("{ \"a:l1\": [ {\"b\" : \"b\", \"a\" : \"a\"}]}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"List instance is missing its key \"c\".", "/a:l1[a='a'][b='b']", 1);
|
||||
|
||||
/* key duplicate */
|
||||
PARSER_CHECK_ERROR("{ \"a:l1\": [ {\"c\" : 1, \"b\" : \"b\", \"a\" : \"a\", \"c\" : 1}]}", 0, LYD_VALIDATE_PRESENT,
|
||||
tree, LY_EVALID, "Duplicate instance of \"c\".", "/a:l1[a='a'][b='b'][c='1'][c='1']/c", 1);
|
||||
|
||||
/* keys order, in contrast to XML, JSON accepts keys in any order even in strict mode */
|
||||
CHECK_PARSE_LYD("{ \"a:l1\": [ {\"d\" : \"d\", \"a\" : \"a\", \"c\" : 1, \"b\" : \"b\"}]}", 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "l1",
|
||||
1, LYS_LIST, 0, 0, NULL, 0);
|
||||
list = (struct lyd_node_inner *)tree;
|
||||
assert_non_null(leaf = (struct lyd_node_term *)list->child);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "a", 1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "b", 1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "c", 1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "d", 1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
CHECK_LOG_CTX(NULL, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS,
|
||||
"{\"a:l1\":[{\"a\":\"a\",\"b\":\"b\",\"c\":1,\"d\":\"d\"}]}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
CHECK_PARSE_LYD("{\"a:l1\":[{\"c\":1,\"b\":\"b\",\"a\":\"a\"}]}", LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_ORDBY_SYSTEM, 1, "l1",
|
||||
1, LYS_LIST, 0, 0, NULL, 0);
|
||||
list = (struct lyd_node_inner *)tree;
|
||||
assert_non_null(leaf = (struct lyd_node_term *)list->child);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "a",
|
||||
1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "b",
|
||||
1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_non_null(leaf = (struct lyd_node_term *)leaf->next);
|
||||
CHECK_LYSC_NODE(leaf->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_KEY, 1, "c",
|
||||
1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
CHECK_LOG_CTX(NULL, NULL, 0);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS,
|
||||
"{\"a:l1\":[{\"a\":\"a\",\"b\":\"b\",\"c\":1}]}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* skip unknown nested nodes */
|
||||
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":3,\"counters\":{\"count1\":\"c1\",\"count2\":\"c2\"}}]}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":3}]}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:cp\":{\"@\":{\"a:hint\":1}}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_PRESENCE, 1, "cp",
|
||||
1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
CHECK_LYD_META(tree->meta, 1, "hint", 0, 1, INT8, "1", 1);
|
||||
assert_null(tree->meta->next);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_container(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
struct lyd_node_inner *cont;
|
||||
|
||||
CHECK_PARSE_LYD("{\"a:c\":{}}", 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "c",
|
||||
1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
cont = (struct lyd_node_inner *)tree;
|
||||
assert_true(cont->flags & LYD_DEFAULT);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:cp\":{}}";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_PRESENCE, 1, "cp",
|
||||
1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
cont = (struct lyd_node_inner *)tree;
|
||||
assert_false(cont->flags & LYD_DEFAULT);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* skip container */
|
||||
CHECK_PARSE_LYD("{\"a:unknown\":{\"a\":\"val\",\"b\":5}}", 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:c\": null}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Expecting JSON name/object but container \"c\" is represented in input data as name/null.", NULL, 1);
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_JSON_NULL, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_null(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_opaq(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
/* invalid value, no flags */
|
||||
data = "{\"a:foo3\":[null]}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Invalid non-number-encoded uint32 value \"\".", "/a:foo3", 1);
|
||||
|
||||
/* opaq flag */
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0, LY_VALUE_JSON, "foo3", 0, 0, NULL, 0, "");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* special chars */
|
||||
data = "{\"a:foo3\":\"ab\\\"\\\\\\r\\t\"}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* wrong encoding */
|
||||
data = "{\"a:foo3\":\"25\"}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0, LY_VALUE_JSON, "foo3", 0, 0, NULL, 0, "25");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:foo4\":25}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0, LY_VALUE_JSON, "foo4", 0, 0, NULL, 0, "25");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* missing key, no flags */
|
||||
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"d\":\"val_d\"}]}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"List instance is missing its key \"c\".", "/a:l1[a='val_a'][b='val_b']", 1);
|
||||
|
||||
/* opaq flag */
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0x1, LY_VALUE_JSON, "l1", 0, 0, NULL, 0, "");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* invalid key, no flags */
|
||||
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"Invalid non-number-encoded int16 value \"val_c\".", "/a:l1[a='val_a'][b='val_b']/c", 1);
|
||||
|
||||
/* opaq flag */
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0x1, LY_VALUE_JSON, "l1", 0, 0, NULL, 0, "");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\",\"c\":{\"val\":\"val_c\"}}]}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0x1, LY_VALUE_JSON, "l1", 0, 0, NULL, 0, "");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:l1\":[{\"a\":\"val_a\",\"b\":\"val_b\"}]}";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)tree, 0, 0x1, LY_VALUE_JSON, "l1", 0, 0, NULL, 0, "");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* invalid metadata */
|
||||
data = "{\"@a:foo\":\"str\",\"@a:foo3\":1,\"a:foo3\":2}";
|
||||
PARSER_CHECK_ERROR(data, 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID, "Unknown module of node \"@a:foo\".", "/", 0);
|
||||
CHECK_LOG_CTX("Missing JSON data instance to be coupled with @a:foo metadata.", "/@a:foo", 1);
|
||||
|
||||
/* empty name */
|
||||
PARSER_CHECK_ERROR("{\"@a:foo\":{\"\":0}}", 0, LYD_VALIDATE_PRESENT, tree, LY_EVALID,
|
||||
"JSON object member name cannot be a zero-length string.", "/@a:foo", 1);
|
||||
|
||||
/* opaque data tree format print */
|
||||
data =
|
||||
"{\n"
|
||||
" \"ietf-netconf-nmda:get-data\": {\n"
|
||||
" \"data\": {\n"
|
||||
" \"ietf-keystore:keystore\": {\n"
|
||||
" \"asymmetric-keys\": {\n"
|
||||
" \"asymmetric-key\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"genkey\",\n"
|
||||
" \"algorithm\": \"rsa2048\"\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" },\n"
|
||||
" \"ietf-netconf-server:netconf-server\": {\n"
|
||||
" \"listen\": {\n"
|
||||
" \"idle-timeout\": 3600,\n"
|
||||
" \"endpoint\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"default-ssh\",\n"
|
||||
" \"ssh\": {\n"
|
||||
" \"tcp-server-parameters\": {\n"
|
||||
" \"local-address\": \"0.0.0.0\",\n"
|
||||
" \"local-port\": 830\n"
|
||||
" },\n"
|
||||
" \"ssh-server-parameters\": {\n"
|
||||
" \"server-identity\": {\n"
|
||||
" \"host-key\": [\n"
|
||||
" {\n"
|
||||
" \"name\": \"default-key\",\n"
|
||||
" \"public-key\": {\n"
|
||||
" \"keystore-reference\": \"genkey\"\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" },\n"
|
||||
" \"client-authentication\": {\n"
|
||||
" \"supported-authentication-methods\": {\n"
|
||||
" \"publickey\": [null],\n"
|
||||
" \"passsword\": [null],\n"
|
||||
" \"other\": [\n"
|
||||
" \"interactive\",\n"
|
||||
" \"gssapi\"\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
CHECK_PARSE_LYD(data, LYD_PARSE_OPAQ | LYD_PARSE_ONLY, 0, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_rpc(void **state)
|
||||
{
|
||||
const char *data;
|
||||
char *str;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *op;
|
||||
const struct lyd_node *node;
|
||||
const char *dsc = "Edit data in an NMDA datastore.\n"
|
||||
"\n"
|
||||
"If an error condition occurs such that an error severity\n"
|
||||
"<rpc-error> element is generated, the server will stop\n"
|
||||
"processing the <edit-data> operation and restore the\n"
|
||||
"specified configuration to its complete state at\n"
|
||||
"the start of this <edit-data> operation.";
|
||||
|
||||
assert_non_null((ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-nmda", "2019-01-07", NULL)));
|
||||
|
||||
data = "{\"ietf-netconf-nmda:edit-data\":{"
|
||||
"\"datastore\":\"ietf-datastores:running\","
|
||||
"\"config\":{\"a:cp\":{\"z\":[null],\"@z\":{\"ietf-netconf:operation\":\"replace\"}},"
|
||||
"\"a:l1\":[{\"@\":{\"ietf-netconf:operation\":\"replace\"},\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}"
|
||||
"}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_RPC_YANG, &tree, &op));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_non_null(op);
|
||||
|
||||
CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, dsc, 0, LYS_STATUS_CURR,
|
||||
1, 0, 0, 1, "edit-data", LYS_RPC,
|
||||
0, 0, 0, 0, 0, NULL, 0);
|
||||
|
||||
node = tree;
|
||||
CHECK_LYSC_ACTION((struct lysc_node_action *)node->schema, dsc, 0, LYS_STATUS_CURR,
|
||||
1, 0, 0, 1, "edit-data", LYS_RPC,
|
||||
0, 0, 0, 0, 0, NULL, 0);
|
||||
node = lyd_child(node)->next;
|
||||
CHECK_LYSC_NODE(node->schema, "Inline config content.", 0, LYS_STATUS_CURR | LYS_IS_INPUT, 1, "config",
|
||||
0, LYS_ANYDATA, 1, 0, NULL, 0);
|
||||
|
||||
node = ((struct lyd_node_any *)node)->value.tree;
|
||||
CHECK_LYSC_NODE(node->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR | LYS_PRESENCE, 1, "cp",
|
||||
1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
node = lyd_child(node);
|
||||
/* z has no value */
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)node, 0x1, 0, LY_VALUE_JSON, "z", 0, 0, NULL, 0, "");
|
||||
node = node->parent->next;
|
||||
/* l1 key c has invalid value so it is at the end */
|
||||
CHECK_LYD_NODE_OPAQ((struct lyd_node_opaq *)node, 0x1, 0x1, LY_VALUE_JSON, "l1", 0, 0, NULL, 0, "");
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* append to parent */
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(NULL, UTEST_LYCTX, "/a:r1", NULL, 0, &op));
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory("{\"l1\": \"some str\", \"l2\": \"some other str\"}", &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, op, in, LYD_JSON, LYD_TYPE_RPC_YANG, &tree, NULL));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&str, op, LYD_JSON, LYD_PRINT_WITHSIBLINGS | LYD_PRINT_SHRINK));
|
||||
lyd_free_tree(op);
|
||||
assert_string_equal(str, "{\"a:r1\":{\"l1\":\"some str\",\"l2\":\"some other str\"}}");
|
||||
free(str);
|
||||
}
|
||||
|
||||
static void
|
||||
test_action(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *op;
|
||||
|
||||
data = "{\"a:c\":{\"act\":{\"al\":\"value\"}}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_RPC_YANG, &tree, &op));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_non_null(op);
|
||||
CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
|
||||
1, 0, 0, 1, "act", LYS_ACTION,
|
||||
1, 0, 0, 1, 0, NULL, 0);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* wrong namespace, element name, whatever... */
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void
|
||||
test_notification(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *ntf;
|
||||
|
||||
data = "{\"a:c\":{\"n1\":{\"nl\":\"value\"}}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_YANG, &tree, &ntf));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_non_null(ntf);
|
||||
CHECK_LYSC_NOTIF((struct lysc_node_notif *)ntf->schema, 1, NULL, 0, 0x4, 1, 0, "n1", 1, 0, NULL, 0);
|
||||
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "c", 1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "{\"a:n2\":{}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_YANG, &tree, &ntf));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_non_null(ntf);
|
||||
CHECK_LYSC_NOTIF((struct lysc_node_notif *)ntf->schema, 0, NULL, 0, 0x4, 1, 0, "n2", 0, 0, NULL, 0);
|
||||
|
||||
assert_non_null(tree);
|
||||
assert_ptr_equal(ntf, tree);
|
||||
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* wrong namespace, element name, whatever... */
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void
|
||||
test_reply(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *op;
|
||||
const struct lyd_node *node;
|
||||
|
||||
data = "{\"a:c\":{\"act\":{\"al\":25}}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_REPLY_YANG, &tree, &op));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
assert_non_null(op);
|
||||
CHECK_LYSC_ACTION((struct lysc_node_action *)op->schema, NULL, 0, LYS_STATUS_CURR,
|
||||
1, 0, 0, 1, "act", LYS_ACTION,
|
||||
1, 0, 0, 1, 0, NULL, 0);
|
||||
node = lyd_child(op);
|
||||
CHECK_LYSC_NODE(node->schema, NULL, 0, LYS_STATUS_CURR | LYS_IS_OUTPUT, 1, "al", 0, LYS_LEAF, 1, 0, NULL, 0);
|
||||
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "c", 1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
|
||||
/* TODO print only rpc-reply node and then output subtree */
|
||||
CHECK_LYD_STRING(lyd_child(op), LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{\"a:al\":25}");
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, "{\"a:c\":{\"act\":{\"al\":25}}}");
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* wrong namespace, element name, whatever... */
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
static void
|
||||
test_restconf_rpc(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *envp;
|
||||
|
||||
assert_non_null((ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-nmda", "2019-01-07", NULL)));
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(NULL, UTEST_LYCTX, "/ietf-netconf-nmda:edit-data", NULL, 0, &tree));
|
||||
|
||||
data = "{\"ietf-netconf-nmda:input\":{"
|
||||
"\"datastore\":\"ietf-datastores:running\","
|
||||
"\"config\":{\"a:cp\":{\"z\":[null],\"@z\":{\"ietf-netconf:operation\":\"replace\"}},"
|
||||
"\"a:l1\":[{\"@\":{\"ietf-netconf:operation\":\"replace\"},\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}"
|
||||
"}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, tree, in, LYD_JSON, LYD_TYPE_RPC_RESTCONF, &envp, NULL));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
/* the same just connected to the edit-data RPC */
|
||||
data = "{\"ietf-netconf-nmda:edit-data\":{"
|
||||
"\"datastore\":\"ietf-datastores:running\","
|
||||
"\"config\":{\"a:cp\":{\"z\":[null],\"@z\":{\"ietf-netconf:operation\":\"replace\"}},"
|
||||
"\"a:l1\":[{\"@\":{\"ietf-netconf:operation\":\"replace\"},\"a\":\"val_a\",\"b\":\"val_b\",\"c\":\"val_c\"}]}"
|
||||
"}}";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
lyd_free_all(envp);
|
||||
}
|
||||
|
||||
static void
|
||||
test_restconf_notification(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *ntf;
|
||||
|
||||
data = "{\"ietf-restconf:notification\":{\"eventTime\":\"2013-12-21T00:01:00Z\",\"a:c\":{\"n1\":{\"nl\":\"value\"}}}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, &tree, &ntf));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
/* envelopes separately */
|
||||
data = "{\"ietf-restconf:notification\":{\"eventTime\":\"2013-12-21T00:01:00Z\"}}";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
/* notification with the parent node */
|
||||
data = "{\"a:c\":{\"n1\":{\"nl\":\"value\"}}}";
|
||||
CHECK_LYD_STRING(lyd_parent(ntf), LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
lyd_free_all(tree);
|
||||
lyd_free_all(ntf);
|
||||
|
||||
/* wrong order */
|
||||
data = "{\"ietf-restconf:notification\":{\"a:n2\":{},\"eventTime\":\"2013-12-21T00:01:00Z\"}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, &tree, &ntf));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
lyd_free_all(tree);
|
||||
lyd_free_all(ntf);
|
||||
|
||||
/* unknown notification */
|
||||
data = "{\"ietf-restconf:notification\":{\"eventTime\":\"2013-12-21T00:01:00Z\",\"invalid:n2\":{}}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_EVALID, lyd_parse_op(UTEST_LYCTX, NULL, in, LYD_JSON, LYD_TYPE_NOTIF_RESTCONF, &tree, &ntf));
|
||||
UTEST_LOG_CTX_CLEAN;
|
||||
ly_in_free(in, 0);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_restconf_reply(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct ly_in *in;
|
||||
struct lyd_node *tree, *envp;
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(NULL, UTEST_LYCTX, "/a:c/act", NULL, 0, &tree));
|
||||
|
||||
data = "{\"a:output\":{\"al\":25}}";
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(data, &in));
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_op(UTEST_LYCTX, lyd_child(tree), in, LYD_JSON, LYD_TYPE_REPLY_RESTCONF, &envp, NULL));
|
||||
ly_in_free(in, 0);
|
||||
|
||||
/* connected to the RPC with the parent */
|
||||
data = "{\"a:c\":{\"act\":{\"al\":25}}}";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
lyd_free_all(envp);
|
||||
}
|
||||
|
||||
static void
|
||||
test_metadata(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
/* invalid metadata value */
|
||||
data = "{\"a:c\":{\"x\":\"xval\",\"@x\":{\"a:hint\":\"value\"}}}";
|
||||
assert_int_equal(LY_EVALID, lyd_parse_data_mem(_UC->ctx, data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
assert_null(tree);
|
||||
CHECK_LOG_CTX("Invalid non-number-encoded int8 value \"value\".", "/a:c/x/@a:hint", 1);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_leaf, setup),
|
||||
UTEST(test_leaflist, setup),
|
||||
UTEST(test_anydata, setup),
|
||||
UTEST(test_anyxml, setup),
|
||||
UTEST(test_list, setup),
|
||||
UTEST(test_container, setup),
|
||||
UTEST(test_opaq, setup),
|
||||
UTEST(test_rpc, setup),
|
||||
UTEST(test_action, setup),
|
||||
UTEST(test_notification, setup),
|
||||
UTEST(test_reply, setup),
|
||||
UTEST(test_restconf_rpc, setup),
|
||||
UTEST(test_restconf_notification, setup),
|
||||
UTEST(test_restconf_reply, setup),
|
||||
UTEST(test_metadata, setup),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
1034
tests/utests/data/test_parser_xml.c
Normal file
1034
tests/utests/data/test_parser_xml.c
Normal file
File diff suppressed because it is too large
Load diff
83
tests/utests/data/test_printer_json.c
Normal file
83
tests/utests/data/test_printer_json.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
* @file test_printer_json.c
|
||||
* @author: Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief unit tests for functions from printer_yang.c
|
||||
*
|
||||
* Copyright (c) 2019-2020 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"
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
const char *schema1 = "module schema1 {namespace urn:tests:schema1;prefix schema1;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"anydata data;"
|
||||
"}";
|
||||
const char *schema2 = "module schema2 {namespace urn:tests:schema2;prefix s2;yang-version 1.1;"
|
||||
" container a {"
|
||||
" container b {"
|
||||
" leaf c {"
|
||||
" type string;"
|
||||
" default \"dflt\";"
|
||||
" }"
|
||||
" }"
|
||||
" }"
|
||||
"}";
|
||||
|
||||
UTEST_SETUP;
|
||||
UTEST_ADD_MODULE(schema1, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_container_presence(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
char *buffer = NULL;
|
||||
const char *data = "{\"schema1:data\":{\"cont1\":{}}}";
|
||||
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&buffer, tree, LYD_JSON, LYD_PRINT_SHRINK));
|
||||
CHECK_STRING(buffer, data);
|
||||
free(buffer);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_empty_container_wd_trim(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
char *buffer = NULL;
|
||||
const char *data = "{\"schema2:a\":{\"b\":{\"c\":\"dflt\"}}}";
|
||||
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&buffer, tree, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WD_TRIM));
|
||||
CHECK_STRING(buffer, "{}");
|
||||
free(buffer);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_print_mem(&buffer, tree, LYD_JSON, LYD_PRINT_SHRINK | LYD_PRINT_WD_TRIM | LYD_PRINT_KEEPEMPTYCONT));
|
||||
CHECK_STRING(buffer, "{\"schema2:a\":{\"b\":{}}}");
|
||||
free(buffer);
|
||||
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_container_presence, setup),
|
||||
UTEST(test_empty_container_wd_trim, setup),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
344
tests/utests/data/test_printer_xml.c
Normal file
344
tests/utests/data/test_printer_xml.c
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* @file test_printer_xml.c
|
||||
* @author: Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief unit tests for functions from printer_yang.c
|
||||
*
|
||||
* Copyright (c) 2019-2020 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 <string.h>
|
||||
|
||||
#include "context.h"
|
||||
#include "out.h"
|
||||
#include "parser_data.h"
|
||||
#include "printer_data.h"
|
||||
#include "tests_config.h"
|
||||
#include "tree_schema.h"
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
const char *schema_defs = "module defs {namespace urn:tests:defs;prefix d;yang-version 1.1;"
|
||||
"identity crypto-alg; identity interface-type; identity ethernet {base interface-type;} identity fast-ethernet {base ethernet;}}";
|
||||
const char *schema_types = "module types {namespace urn:tests:types;prefix t;yang-version 1.1; import defs {prefix defs;}"
|
||||
"feature f; identity gigabit-ethernet { base defs:ethernet;}"
|
||||
"container cont {leaf leaftarget {type empty;}"
|
||||
" list listtarget {key id; max-elements 5;leaf id {type uint8;} leaf value {type string;}"
|
||||
" action test {input {leaf a {type string;}} output {leaf b {type string;}}}}"
|
||||
" leaf-list leaflisttarget {type uint8; max-elements 5;}}"
|
||||
"list list {key id; leaf id {type string;} leaf value {type string;} leaf-list targets {type string;}}"
|
||||
"list list2 {key \"id value\"; leaf id {type string;} leaf value {type string;}}"
|
||||
"list list_inst {key id; leaf id {type instance-identifier {require-instance true;}} leaf value {type string;}}"
|
||||
"list list_ident {key id; leaf id {type identityref {base defs:interface-type;}} leaf value {type string;}}"
|
||||
"leaf-list leaflisttarget {type string;}"
|
||||
"leaf binary {type binary {length 5 {error-message \"This base64 value must be of length 5.\";}}}"
|
||||
"leaf binary-norestr {type binary;}"
|
||||
"leaf int8 {type int8 {range 10..20;}}"
|
||||
"leaf uint8 {type uint8 {range 150..200;}}"
|
||||
"leaf int16 {type int16 {range -20..-10;}}"
|
||||
"leaf uint16 {type uint16 {range 150..200;}}"
|
||||
"leaf int32 {type int32;}"
|
||||
"leaf uint32 {type uint32;}"
|
||||
"leaf int64 {type int64;}"
|
||||
"leaf uint64 {type uint64;}"
|
||||
"leaf bits {type bits {bit zero; bit one {if-feature f;} bit two;}}"
|
||||
"leaf enums {type enumeration {enum white; enum yellow {if-feature f;}}}"
|
||||
"leaf dec64 {type decimal64 {fraction-digits 1; range 1.5..10;}}"
|
||||
"leaf dec64-norestr {type decimal64 {fraction-digits 18;}}"
|
||||
"leaf str {type string {length 8..10; pattern '[a-z ]*';}}"
|
||||
"leaf str-norestr {type string;}"
|
||||
"leaf bool {type boolean;}"
|
||||
"leaf empty {type empty;}"
|
||||
"leaf ident {type identityref {base defs:interface-type;}}"
|
||||
"leaf inst {type instance-identifier {require-instance true;}}"
|
||||
"leaf inst-noreq {type instance-identifier {require-instance false;}}"
|
||||
"leaf lref {type leafref {path /leaflisttarget; require-instance true;}}"
|
||||
"leaf lref2 {type leafref {path \"../list[id = current()/../str-norestr]/targets\"; require-instance true;}}"
|
||||
"leaf un1 {type union {"
|
||||
" type leafref {path /int8; require-instance true;}"
|
||||
" type union { type identityref {base defs:interface-type;} type instance-identifier {require-instance true;} }"
|
||||
" type string {length 1..20;}}}"
|
||||
"anydata any;"
|
||||
"rpc sum {input {leaf x {type uint8;} leaf y {type uint8;}} output {leaf result {type uint16;}}}}";
|
||||
const char *schema_defaults =
|
||||
"module defaults {\n"
|
||||
" namespace \"urn:defaults\";\n"
|
||||
" prefix d;\n"
|
||||
" leaf a {\n"
|
||||
" type union {\n"
|
||||
" type instance-identifier;\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" default \"/d:b\";\n"
|
||||
" }\n"
|
||||
" leaf b {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
" leaf c {\n"
|
||||
" type string;\n"
|
||||
" }\n"
|
||||
"}";
|
||||
|
||||
UTEST_SETUP;
|
||||
|
||||
UTEST_ADD_MODULE(schema_defs, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema_types, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema_defaults, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CHECK_PARSE_LYD(INPUT, PARSE_OPTION, VALIDATE_OPTION, TREE) \
|
||||
CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, PARSE_OPTION, VALIDATE_OPTION, LY_SUCCESS, TREE)
|
||||
|
||||
#define CHECK_LYD_STRING(IN_MODEL, PRINT_OPTION, TEXT) \
|
||||
CHECK_LYD_STRING_PARAM(IN_MODEL, TEXT, LYD_XML, PRINT_OPTION)
|
||||
|
||||
static void
|
||||
test_anydata(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
const char *data;
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\"><somexml xmlns:x=\"url:x\" xmlns=\"example.com\"><x:x/></somexml></any>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
/* canonized */
|
||||
data = "<any xmlns=\"urn:tests:types\"><somexml xmlns=\"example.com\"><x xmlns=\"url:x\"/></somexml></any>";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\"/>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\">\n"
|
||||
" <cont>\n"
|
||||
" <defs:elem1 xmlns:defs=\"urn:tests:defs\">\n"
|
||||
" <elem2 xmlns:defaults=\"urn:defaults\" defs:attr1=\"defaults:val\" attr2=\"/defaults:node/defs:node2\">\n"
|
||||
" </elem2>\n"
|
||||
" </defs:elem1>\n"
|
||||
" </cont>\n"
|
||||
"</any>\n";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_non_null(tree);
|
||||
tree = tree->next;
|
||||
/* cont should be normally parsed */
|
||||
CHECK_LYSC_NODE(tree->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "any", 0, LYS_ANYDATA, 0, 0, NULL, 0);
|
||||
CHECK_LYD_NODE_ANY((struct lyd_node_any *)tree, 0, 0, 0, LYD_ANYDATA_DATATREE);
|
||||
struct lyd_node *tree_tmp = ((struct lyd_node_any *)tree)->value.tree;
|
||||
|
||||
CHECK_LYSC_NODE(tree_tmp->schema, NULL, 0, LYS_CONFIG_W | LYS_STATUS_CURR, 1, "cont", 1, LYS_CONTAINER, 0, 0, NULL, 0);
|
||||
/* but its children not */
|
||||
assert_null(((struct lyd_node_inner *)tree_tmp)->child->schema);
|
||||
/* canonized */
|
||||
data =
|
||||
"<any xmlns=\"urn:tests:types\">\n"
|
||||
" <cont>\n"
|
||||
" <elem1 xmlns=\"urn:tests:defs\">\n"
|
||||
" <elem2 xmlns=\"urn:tests:types\" xmlns:defs=\"urn:tests:defs\" xmlns:defaults=\"urn:defaults\" "
|
||||
"defs:attr1=\"defaults:val\" attr2=\"/defaults:node/defs:node2\">\n"
|
||||
" </elem2>\n"
|
||||
" </elem1>\n"
|
||||
" </cont>\n"
|
||||
"</any>\n";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\">\n"
|
||||
" <ahoj attr=\"<test\">\n"
|
||||
" ahoj jak se vede < how are you"
|
||||
" </ahoj>\n"
|
||||
"</any>\n";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\">\n"
|
||||
" <leaflisttarget> ahoj </leaflisttarget>\n"
|
||||
" <leaflisttarget> nazdar </leaflisttarget>\n"
|
||||
" <leaflisttarget> Čau </leaflisttarget>\n"
|
||||
"</any>\n";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\">\n"
|
||||
" <cont2/>\n"
|
||||
"</any>\n";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:types\">\n"
|
||||
" <cont>\n"
|
||||
" < how are you"
|
||||
" </cont>\n"
|
||||
"</any>\n";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_defaults(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
const char *data;
|
||||
const char *data_trim;
|
||||
const char *data_all;
|
||||
const char *data_all_tag;
|
||||
const char *data_impl_tag;
|
||||
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_set_searchdir(UTEST_LYCTX, TESTS_DIR_MODULES_YANG));
|
||||
assert_non_null(ly_ctx_load_module(UTEST_LYCTX, "ietf-netconf-with-defaults", "2011-06-01", NULL));
|
||||
|
||||
/* standard default value */
|
||||
data = "<c xmlns=\"urn:defaults\">aa</c>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_TRIM | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
data = "<a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><c xmlns=\"urn:defaults\">aa</c>";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
data = "<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
|
||||
" ncwd:default=\"true\" xmlns:d=\"urn:defaults\">/d:b</a>"
|
||||
"<c xmlns=\"urn:defaults\">aa</c>";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
|
||||
data = "<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
|
||||
" ncwd:default=\"true\" xmlns:d=\"urn:defaults\">/d:b</a>"
|
||||
"<c xmlns=\"urn:defaults\">aa</c>";
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* string value equal to the default but default is an unresolved instance-identifier, so they are not considered equal */
|
||||
data = "<a xmlns=\"urn:defaults\">/d:b</a><c xmlns=\"urn:defaults\">aa</c>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_TRIM | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data);
|
||||
lyd_free_all(tree);
|
||||
|
||||
/* instance-identifier value equal to the default, should be considered equal */
|
||||
data = "<a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b><c xmlns=\"urn:defaults\">aa</c>";
|
||||
data_trim = "<b xmlns=\"urn:defaults\">val</b><c xmlns=\"urn:defaults\">aa</c>";
|
||||
data_all = "<a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b><c xmlns=\"urn:defaults\">aa</c>";
|
||||
data_all_tag = "<a xmlns=\"urn:defaults\" xmlns:ncwd=\"urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults\""
|
||||
" ncwd:default=\"true\" xmlns:d=\"urn:defaults\">/d:b</a>"
|
||||
"<b xmlns=\"urn:defaults\">val</b>"
|
||||
"<c xmlns=\"urn:defaults\">aa</c>";
|
||||
data_impl_tag = "<a xmlns=\"urn:defaults\" xmlns:d=\"urn:defaults\">/d:b</a><b xmlns=\"urn:defaults\">val</b><c xmlns=\"urn:defaults\">aa</c>";
|
||||
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_TRIM | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data_trim);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data_all);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_ALL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data_all_tag);
|
||||
CHECK_LYD_STRING(tree, LYD_PRINT_WD_IMPL_TAG | LYD_PRINT_SHRINK | LYD_PRINT_WITHSIBLINGS, data_impl_tag);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static void
|
||||
test_rpc(void **state)
|
||||
{
|
||||
struct state_s *s = (struct state_s *)(*state);
|
||||
struct lyd_node *tree1;
|
||||
struct lyd_node *tree2;
|
||||
const struct lyd_node **trees;
|
||||
const char *request;
|
||||
const char *reply, *result;
|
||||
char *printed;
|
||||
ssize_t len;
|
||||
struct ly_out *out;
|
||||
|
||||
s->func = test_rpc;
|
||||
assert_non_null(out = ly_out_new_memory(&printed, 0));
|
||||
|
||||
request = "<sum xmlns=\"urn:tests:types\"><x>10</x><y>20</y></sum>";
|
||||
reply = "<result xmlns=\"urn:tests:types\">30</result>";
|
||||
result = "<sum xmlns=\"urn:tests:types\"><result>30</result></sum>";
|
||||
assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
|
||||
assert_true((len = lyd_print_tree(out, tree1, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, request);
|
||||
ly_out_reset(out);
|
||||
assert_non_null(trees = lyd_trees_new(1, tree1));
|
||||
assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
|
||||
assert_true((len = lyd_print_tree(out, tree2, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, result);
|
||||
ly_out_reset(out);
|
||||
lyd_trees_free(trees, 0);
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* no arguments */
|
||||
request = "<sum xmlns=\"urn:tests:types\"/>";
|
||||
reply = "";
|
||||
result = "<sum xmlns=\"urn:tests:types\"/>";
|
||||
assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
|
||||
assert_true((len = lyd_print_tree(out, tree1, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, request);
|
||||
ly_out_reset(out);
|
||||
assert_non_null(trees = lyd_trees_new(1, tree1));
|
||||
assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
|
||||
assert_true((len = lyd_print_tree(out, tree2, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, result);
|
||||
ly_out_reset(out);
|
||||
lyd_trees_free(trees, 0);
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* action
|
||||
* "container cont {leaf leaftarget {type empty;}"
|
||||
"list listtarget {key id; max-elements 5;leaf id {type uint8;} leaf value {type string;}"
|
||||
"action test {input {leaf a {type string;}} output {leaf b {type string;}}}}"
|
||||
"leaf-list leaflisttarget {type uint8; max-elements 5;}}"
|
||||
*/
|
||||
request = "<cont xmlns=\"urn:tests:types\"><listtarget><id>10</id><test><a>test</a></test></listtarget></cont>";
|
||||
reply = "<b xmlns=\"urn:tests:types\">test-reply</b>";
|
||||
result = "<cont xmlns=\"urn:tests:types\"><listtarget><id>10</id><test><b>test-reply</b></test></listtarget></cont>";
|
||||
assert_non_null(tree1 = lyd_parse_mem(s->ctx, request, LYD_XML, LYD_OPT_RPC, NULL));
|
||||
assert_true((len = lyd_print_tree(out, tree1, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, request);
|
||||
ly_out_reset(out);
|
||||
assert_non_null(trees = lyd_trees_new(1, tree1));
|
||||
assert_non_null(tree2 = lyd_parse_mem(s->ctx, reply, LYD_XML, LYD_OPT_RPCREPLY, trees));
|
||||
assert_true((len = lyd_print_tree(out, tree2, LYD_XML, LYD_PRINT_SHRINK)) >= 0);
|
||||
assert_int_equal(len, strlen(printed));
|
||||
assert_string_equal(printed, result);
|
||||
ly_out_reset(out);
|
||||
lyd_trees_free(trees, 0);
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
ly_out_free(out, NULL, 1);
|
||||
s->func = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_anydata, setup),
|
||||
UTEST(test_defaults, setup),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
822
tests/utests/data/test_tree_data.c
Normal file
822
tests/utests/data/test_tree_data.c
Normal file
|
@ -0,0 +1,822 @@
|
|||
/**
|
||||
* @file test_tree_data.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @brief unit tests for functions from tree_data.c
|
||||
*
|
||||
* Copyright (c) 2018-2023 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"
|
||||
#include "ly_common.h"
|
||||
#include "path.h"
|
||||
#include "xpath.h"
|
||||
|
||||
static int
|
||||
setup(void **state)
|
||||
{
|
||||
const char *schema1 = "module a {namespace urn:tests:a;prefix a;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"leaf bar {type string;}"
|
||||
"list l1 { key \"a b\"; leaf a {type string;} leaf b {type string;} leaf c {type string;}}"
|
||||
"leaf foo { type string;}"
|
||||
"leaf-list ll { type string;}"
|
||||
"container c {leaf-list x {type string;}}"
|
||||
"anydata any {config false;}"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;} leaf-list d {type string;}}"
|
||||
"}}";
|
||||
|
||||
const char *schema2 = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;}}}"
|
||||
"anydata any {config false;}"
|
||||
"}";
|
||||
|
||||
const char *schema3 = "module c {yang-version 1.1; namespace \"http://example.com/main\";prefix m;"
|
||||
"import \"ietf-inet-types\" {prefix inet;}"
|
||||
"typedef optional-ip-address {type union {"
|
||||
" type inet:ip-address;"
|
||||
" type string;"
|
||||
"}}"
|
||||
"container cont {"
|
||||
" list nexthop {min-elements 1; key \"gateway\";"
|
||||
" leaf gateway {type optional-ip-address;}"
|
||||
" }"
|
||||
" leaf-list pref {type inet:ipv6-prefix;}"
|
||||
"}}";
|
||||
|
||||
UTEST_SETUP;
|
||||
|
||||
UTEST_ADD_MODULE(schema1, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema2, LYS_IN_YANG, NULL, NULL);
|
||||
UTEST_ADD_MODULE(schema3, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define CHECK_PARSE_LYD(INPUT, PARSE_OPTION, VALIDATE_OPTION, TREE) \
|
||||
CHECK_PARSE_LYD_PARAM(INPUT, LYD_XML, PARSE_OPTION, VALIDATE_OPTION, LY_SUCCESS, TREE)
|
||||
|
||||
#define CHECK_PARSE_LYD_PARAM_CTX(CTX, INPUT, PARSE_OPTION, OUT_NODE) \
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(CTX, INPUT, LYD_XML, PARSE_OPTION, LYD_VALIDATE_PRESENT, &OUT_NODE)); \
|
||||
assert_non_null(OUT_NODE);
|
||||
|
||||
#define RECREATE_CTX_WITH_MODULE(CTX, MODULE) \
|
||||
ly_ctx_destroy(CTX); \
|
||||
assert_int_equal(LY_SUCCESS, ly_ctx_new(NULL, 0, &CTX)); \
|
||||
assert_int_equal(LY_SUCCESS, ly_in_new_memory(MODULE, &_UC->in)); \
|
||||
assert_int_equal(LY_SUCCESS, lys_parse(CTX, _UC->in, LYS_IN_YANG, NULL, NULL)); \
|
||||
ly_in_free(_UC->in, 0);
|
||||
|
||||
static void
|
||||
test_compare(void **state)
|
||||
{
|
||||
struct lyd_node *tree1, *tree2;
|
||||
const char *data1;
|
||||
const char *data2;
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(NULL, NULL, 0));
|
||||
|
||||
data1 = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>x</c></l1>";
|
||||
data2 = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>y</c></l1>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(((struct lyd_node_inner *)tree1)->child, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<l2 xmlns=\"urn:tests:a\"><c><x>a</x></c></l2><l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1->next, tree2->next, LYD_COMPARE_FULL_RECURSION));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next->next, tree2->next, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<ll xmlns=\"urn:tests:a\">a</ll><ll xmlns=\"urn:tests:a\">b</ll>";
|
||||
data2 = "<ll xmlns=\"urn:tests:a\">b</ll>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, 0));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(NULL, tree2, 0));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, NULL, 0));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<c xmlns=\"urn:tests:a\"><x>x</x></c>";
|
||||
data2 = "<c xmlns=\"urn:tests:a\"><x>y</x></c>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<c xmlns=\"urn:tests:a\"><x>x</x></c>";
|
||||
data2 = "<c xmlns=\"urn:tests:a\"><x>x</x><x>y</x></c>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<any xmlns=\"urn:tests:a\"><x>x</x></any>";
|
||||
data2 = "<any xmlns=\"urn:tests:a\"><x>x</x><x>y</x></any>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1->next, tree2->next, 0));
|
||||
lyd_free_all(tree1);
|
||||
data1 = "<any xmlns=\"urn:tests:a\"><x>x</x><x>y</x></any>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data1 = "<c xmlns=\"urn:tests:a\"><x>c</x><x>a</x><x>b</x></c>";
|
||||
data2 = "<c xmlns=\"urn:tests:a\"><x>a</x><x>b</x><x>c</x></c>";
|
||||
CHECK_PARSE_LYD(data1, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
CHECK_PARSE_LYD(data2, 0, LYD_VALIDATE_PRESENT, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_compare_diff_ctx(void **state)
|
||||
{
|
||||
struct lyd_node *tree1, *tree2;
|
||||
const char *data1, *data2;
|
||||
struct ly_ctx *ctx2 = NULL;
|
||||
const char *module;
|
||||
|
||||
/* create second context with the same schema */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;}}"
|
||||
"}}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, 0, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, 0, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with schema that has a different name */
|
||||
module = "module c {namespace urn:tests:c;prefix c;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;}}"
|
||||
"}}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:c\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, 0, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, 0, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with schema that has a different revision */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2015-05-08;"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;}}"
|
||||
"}}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, 0, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, 0, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with schema that has no revision */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"list l2 {config false;"
|
||||
" container c{leaf x {type string;}}"
|
||||
"}}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, 0, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, 0, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with schema that has a different parent nodetype */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"container l2 {config false;"
|
||||
" container c{leaf x {type string;}}"
|
||||
"}}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
data2 = "<l2 xmlns=\"urn:tests:b\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, 0, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, 0, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(lyd_child(lyd_child(tree1)), lyd_child(lyd_child(tree2)), 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with the same opaq data nodes */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"anydata any {config false;}"
|
||||
"}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<any xmlns=\"urn:tests:b\" xmlns:aa=\"urn:tests:b\"><x>aa:x</x></any>";
|
||||
data2 = "<any xmlns=\"urn:tests:b\" xmlns:bb=\"urn:tests:b\"><x>bb:x</x></any>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, LYD_PARSE_ONLY, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, LYD_PARSE_ONLY, tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with the different opaq data node value */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"anydata any {config false;}"
|
||||
"}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<any xmlns=\"urn:tests:b\" xmlns:aa=\"urn:tests:b\"><x>aa:x</x></any>";
|
||||
data2 = "<any xmlns=\"urn:tests:b\" xmlns:bb=\"urn:tests:b\"><x>bb:y</x></any>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, LYD_PARSE_ONLY, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, LYD_PARSE_ONLY, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* recreate second context with the wrong prefix in opaq data node value */
|
||||
module = "module b {namespace urn:tests:b;prefix b;yang-version 1.1;"
|
||||
"revision 2014-05-08;"
|
||||
"anydata any {config false;}"
|
||||
"}";
|
||||
RECREATE_CTX_WITH_MODULE(ctx2, module);
|
||||
data1 = "<any xmlns=\"urn:tests:b\" xmlns:aa=\"urn:tests:b\"><x>aa:x</x></any>";
|
||||
data2 = "<any xmlns=\"urn:tests:b\" xmlns:bb=\"urn:tests:b\"><x>cc:x</x></any>";
|
||||
CHECK_PARSE_LYD_PARAM_CTX(UTEST_LYCTX, data1, LYD_PARSE_ONLY, tree1);
|
||||
CHECK_PARSE_LYD_PARAM_CTX(ctx2, data2, LYD_PARSE_ONLY, tree2);
|
||||
assert_int_equal(LY_ENOT, lyd_compare_single(tree1, tree2, 0));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* clean up */
|
||||
ly_ctx_destroy(ctx2);
|
||||
_UC->in = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_dup(void **state)
|
||||
{
|
||||
struct lyd_node *tree1, *tree2;
|
||||
const char *result;
|
||||
const char *data;
|
||||
|
||||
data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>x</c></l1>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1, NULL, LYD_DUP_RECURSIVE, &tree2));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>x</c></l1>";
|
||||
result = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b></l1>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1, NULL, 0, &tree2));
|
||||
lyd_free_all(tree1);
|
||||
CHECK_PARSE_LYD(result, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<l2 xmlns=\"urn:tests:a\"><c><x>a</x></c></l2><l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
result = "<l2 xmlns=\"urn:tests:a\"><c><x>a</x></c></l2>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_siblings(tree1, NULL, LYD_DUP_RECURSIVE, &tree2));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next, tree2->next, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree2);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1->next, NULL, LYD_DUP_RECURSIVE, &tree2));
|
||||
lyd_free_all(tree1);
|
||||
CHECK_PARSE_LYD(result, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree2);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1->next, NULL, 0, &tree2));
|
||||
lyd_free_all(tree1);
|
||||
result = "<l2 xmlns=\"urn:tests:a\"/>";
|
||||
CHECK_PARSE_LYD_PARAM(result, LYD_XML, LYD_PARSE_ONLY, 0, LY_SUCCESS, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<any xmlns=\"urn:tests:a\"><c><a>a</a></c></any>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1, NULL, 0, &tree2));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(lyd_child(lyd_child(tree1->next)), NULL, LYD_DUP_WITH_PARENTS, &tree2));
|
||||
int unsigned flag = LYS_CONFIG_R | LYS_SET_ENUM;
|
||||
|
||||
CHECK_LYSC_NODE(tree2->schema, NULL, 0, flag, 1, "x", 1, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next, (struct lyd_node *)tree2->parent->parent,
|
||||
LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>c</c></l1>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(((struct lyd_node_inner *)tree1)->child->prev, NULL,
|
||||
LYD_DUP_WITH_PARENTS, &tree2));
|
||||
flag = LYS_CONFIG_W | LYS_SET_ENUM;
|
||||
CHECK_LYSC_NODE(tree2->schema, NULL, 0, flag, 1, "c", 0, LYS_LEAF, 1, 0, NULL, 0);
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1, (struct lyd_node *)tree2->parent, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
data = "<l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(tree1->next, NULL, 0, &tree2));
|
||||
assert_int_equal(LY_SUCCESS, lyd_dup_single(lyd_child(lyd_child(tree1->next)), (struct lyd_node_inner *)tree2,
|
||||
LYD_DUP_WITH_PARENTS, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lyd_compare_single(tree1->next, tree2, LYD_COMPARE_FULL_RECURSION));
|
||||
lyd_free_all(tree1);
|
||||
lyd_free_all(tree2);
|
||||
|
||||
/* invalid */
|
||||
data = "<l1 xmlns=\"urn:tests:a\"><a>a</a><b>b</b><c>c</c></l1><l2 xmlns=\"urn:tests:a\"><c><x>b</x></c></l2>";
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree1);
|
||||
assert_int_equal(LY_EINVAL, lyd_dup_single(((struct lyd_node_inner *)tree1)->child->prev,
|
||||
(struct lyd_node_inner *)tree1->next, LYD_DUP_WITH_PARENTS, NULL));
|
||||
CHECK_LOG_CTX("None of the duplicated node \"c\" schema parents match the provided parent \"c\".", NULL, 0);
|
||||
lyd_free_all(tree1);
|
||||
}
|
||||
|
||||
static void
|
||||
test_target(void **state)
|
||||
{
|
||||
const struct lyd_node_term *term;
|
||||
struct lyd_node *tree;
|
||||
struct lyxp_expr *exp;
|
||||
struct ly_path *path;
|
||||
const char *path_str = "/a:l2[2]/c/d[3]";
|
||||
const char *data =
|
||||
"<l2 xmlns=\"urn:tests:a\"><c>"
|
||||
" <d>a</d>"
|
||||
" </c></l2>"
|
||||
"<l2 xmlns=\"urn:tests:a\"><c>"
|
||||
" <d>a</d>"
|
||||
" <d>b</d>"
|
||||
" <d>b</d>"
|
||||
" <d>c</d>"
|
||||
"</c></l2>"
|
||||
"<l2 xmlns=\"urn:tests:a\"><c>"
|
||||
"</c></l2>";
|
||||
|
||||
CHECK_PARSE_LYD(data, 0, LYD_VALIDATE_PRESENT, tree);
|
||||
assert_int_equal(LY_SUCCESS, ly_path_parse(UTEST_LYCTX, NULL, path_str, strlen(path_str), 0, LY_PATH_BEGIN_EITHER,
|
||||
LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_SIMPLE, &exp));
|
||||
assert_int_equal(LY_SUCCESS, ly_path_compile(UTEST_LYCTX, NULL, NULL, NULL, exp, LY_PATH_OPER_INPUT,
|
||||
LY_PATH_TARGET_SINGLE, 1, LY_VALUE_JSON, NULL, &path));
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_target(path, tree, (struct lyd_node **)&term));
|
||||
|
||||
const int unsigned flag = LYS_CONFIG_R | LYS_SET_ENUM | LYS_ORDBY_USER;
|
||||
|
||||
CHECK_LYSC_NODE(term->schema, NULL, 0, flag, 1, "d", 0, LYS_LEAFLIST, 1, 0, NULL, 0);
|
||||
assert_string_equal(lyd_get_value(&term->node), "b");
|
||||
assert_string_equal(lyd_get_value(term->prev), "b");
|
||||
|
||||
lyd_free_all(tree);
|
||||
ly_path_free(UTEST_LYCTX, path);
|
||||
lyxp_expr_free(UTEST_LYCTX, exp);
|
||||
}
|
||||
|
||||
static void
|
||||
test_list_pos(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
|
||||
data = "<bar xmlns=\"urn:tests:a\">test</bar>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>one</a><b>one</b></l1>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>two</a><b>two</b></l1>"
|
||||
"<foo xmlns=\"urn:tests:a\">test</foo>";
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
assert_int_equal(0, lyd_list_pos(tree));
|
||||
assert_int_equal(1, lyd_list_pos(tree->next));
|
||||
assert_int_equal(2, lyd_list_pos(tree->next->next));
|
||||
assert_int_equal(0, lyd_list_pos(tree->next->next->next));
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<ll xmlns=\"urn:tests:a\">one</ll>"
|
||||
"<ll xmlns=\"urn:tests:a\">two</ll>"
|
||||
"<ll xmlns=\"urn:tests:a\">three</ll>";
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
assert_int_equal(1, lyd_list_pos(tree));
|
||||
assert_int_equal(2, lyd_list_pos(tree->next));
|
||||
assert_int_equal(3, lyd_list_pos(tree->next->next));
|
||||
lyd_free_all(tree);
|
||||
|
||||
data = "<ll xmlns=\"urn:tests:a\">one</ll>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>one</a><b>one</b></l1>"
|
||||
"<ll xmlns=\"urn:tests:a\">two</ll>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>two</a><b>two</b></l1>"
|
||||
"<ll xmlns=\"urn:tests:a\">three</ll>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>three</a><b>three</b></l1>";
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
assert_string_equal("l1", tree->schema->name);
|
||||
assert_int_equal(1, lyd_list_pos(tree));
|
||||
assert_int_equal(2, lyd_list_pos(tree->next));
|
||||
assert_int_equal(3, lyd_list_pos(tree->next->next));
|
||||
assert_string_equal("ll", tree->next->next->next->schema->name);
|
||||
assert_int_equal(1, lyd_list_pos(tree->next->next->next));
|
||||
assert_int_equal(2, lyd_list_pos(tree->next->next->next->next));
|
||||
assert_int_equal(3, lyd_list_pos(tree->next->next->next->next->next));
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_first_sibling(void **state)
|
||||
{
|
||||
const char *data;
|
||||
struct lyd_node *tree;
|
||||
struct lyd_node_inner *parent;
|
||||
|
||||
data = "<bar xmlns=\"urn:tests:a\">test</bar>"
|
||||
"<l1 xmlns=\"urn:tests:a\"><a>one</a><b>one</b><c>one</c></l1>"
|
||||
"<foo xmlns=\"urn:tests:a\">test</foo>";
|
||||
assert_int_equal(LY_SUCCESS, lyd_parse_data_mem(UTEST_LYCTX, data, LYD_XML, 0, LYD_VALIDATE_PRESENT, &tree));
|
||||
assert_ptr_equal(tree, lyd_first_sibling(tree->next));
|
||||
assert_ptr_equal(tree, lyd_first_sibling(tree));
|
||||
assert_ptr_equal(tree, lyd_first_sibling(tree->prev));
|
||||
parent = (struct lyd_node_inner *)tree->next;
|
||||
assert_int_equal(LYS_LIST, parent->schema->nodetype);
|
||||
assert_ptr_equal(parent->child, lyd_first_sibling(parent->child->next));
|
||||
assert_ptr_equal(parent->child, lyd_first_sibling(parent->child));
|
||||
assert_ptr_equal(parent->child, lyd_first_sibling(parent->child->prev));
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_find_path(void **state)
|
||||
{
|
||||
struct lyd_node *root;
|
||||
const struct lys_module *mod;
|
||||
|
||||
mod = ly_ctx_get_module_implemented(UTEST_LYCTX, "c");
|
||||
assert_non_null(mod);
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_inner(NULL, mod, "cont", 0, &root));
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(root, NULL, "/c:cont/nexthop[gateway='10.0.0.1']", NULL, LYD_NEW_PATH_UPDATE, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(root, NULL, "/c:cont/nexthop[gateway='2100::1']", NULL, LYD_NEW_PATH_UPDATE, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lyd_new_path(root, NULL, "/c:cont/pref[.='fc00::/64']", NULL, 0, NULL));
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "/c:cont/nexthop[gateway='10.0.0.1']", 0, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "/c:cont/nexthop[gateway='2100::1']", 0, NULL));
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "/c:cont/pref[.='fc00::/64']", 0, NULL));
|
||||
|
||||
assert_int_equal(LY_EVALID, lyd_find_path(root, "/cont", 0, NULL));
|
||||
CHECK_LOG_CTX("Prefix missing for \"cont\" in path.", "/c:cont", 0);
|
||||
assert_int_equal(LY_SUCCESS, lyd_find_path(root, "nexthop[gateway='2100::1']", 0, NULL));
|
||||
|
||||
lyd_free_all(root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_hash(void **state)
|
||||
{
|
||||
struct lyd_node *tree;
|
||||
const char *schema, *data;
|
||||
|
||||
schema =
|
||||
"module test-data-hash {"
|
||||
" yang-version 1.1;"
|
||||
" namespace \"urn:tests:tdh\";"
|
||||
" prefix t;"
|
||||
" container c {"
|
||||
" leaf-list ll {"
|
||||
" type string;"
|
||||
" }"
|
||||
" }"
|
||||
"}";
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
/* The number of <ll/> must be greater or equal to LYD_HT_MIN_ITEMS
|
||||
* for the correct test run. It should guarantee the creation of a hash table.
|
||||
*/
|
||||
assert_true(LYD_HT_MIN_ITEMS <= 4);
|
||||
data =
|
||||
"<c xmlns='urn:tests:tdh'>"
|
||||
" <ll/>"
|
||||
" <ll/>"
|
||||
" <ll/>"
|
||||
" <ll/>"
|
||||
"</c>";
|
||||
|
||||
/* The run must not crash due to the assert that checks the hash. */
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_XML, 0, LYD_VALIDATE_PRESENT, LY_EVALID, tree);
|
||||
CHECK_LOG_CTX("Duplicate instance of \"ll\".", "/test-data-hash:c/ll[.='']", 1);
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_lyxp_vars(void **UNUSED(state))
|
||||
{
|
||||
struct lyxp_var *vars;
|
||||
|
||||
/* Test free. */
|
||||
vars = NULL;
|
||||
lyxp_vars_free(vars);
|
||||
|
||||
/* Bad arguments for lyxp_vars_add(). */
|
||||
assert_int_equal(LY_EINVAL, lyxp_vars_set(NULL, "var1", "val1"));
|
||||
assert_int_equal(LY_EINVAL, lyxp_vars_set(&vars, NULL, "val1"));
|
||||
assert_int_equal(LY_EINVAL, lyxp_vars_set(&vars, "var1", NULL));
|
||||
lyxp_vars_free(vars);
|
||||
vars = NULL;
|
||||
|
||||
/* Add one item. */
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "val1"));
|
||||
assert_int_equal(LY_ARRAY_COUNT(vars), 1);
|
||||
assert_string_equal(vars[0].name, "var1");
|
||||
assert_string_equal(vars[0].value, "val1");
|
||||
lyxp_vars_free(vars);
|
||||
vars = NULL;
|
||||
|
||||
/* Add three items. */
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "val1"));
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var2", "val2"));
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var3", "val3"));
|
||||
assert_int_equal(LY_ARRAY_COUNT(vars), 3);
|
||||
assert_string_equal(vars[0].name, "var1");
|
||||
assert_string_equal(vars[0].value, "val1");
|
||||
assert_string_equal(vars[1].name, "var2");
|
||||
assert_string_equal(vars[1].value, "val2");
|
||||
assert_string_equal(vars[2].name, "var3");
|
||||
assert_string_equal(vars[2].value, "val3");
|
||||
lyxp_vars_free(vars);
|
||||
vars = NULL;
|
||||
|
||||
/* Change value of a variable. */
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "val1"));
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var2", "val2"));
|
||||
assert_int_equal(LY_SUCCESS, lyxp_vars_set(&vars, "var1", "new_value"));
|
||||
assert_string_equal(vars[0].name, "var1");
|
||||
assert_string_equal(vars[0].value, "new_value");
|
||||
assert_string_equal(vars[1].name, "var2");
|
||||
assert_string_equal(vars[1].value, "val2");
|
||||
lyxp_vars_free(vars);
|
||||
vars = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_leafref_nodes(void **state)
|
||||
{
|
||||
struct lyd_node *tree, *iter;
|
||||
struct lyd_node_term *target_node = NULL, *leafref_node;
|
||||
const struct lyd_leafref_links_rec *rec;
|
||||
const char *schema, *data, *value;
|
||||
|
||||
ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_LINKING);
|
||||
|
||||
schema =
|
||||
"module test-data-hash {"
|
||||
" yang-version 1.1;"
|
||||
" namespace \"urn:tests:tdh\";"
|
||||
" prefix t;"
|
||||
" leaf-list ll {"
|
||||
" type string;"
|
||||
" }"
|
||||
" container c1 {"
|
||||
" leaf ref1 {"
|
||||
" type leafref {"
|
||||
" path \"../../ll\";"
|
||||
" }"
|
||||
" }"
|
||||
" }"
|
||||
" leaf ref2 {"
|
||||
" type leafref {"
|
||||
" path \"../ll\";"
|
||||
" }"
|
||||
" }"
|
||||
"}";
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
data =
|
||||
"{"
|
||||
" \"test-data-hash:ll\": [\"qwe\", \"asd\"],"
|
||||
" \"test-data-hash:c1\": { \"ref1\": \"qwe\"},"
|
||||
" \"test-data-hash:ref2\": \"asd\""
|
||||
"}";
|
||||
|
||||
/* The run must not crash due to the assert that checks the hash. */
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
LY_LIST_FOR(tree, iter) {
|
||||
if (strcmp(iter->schema->name, "ll") == 0) {
|
||||
value = lyd_get_value(iter);
|
||||
if (strcmp(value, "asd") == 0) {
|
||||
target_node = (struct lyd_node_term *)iter;
|
||||
}
|
||||
}
|
||||
if (strcmp(iter->schema->name, "ref2") == 0) {
|
||||
leafref_node = (struct lyd_node_term *)iter;
|
||||
}
|
||||
}
|
||||
|
||||
/* verify state after leafref plugin validation */
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
assert_ptr_equal(rec->target_nodes[0], target_node);
|
||||
/* value modification of target */
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)target_node, "ASD"));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
|
||||
/* change back to original value */
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)target_node, "asd"));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
|
||||
/* linking the whole tree again */
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_link_node_tree(tree));
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
assert_ptr_equal(rec->target_nodes[0], target_node);
|
||||
/* value modification of leafref */
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)leafref_node, "qwe"));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)leafref_node, "asd"));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
|
||||
/* linking the whole tree again */
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_link_node_tree(tree));
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
assert_ptr_equal(rec->target_nodes[0], target_node);
|
||||
/* freeing whole tree */
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_leafref_nodes2(void **state)
|
||||
{
|
||||
struct lyd_node *tree, *iter;
|
||||
const char *schema, *data;
|
||||
struct lyd_node_term *leafref_node = NULL;
|
||||
const struct lyd_node_term *target_node1, *target_node2;
|
||||
const struct lyd_leafref_links_rec *rec;
|
||||
|
||||
ly_ctx_set_options(UTEST_LYCTX, LY_CTX_LEAFREF_LINKING);
|
||||
|
||||
schema =
|
||||
"module test-data-hash {"
|
||||
" yang-version 1.1;"
|
||||
" namespace \"urn:tests:tdh\";"
|
||||
" prefix t;"
|
||||
" list l1 {"
|
||||
" key \"l1 l2\";"
|
||||
" leaf l1 {"
|
||||
" type string;"
|
||||
" }"
|
||||
" leaf l2 {"
|
||||
" type string;"
|
||||
" }"
|
||||
" }"
|
||||
" leaf ref1 {"
|
||||
" type leafref {"
|
||||
" path \"../l1/l1\";"
|
||||
" }"
|
||||
" }"
|
||||
" leaf-list ll1 {"
|
||||
" type string;"
|
||||
" config false;"
|
||||
" }"
|
||||
" leaf ref2 {"
|
||||
" type leafref {"
|
||||
" path \"../ll1\";"
|
||||
" }"
|
||||
" config false;"
|
||||
" }"
|
||||
"}";
|
||||
|
||||
UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
|
||||
|
||||
data =
|
||||
"{"
|
||||
" \"test-data-hash:l1\": ["
|
||||
" {\"l1\": \"A\", \"l2\": \"B\"},"
|
||||
" {\"l1\": \"A\", \"l2\": \"C\"}"
|
||||
" ],"
|
||||
" \"test-data-hash:ref1\": \"A\","
|
||||
" \"test-data-hash:ll1\": [\"asd\", \"qwe\", \"asd\"],"
|
||||
" \"test-data-hash:ref2\": \"asd\""
|
||||
"}";
|
||||
|
||||
/* The run must not crash due to the assert that checks the hash. */
|
||||
CHECK_PARSE_LYD_PARAM(data, LYD_JSON, 0, LYD_VALIDATE_PRESENT, LY_SUCCESS, tree);
|
||||
LY_LIST_FOR(tree, iter) {
|
||||
if (strcmp(iter->schema->name, "ref1") == 0) {
|
||||
leafref_node = (struct lyd_node_term *)iter;
|
||||
}
|
||||
}
|
||||
|
||||
/* verify state after leafref plugin validation */
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(2, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
target_node1 = rec->target_nodes[0];
|
||||
target_node2 = rec->target_nodes[1];
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node1, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node2, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
/* value modification of leafref to remove all links*/
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)leafref_node, "qwe"));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node1, &rec));
|
||||
assert_int_equal(LY_ENOTFOUND, lyd_leafref_get_links(target_node2, &rec));
|
||||
/* linking the whole tree again */
|
||||
assert_int_equal(LY_SUCCESS, lyd_change_term((struct lyd_node *)leafref_node, "A"));
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_link_node_tree(tree));
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(2, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node1, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node2, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
|
||||
/* verify duplicated value in leaf-list */
|
||||
LY_LIST_FOR(tree, iter) {
|
||||
if (strcmp(iter->schema->name, "ref2") == 0) {
|
||||
leafref_node = (struct lyd_node_term *)iter;
|
||||
}
|
||||
}
|
||||
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(leafref_node, &rec));
|
||||
assert_int_equal(2, LY_ARRAY_COUNT(rec->target_nodes));
|
||||
target_node1 = rec->target_nodes[0];
|
||||
target_node2 = rec->target_nodes[1];
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node1, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
assert_int_equal(LY_SUCCESS, lyd_leafref_get_links(target_node2, &rec));
|
||||
assert_int_equal(1, LY_ARRAY_COUNT(rec->leafref_nodes));
|
||||
assert_ptr_equal(rec->leafref_nodes[0], leafref_node);
|
||||
/* freeing whole tree */
|
||||
lyd_free_all(tree);
|
||||
}
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
const struct CMUnitTest tests[] = {
|
||||
UTEST(test_compare, setup),
|
||||
UTEST(test_compare_diff_ctx, setup),
|
||||
UTEST(test_dup, setup),
|
||||
UTEST(test_target, setup),
|
||||
UTEST(test_list_pos, setup),
|
||||
UTEST(test_first_sibling, setup),
|
||||
UTEST(test_find_path, setup),
|
||||
UTEST(test_data_hash, setup),
|
||||
UTEST(test_lyxp_vars),
|
||||
UTEST(test_data_leafref_nodes),
|
||||
UTEST(test_data_leafref_nodes2),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
1638
tests/utests/data/test_tree_data_sorted.c
Normal file
1638
tests/utests/data/test_tree_data_sorted.c
Normal file
File diff suppressed because it is too large
Load diff
1541
tests/utests/data/test_validation.c
Normal file
1541
tests/utests/data/test_validation.c
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue